2016-01-26 35 views
5

Tôi có một khung dữ liệu mà tôi đang tìm cách nhóm và sau đó phân chia các giá trị trong một nhóm thành nhiều cột.Pandas groupby kết quả thành nhiều cột

Ví dụ: nói rằng tôi có dataframe sau:

>>> import pandas as pd 
>>> import numpy as np 
>>> df=pd.DataFrame() 
>>> df['Group']=['A','C','B','A','C','C'] 
>>> df['ID']=[1,2,3,4,5,6] 
>>> df['Value']=np.random.randint(1,100,6) 
>>> df 
    Group ID Value 
0  A 1  66 
1  C 2  2 
2  B 3  98 
3  A 4  90 
4  C 5  85 
5  C 6  38 
>>> 

Tôi muốn groupby "Tập đoàn" lĩnh vực, lấy tổng của các trường "Value", và nhận được các lĩnh vực mới, mỗi trong số đó nắm giữ các giá trị ID của nhóm.

Hiện nay tôi có thể làm điều này như sau, nhưng tôi đang tìm kiếm một phương pháp làm sạch:

Trước tiên, tôi tạo ra một dataframe với một danh sách các ID trong mỗi nhóm.

>>> g=df.groupby('Group') 
>>> result=g.agg({'Value':np.sum, 'ID':lambda x:x.tolist()}) 
>>> result 
       ID Value 
Group     
A   [1, 4]  98 
B   [3]  76 
C  [2, 5, 6] 204 
>>> 

Và sau đó tôi sử dụng pd.Series để chia thành các cột, đổi tên chúng và sau đó nối lại.

>>> id_df=result.ID.apply(lambda x:pd.Series(x)) 
>>> id_cols=['ID'+str(x) for x in range(1,len(id_df.columns)+1)] 
>>> id_df.columns=id_cols 
>>> 
>>> result.join(id_df)[id_cols+['Value']] 
     ID1 ID2 ID3 Value 
Group      
A  1 4 NaN  98 
B  3 NaN NaN  76 
C  2 5 6 204 
>>> 

Có cách nào để thực hiện việc này mà không phải tạo danh sách các giá trị không?

Trả lời

8

Bạn có thể sử dụng

id_df = grouped['ID'].apply(lambda x: pd.Series(x.values)).unstack() 

để tạo id_df mà không có sự trung gian result DataFrame.


import pandas as pd 
import numpy as np 
np.random.seed(2016) 

df = pd.DataFrame({'Group': ['A', 'C', 'B', 'A', 'C', 'C'], 
        'ID': [1, 2, 3, 4, 5, 6], 
        'Value': np.random.randint(1, 100, 6)}) 

grouped = df.groupby('Group') 
values = grouped['Value'].agg('sum') 
id_df = grouped['ID'].apply(lambda x: pd.Series(x.values)).unstack() 
id_df = id_df.rename(columns={i: 'ID{}'.format(i + 1) for i in range(len(id_df))}) 
result = pd.concat([id_df, values], axis=1) 
print(result) 

sản lượng

 ID1 ID2 ID3 Value 
Group      
A  1 4 NaN  77 
B  3 NaN NaN  84 
C  2 5 6  86 
0

Sử dụng get_dummies và MultiLabelBinarizer (scikit-học):

import pandas as pd 
import numpy as np 
from sklearn import preprocessing 
df = pd.DataFrame() 
df['Group']=['A','C','B','A','C','C'] 
df['ID']=[1,2,3,4,5,6] 
df['Value']=np.random.randint(1,100,6) 

mlb = preprocessing.MultiLabelBinarizer(classes=classes).fit([]) 

df2 = pd.get_dummies(df, '', '', columns=['ID']).groupby(by='Group').sum() 
df3 = pd.DataFrame(mlb.inverse_transform(df2[df['ID'].unique()].values), index=df2.index) 
df3.columns = ['ID' + str(x + 1) for x in range(df3.shape[0])] 
pd.concat([df3, df2['Value']], axis=1) 


     ID1 ID2 ID3 Value 
Group      
A  1 4 NaN  63 
B  3 NaN NaN  59 
C  2 5 6 230 
Các vấn đề liên quan