2017-08-22 39 views
3

我有這樣換位和彙總數據幀

name tag time val 
0 ABC A  1 10 
0 ABC A  1 12 
1 ABC B  1 12 
1 ABC B  1 14 
2 ABC A  2 11 
3 ABC C  2 12 
4 DEF B  3 10 
5 DEF C  3 9 
6 GHI A  4 14 
7 GHI B  4 12 
8 GHI C  5 10 

每行一個數據幀是時間戳記,並顯示該行的名稱和標籤之間的值。

我要的是一個數據幀,其中每一行表示在每個時間戳從每個標籤的平均值,像這樣:

name time  A  B  C 
0 ABC  1 11.0 13.0 NaN 
1 ABC  2 11.0 NaN 12.0 
2 DEF  3 NaN 10.0 9.0 
3 GHI  4 14.0 12.0 NaN 
4 GHI  5 NaN NaN 10.0 

我可以通過nametime分組並返回一個換位系列順利實現這一每次:

def transpose_df(observation_df): 
    ser = pd.Series() 
    for tag in tags: 
    ser[tag] = observation_df[observation_df['tag'] == tag]['val'].mean() 
    return ser 


tdf = df.groupby(['name', 'time']).apply(transpose_df).reset_index() 

但是這很慢。我覺得使用內置轉置/重塑工具必須有更聰明的方法,但我無法弄清楚。任何人都可以看到建議更好的選擇?

回答

5

選項1

使用pivot_table

df.pivot_table(values='val',index=['name','time'],columns='tag',aggfunc='mean').reset_index() 

輸出:

tag name time  A  B  C 
0 ABC  1 11.0 13.0 NaN 
1 ABC  2 11.0 NaN 12.0 
2 DEF  3 NaN 10.0 9.0 
3 GHI  4 14.0 12.0 NaN 
4 GHI  5 NaN NaN 10.0 

選項2:

使用groupbyunstack

df.groupby(['name','time','tag']).agg('mean')['val'].unstack().reset_index() 

輸出:

tag name time  A  B  C 
0 ABC  1 11.0 13.0 NaN 
1 ABC  2 11.0 NaN 12.0 
2 DEF  3 NaN 10.0 9.0 
3 GHI  4 14.0 12.0 NaN 
4 GHI  5 NaN NaN 10.0 

選項3

使用​​和meanunstack

df.set_index(['name','time','tag']).mean(level=[0,1,2])['val'].unstack().reset_index() 

輸出:

tag name time  A  B  C 
0 ABC  1 11.0 13.0 NaN 
1 ABC  2 11.0 NaN 12.0 
2 DEF  3 NaN 10.0 9.0 
3 GHI  4 14.0 12.0 NaN 
4 GHI  5 NaN NaN 10.0 
+0

是的,它幫助確實 - 謝謝!所有的答案都很棒,但我提供了幾個選項,我接受了你的答案。 – DaveBensonPhillips

6
In [175]: df.pivot_table(index=['name','time'], columns='tag', values='val').reset_index() 
Out[175]: 
tag name time  A  B  C 
0 ABC  1 11.0 13.0 NaN 
1 ABC  2 11.0 NaN 12.0 
2 DEF  3 NaN 10.0 9.0 
3 GHI  4 14.0 12.0 NaN 
4 GHI  5 NaN NaN 10.0 
4

你也可以groupby然後unpackack(相當於一個數據透視表)。

>>> df.groupby(['name', 'time', 'tag'])['val'].mean().unstack('tag').reset_index() 
tag name time A B C 
0 ABC  1 11 13 NaN 
1 ABC  2 11 NaN 12 
2 DEF  3 NaN 10 9 
3 GHI  4 14 12 NaN 
4 GHI  5 NaN NaN 10 

順便說一句,transform是當你要保持你原有的數據幀,例如形狀

>>> df.assign(tag_mean=df.groupby(['name', 'time', 'tag'])['val'].transform(np.mean)) 
    name tag time val tag_mean 
0 ABC A  1 10  11 
0 ABC A  1 12  11 
1 ABC B  1 12  13 
1 ABC B  1 14  13 
2 ABC A  2 11  11 
3 ABC C  2 12  12 
4 DEF B  3 10  10 
5 DEF C  3 9   9 
6 GHI A  4 14  14 
7 GHI B  4 12  12 
8 GHI C  5 10  10