2015-12-30 88 views
1

我有一個數據幀如下:蟒大熊貓GROUPBY多個組與二進制類

id class 
A 1 
B 1 
C 0 
D 0 
E 1 
F 1 

欲組成3組,G1:A,B,G2:C,d,G3:E, F。 有沒有辦法這樣做循環所有行爲每個ID分配一個新的類?

+0

你能後所需的輸出,所以我們可以理解你的問題好? –

回答

0

您可以使用diffastypecumsum

print df 
    id class 
0 A  0 
1 B  1 
2 B1  1 
3 C  0 
4 D  0 
5 E  1 
6 F  1 
7 F1  1 
8 G  0 
9 H  0 
10 I  1 
11 J  1 

df['count'] = (df['class'].diff(1) != 0).astype('int').cumsum() 
print df 

    id class count 
0 A  0  1 
1 B  1  2 
2 B1  1  2 
3 C  0  3 
4 D  0  3 
5 E  1  4 
6 F  1  4 
7 F1  1  4 
8 G  0  5 
9 H  0  5 
10 I  1  6 
11 J  1  6 

for name, group in df.groupby('count'): 
    print name 
    print group[['id', 'class']] 

性能測試:

這些時間都將是非常依賴的DF的大小以及數量(和位置) 01):

import pandas as pd 

df = pd.DataFrame({'id': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], 'class': [0, 1, 1, 0, 0, 1, 1, 1, 0, 0]}, columns=['id', 'class']) 

#uncomment for test len(df) = 1000 
#df = pd.concat([df]*1000).reset_index(drop=True) 

def jez(df): 
    df['count'] = (df['class'].diff(1) != 0).astype('int').cumsum() 
    return df 

def eze(df): 
    group_index = [0] 
    for i in df.index[1:]: 
     if df['class'][i]==df['class'][i-1]: 
      group_index.append(group_index[-1]) 
     else: 
      group_index.append(group_index[-1]+1) 

    df['group_index'] = group_index   
    return df 

def sy2(df): 
    df = pd.concat([df, pd.Series(map(lambda x: 1 if abs(x) > 0 else 0, df['class'].diff().fillna(0)), name='groupid').cumsum()], axis=1) 
    return df 

print jez(df) 
print eze(df) 
print sy2(df) 

測試len(df) = 10

In [28]: %timeit jez(df) 
The slowest run took 5.08 times longer than the fastest. This could mean that an intermediate result is being cached 
1000 loops, best of 3: 454 µs per loop 

In [29]: %timeit eze(df) 
The slowest run took 4.83 times longer than the fastest. This could mean that an intermediate result is being cached 
1000 loops, best of 3: 422 µs per loop 

In [30]: %timeit sy2(df) 
The slowest run took 4.57 times longer than the fastest. This could mean that an intermediate result is being cached 
1000 loops, best of 3: 1.46 ms per loop 

測試len(df) = 10000

In [32]: %timeit jez(df) 
The slowest run took 4.78 times longer than the fastest. This could mean that an intermediate result is being cached 
1000 loops, best of 3: 543 µs per loop 

In [33]: %timeit eze(df) 
1 loops, best of 3: 245 ms per loop 

In [34]: %timeit sy2(df) 
The slowest run took 4.11 times longer than the fastest. This could mean that an intermediate result is being cached 
100 loops, best of 3: 9.11 ms per loop 
0

迭代通過「類」,每類是不一樣的前一個時間開始一個新的羣體,對於例如:

克里特島DF:

import pandas as pd 
df = pd.DataFrame() 
df['id'] = ['a','b','c','d','e','f'] 
df['class'] = [1,1,0,0,1,1] 

遍歷'class'創建組索引:

group_index = [0] 
for i in df.index[1:]: 
    if df['class'][i]==df['class'][i-1]: 
     group_index.append(group_index[-1]) 
    else: 
     group_index.append(group_index[-1]+1) 

的GROUP_INDEX添加到DF:

df['group_index'] = group_index 

和輸出應爲:

id class group_index 
    0 a  1  0 
    1 b  1  0 
    2 c  0  1 
    3 d  0  1 
    4 e  1  2 
    5 f  1  2 

0

這裏是一個單行的代碼。 :p 它利用相鄰行的差異信息和累積和來爲每行分配組標識。

>>> df = pd.DataFrame({'id': ['A','B','C','D','E','F'], 
         'class': [1, 1, 0, 0, 1, 1]}, 
         columns=['id', 'class']) 

>>> pd.concat([df, pd.Series(map(lambda x: 1 if abs(x) > 0 else 0, 
df['class'].diff().fillna(0)), name='groupid').cumsum()], axis=1) 

    id class groupid 
0 A  1  0 
1 B  1  0 
2 C  0  1 
3 D  0  1 
4 E  1  2 
5 F  1  2 

現在,您可以使用groupby()獲取groupy對象。

>>> g = pd.concat([df, pd.Series(map(lambda x: 1 if abs(x) > 0 else 0, 
df['class'].diff().fillna(0)), name='groupid').cumsum()], axis=1).groupby('groupid') 

>>> for index, group_df in g: 
     print(group_df) 

    id class groupid 
0 A  1  0 
1 B  1  0 
    id class groupid 
2 C  0  1 
3 D  0  1 
    id class groupid 
4 E  1  2 
5 F  1  2 

完整的代碼已附上。

import pandas as pd 

def groupby_binaryflag(df, key='class'): 
    return pd.concat([df, 
         pd.Series(map(lambda x: 1 
            if abs(x) > 0 
            else 0, df['class'].diff().fillna(0)), 
           name='groupid').cumsum()], axis=1).groupby('groupid') 

if __name__ == '__main__': 
    df1 = pd.DataFrame({'id': ['A','B','C','D','E','F'], 
         'class': [1, 1, 0, 0, 1, 1]}, columns=['id', 'class']) 

    df2 = pd.DataFrame({'id': ['A','B','C','D','E','F', 'G', 'H', 'I', 'J', 'K', 'L'], 
         'class': [1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1]}, columns=['id', 'class']) 

    for df in [df1, df2]: 
     for index, group_df in groupby_binaryflag(df): 
      print(group_df) 
     print("=====\n") 

輸出:

id class groupid 
0 A  1  0 
1 B  1  0 
    id class groupid 
2 C  0  1 
3 D  0  1 
    id class groupid 
4 E  1  2 
5 F  1  2 
===== 

    id class groupid 
0 A  1  0 
1 B  1  0 
    id class groupid 
2 C  0  1 
3 D  0  1 
    id class groupid 
4 E  1  2 
5 F  1  2 
    id class groupid 
6 G  0  3 
7 H  0  3 
8 I  0  3 
    id class groupid 
9 J  1  4 
10 K  1  4 
11 L  1  4 
=====