2016-10-24 79 views
3

我有一個熊貓非數據幀,看起來像:結合的條件數據幀行

INPUT - 這裏的例子可運行代碼來創建輸入:

#Create Dataframe with example data 
df_example = pd.DataFrame(columns=["START_D","ID_1", "ID_2", "STOP_D"]) 
df_example["START_D"] = ['2014-06-16', '2014-06-01', '2016-05-01','2014-05-28', '2014-05-20', '2015-09-01'] 
df_example['ID_1'] = [1,2,3,2,1,1] 
df_example['ID_2'] = ['a', 'a', 'b', 'b', 'a', 'a'] 
df_example["STOP_D"] = ['2014-07-28', '2014-07-01', '2016-06-01', '2014-08-01', '2014-07-29', '2015-10-01'] 

#Convert to datetime 
df_example["START_D"] = pd.to_datetime(df_example["START_D"]) 
df_example["STOP_D"] = pd.to_datetime(df_example["STOP_D"]) 
df_example 

START_D ID_1 ID_2  STOP_D 
0 2014-06-16  1 a 2014-07-28 
1 2014-06-01  2 a 2014-07-01 
2 2016-05-01  3 b 2016-06-01 
3 2014-05-28  2 b 2014-08-01 
4 2014-05-20  1 a 2014-07-29 
5 2015-09-01  1 a 2015-10-01 

和我正在尋找一種方式來按ID_1分組,併合並START_D和STOP_D重疊的行。 start_d最小,stop_d最大。 下面您可以看到所需的輸出,我得到了循環遍歷所有行(iterrows)並在一次檢查一個元素。

OUTPUT 即使這種方法的工作,我認爲它是緩慢的(對於大型DF),我認爲必須有一個更pythonic-pandas的方式來做到這一點。

>>> df_result 
    START_D ID_1  STOP_D 
    0 2014-05-20  1 2014-07-29 
    1 2014-05-28  2 2014-08-01 
    2 2016-05-01  3 2016-06-01 
    3 2015-09-01  1 2015-10-01 

謝謝!

+1

請檢查[如何使重複性好大熊貓的例子(http://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples) – jezrael

回答

1
  • sort_values
  • groupby('ID_1')
  • 軌道STOP_D.cummax(),看看是否START_D小於現有cummax
  • cumsum生成分組
  • agg抓住minSTART_DmaxSTOP_D

df_example = df.sort_values(['START_D', 'STOP_D']) 

def collapse(df): 
    s, e = 'START_D', 'STOP_D' 
    grps = df[s].gt(df[e].cummax().shift()).cumsum() 
    funcs = {s: 'min', e: 'max', 'ID_1': 'first'} 
    return df.groupby(grps).agg(funcs) 

df_example.groupby('ID_1').apply(collapse).reset_index(drop=True) 

enter image description here

0

問題的難點在於聚合需要導致單個條目。因此,如果START_D和STOP_D不重疊,但ID1相同,則不會進行聚合(甚至可以自定義)。我推薦以下步驟:

  1. 循環遍歷每個ID並確保始終發生所需的重疊。這可以通過一些機智的編碼進行矢量化。在發現衝突的情況下,生成一個新的ID(使用ID3這樣的新列)來解決衝突。否則,如果不存在衝突,只需將ID1放入ID3即可。
  2. 使用做一個ID3 GROUPBY(或任何你選擇稱呼它)

    df_result = df_example.groupby(['ID1']).agg({START_D: min, STOP_D: max}) 
    

在性能提升的關鍵是拿出一個量化的解決方案來檢查啓動和停止衝突。祝你好運!希望這可以幫助!