2016-01-24 109 views
2

所以我们可以说我有一些数据如下:熊猫:聚合不同的基于组

patient_id lab_type value 
1   food  10 
1   food  8 
2   food  3 
2   food  5 
1   shot  4 
1   shot  10 
2   shot  2 
2   shot  4 

然后我会组的东西,如groupby(['patient_id', 'lab_type'])

在那之后,我想聚集在value但每个lab_type都不相同。在food我想使用meanshot进行汇总,我想使用sum进行汇总。

最终的数据应该是这样的:

patient_id lab_type value 
    1   food  9 (10 + 8/2) 
    2   food  4 (3 + 5/2) 
    1   shot  14 (10 + 4) 
    2   shot  6 (2 + 4) 
+0

只写一个函数检查其输入的'lab_type',并根据它的内容做不同的事情,然后''应用'那个函数给groupby。 – BrenBarn

回答

1

关于食物我想聚合使用均值和在射击我想汇总使用总和。

只需使用.apply并传递一个自定义函数:

def calc(g): 
    if g.iloc[0].lab_type == 'shot': 
     return sum(g.value) 
    else: 
     return np.mean(g.value) 
result = df.groupby(['patient_id', 'lab_type']).apply(calc) 

这里calc接收作为在Panda's split-apply-combine所示的每个数据帧组。因此,你得到你想要的东西:

patient_id lab_type 
1   food   9 
      shot  14 
2   food   4 
      shot   6 
dtype: float64 
+0

你的答案似乎是最简洁的,但是,你能解释一下在这种情况下g是指什么,你需要返回什么? – adrian

+0

'calc'每个组被调用一次,'g'是指组中的数据(实际上是一个DataFrame)。返回的值是您应用的任何操作的结果,在这种情况下,它是计算的统计量。本质上,熊猫自动连接所有结果。 – miraculixx

0

答案在this post看起来很有希望。从这开始,我想出了下面的代码,它应该适合你。

TESTDATA:

data = [{"A" : 1, "B" : "food", "C" : 10}, 
{"A" : 1, "B" : "food", "C" : 8}, 
{"A" : 2, "B" : "food", "C" : 3}, 
{"A" : 2, "B" : "food", "C" : 5}, 
{"A" : 1, "B" : "shot", "C" : 4}, 
{"A" : 1, "B" : "shot", "C" : 10}, 
{"A" : 2, "B" : "shot", "C" : 2}, 
{"A" : 2, "B" : "shot", "C" : 4}]  
df = pd.DataFrame(data) 

实际代码:

res = df.groupby(['A', 'B']).apply(
    lambda x: pd.Series(
    {"value" : x.C.mean() if x.iloc[0].B == "food" else x.C.sum()} 
) 
) 

这导致

 value 
A B   
1 food  9 
    shot  14 
2 food  4 
    shot  6 
0

P是你的数据帧。

P[P.lab_type =="food"].groupby(['patient_id']).aggregate(np.avg) 

和类似地对于shot组和concatenate结果。

1

我尝试修改john答案:

您可以使用meansum然后concatreset_index

print df 
    patient_id lab_type value 
0   1  food  10 
1   1  food  8 
2   2  food  3 
3   2  food  5 
4   1  shot  4 
5   1  shot  10 
6   2  shot  2 
7   2  shot  4 


df1 = df[df.lab_type =="food"].groupby(['patient_id']).mean() 
df1['lab_type'] = 'food' 
print df1 
      value lab_type 
patient_id     
1    9  food 
2    4  food 

df2 = df[df.lab_type =="shot"].groupby(['patient_id']).sum() 
df2['lab_type'] = 'shot' 
print df2 
      value lab_type 
patient_id     
1    14  shot 
2    6  shot 

print pd.concat([df1, df2]).reset_index() 
    patient_id value lab_type 
0   1  9  food 
1   2  4  food 
2   1  14  shot 
3   2  6  shot 
+0

这是一个可靠的答案,但与米拉的答案相比略显冗长。 – adrian

+0

是的,你是对的。 – jezrael