2017-03-13 5 views
1

最近私はパンダを使い始めたばかりで、この問題は数日間はつまずきました。私はこのようなビット間隔のデータフレームを持っています:パンダ - 連続した間隔で行をマージする

df = pd.DataFrame({'RangeBegin' : [1,3,5,10,12,42,65], 
       'RangeEnd' : [2,4,7,11,41,54,100], 
       'Var1' : ['A','A','A','B','B','B','A'], 
       'Var2' : ['A','A','B','B','B','B','A']}) 

    RangeBegin RangeEnd Var1 Var2 
0   1   2 A A 
1   3   4 A A 
2   5   7 A B 
3   10  11 B B 
4   12  41 B B 
5   42  54 B B 
6   65  100 A A 

RangeBeginでソートされています。連続した範囲を有するすべての(VAR1とVAR2に一致)「重複」行が単一の行に集約され

 RangeBegin RangeEnd Var1 Var2 
0   1.0  4.0 A A 
2   5.0  7.0 A B 
3  10.0  54.0 B B 
6  65.0  100.0 A A 

:アイデアは、代わりにこのようなもので終わるすることです。オーバーラップを検出して処理するためにこのアルゴリズムを拡張することを考えていますが、これを最初に正しく動作させたいと思います。

iterrowsを使用して新しいデータフレームを行単位で作成するソリューションがありますが、実際のデータセットでは時間がかかり過ぎるため、ベクトル化された実装を使用したいと考えています。 私はgroupbyを調べましたが、この作業をするキーのセット(または上記のグループに適用する関数)を見つけることができません。それが立つよう

は、ここに私の現在の実装です:

def test(): 
    df = pd.DataFrame({'RangeBegin' : [1,3,5,10,12,42,65], 
        'RangeEnd' : [2,4,7,11,41,54,100], 
        'Var1' : ['A','A','A','B','B','B','A'], 
        'Var2' : ['A','A','B','B','B','B','A']}) 
    print(df) 

    i = 0 
    cols = df.columns 
    aggData = pd.DataFrame(columns = cols) 
    for row in df.iterrows(): 
     rowIndex, rowData = row 
     #if our new dataframe is empty or its last row is not contiguous, append it 
     if(aggData.empty or not duplicateContiguousRow(cols,rowData,aggData.loc[i])): 
      aggData = aggData.append(rowData) 
      i=rowIndex 
     #otherwise, modify the last row 
     else: 
      aggData.loc[i,'RangeEnd'] = rowData['RangeEnd'] 
    print(aggData) 

def duplicateContiguousRow(cols, row, aggDataRow): 
    #first bool: are the ranges contiguous? 
    contiguousBool = aggDataRow['RangeEnd']+1 == row['RangeBegin'] 
    if(not contiguousBool): 
     return False 

    #second bool: is this row a duplicate (minus range columns)? 
    duplicateBool = True 
    for col in cols: 
     if(not duplicateBool): 
      break 
     elif col not in ['RangeBegin','RangeEnd']: 
      #Nan != Nan 
      duplicateBool = duplicateBool and (row[col] == aggDataRow[col] or (row[col]!=row[col] and aggDataRow[col]!=aggDataRow[col])) 
    return duplicateBool 

EDIT:This question私はこの1つを書いていた間、ちょうど尋ねました。答えは有望

答えて

0

に見える最初consecutive segmentsを検出したときに、この目的のためにgroupbyを使用することができます:あなたはその後、ソートblockによるオリジナルを復元することができ

Var1 Var2 block RangeBegin RangeEnd 
0 A A  1   1   4 
1 A A  4   65  100 
2 A B  2   5   7 
3 B B  3   10  54 

df['block'] = ((df['Var1'].shift(1) != df['Var1']) | (df['Var2'].shift(1) != df['Var2'])).astype(int).cumsum() 
df.groupby(['Var1', 'Var2', 'block']).agg({'RangeBegin': np.min, 'RangeEnd': np.max}).reset_index() 

はになります注文。

+0

偉大な答え、ありがとう!ちょうど1つの質問は、あなたがVar1とVar2だけでなくブロックする理由はありますか?私はブロックだけで同じ結果をグループ化するように見える –

+0

おそらくそれを無視することができます;-)残っているかもしれません。 – languitar

+0

もう一度、ありがとう! –

関連する問題