2017-03-01 147 views
2

我有一個數據幀,看起來是這樣的:熊貓GROUPBY彙總到新列

A B C D 
1 10 22 14 
1 12 20 37 
1 11 8 18 
1 10 10 6 
2 11 13 4 
2 12 10 12 
3 14 0 5 

而且看起來是這樣的(注意的功能:它實際上是做一些更復雜,不能輕易分隔成三個獨立的電話,但我簡化爲清楚起見):

def myfunc(g): 
    return min(g), mean(g), max(g) 

我想在A使用groupbymyfunc獲得對列輸出和C(忽略D)是這樣的:

   B    C 
    min mean max min mean max 
A 
1 10 10.75 12  8 15.0 22 
2 11 11.50 12 10 11.5 13 
3 14 14.00 14  0 0.0 0 

我可以做到以下幾點:

df2.groupby('A')[['B','C']].agg(
    { 
     'min': lambda g: myfunc(g)[0], 
     'mean': lambda g: myfunc(g)[1], 
     'max': lambda g: myfunc(g)[2] 
    }) 

但隨後預留這是醜陋的,並呼籲myfunc多次,我結束了

max  mean  min 
    B C  B  C B C 
A 
1 12 22 10.75 15.0 10 8 
2 12 13 11.50 11.5 11 10 
3 14 0 14.00 0.0 14 0 

我可以使用.swaplevel(axis=1)交換列級別,但即使如此BC是在多個重複的列中,並且使用多個函數調用時,感覺就像吠叫錯誤的樹。

回答

4

如果您安排myfunc返回一個數據幀的列是['A','B','C','D'],其行的索引是['min', 'mean', 'max'],那麼你可以使用groupby/apply調用的函數(一次爲每個組)並連接結果期望:

import numpy as np 
import pandas as pd 

def myfunc(g): 
    result = pd.DataFrame({'min':np.min(g), 
          'mean':np.mean(g), 
          'max':np.max(g)}).T 
    return result 

df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 3], 
'B': [10, 12, 11, 10, 11, 12, 14], 
'C': [22, 20, 8, 10, 13, 10, 0], 
'D': [14, 37, 18, 6, 4, 12, 5]}) 

result = df.groupby('A')[['B','C']].apply(myfunc) 
result = result.unstack(level=-1) 
print(result) 

打印

 B     C    
    max mean min max mean min 
A          
1 12.0 10.75 10.0 22.0 15.0 8.0 
2 12.0 11.50 11.0 13.0 11.5 10.0 
3 14.0 14.00 14.0 0.0 0.0 0.0 

對於其他人誰可能跨越此運行,誰不需要一個自定義功能,注意 ,如果可能的話,您應始終使用builtin aggregators(以下由 字符串'min','mean''max'指定)。它們的性能優於 自定義Python函數。令人高興的是,在這個玩具問題中,它產生了期望的結果:

In [99]: df.groupby('A')[['B','C']].agg(['min','mean','max']) 
Out[99]: 
    B    C   
    min mean max min mean max 
A        
1 10 10.75 12 8 15.0 22 
2 11 11.50 12 10 11.5 13 
3 14 14.00 14 0 0.0 0 
-1

這樣的事情可能會奏效。

df2.groupby('A')[['B','C']] 
aggregated = df2.agg(['min', 'mean', 'max']) 

,那麼你可以使用交換級來獲得列的順序換各地

aggregated.columns = aggregated.columns.swaplevel(0, 1) 
aggregated.sortlevel(0, axis=1, inplace=True) 
+0

注意:它實際上是做一些更復雜,不容易被分隔成三個獨立的電話,但我簡化清晰 – Dan