熊猫groupby获取总和中的过滤总和

时间:2019-10-30 10:46:56

标签: python pandas pandas-groupby

我有以下数据框:

df = pd.DataFrame([[1, 2, True], [1, 4, False], [2, 6, False], [2, 8, True]], columns=["Group", "Value", "C"])

   Group  Value      C
0      1      2   True
1      1      4  False
2      2      6  False
3      2      8   True

我想让每个小组都知道值的总和,其中C等于值的总和。例如,对于第1组,我们有2 /(2 + 4)

我已经进行了广泛的搜索以达到以下阶段:

df.groupby('Group').agg(lambda x: x.loc[x.C == True, 'Value'].sum() / x.Value.sum())

          Value         C
Group                    
1      0.333333  0.333333
2      0.571429  0.571429

但是(如预期的那样)我得到两列,而我只想得到一列。我理想的结果是:

       Ratio        
Group                    
1      0.333333  
2      0.571429  

我肯定可以在groupby之后进行一些修改并得到我想要的东西,但是由于我是Python的新手,所以我想知道我是否在这里缺少一些基本知识。

3 个答案:

答案 0 :(得分:2)

我相信您可以对groupby.transform()进行除法运算,并在过滤后使用.assign()进行赋值,以便与索引对齐:

df[df['C']].assign(Ratio=df['Value']/df.groupby('Group')['Value'].transform('sum'))

如果每个组的True大于1,请使用:

m=(df.groupby(['Group','C'],as_index=False,sort=False)['Value'].sum()
  .query('C==True').assign(Sum=df.groupby(['Group'])['Value'].transform('sum')))
m[['Group']].assign(Ratio=m['Value']/m['Sum'])

   Group     Ratio
0      1  0.333333
3      2  0.571429

答案 1 :(得分:2)

您可以按过滤后的行除以所有行,然后将Series转换为一列DataFrame

filt = df.loc[df['C']].groupby('Group')['Value'].sum()
tot = df.groupby('Group')['Value'].sum()
df1 = filt.div(tot, fill_value=0).to_frame('ratio')
print (df1)
          ratio
Group          
1      0.333333
2      0.571429

通过更改.agg处理所有列到GroupBy.apply以获得返回值Series,您的解决方案是可能的,但是如果有大数据/许多唯一组,它应该很慢:

df = (df.groupby('Group')
        .apply(lambda x: x.loc[x.C, 'Value'].sum() / x.Value.sum())
        .to_frame('ratio'))
print (df)
          ratio
Group          
1      0.333333
2      0.571429

False组的解决方案也能很好地工作:

df = pd.DataFrame([[0, 2, False], [1, 2, True], [1, 4, False], 
                   [2, 6, False], [2, 8, True]], columns=["Group", "Value", "C"])


df1 = (df.groupby('Group')
        .apply(lambda x: x.loc[x.C, 'Value'].sum() / x.Value.sum())
        .to_frame('ratio'))
print (df1)
          ratio
Group          
0      0.000000
1      0.333333
2      0.571429

filt = df.loc[df['C']].groupby('Group')['Value'].sum()
tot = df.groupby('Group')['Value'].sum()

print (df1)
          ratio
Group          
0      0.000000
1      0.333333
2      0.571429

答案 2 :(得分:1)

您可以使用apply

result = df.groupby('Group').apply(lambda x: pd.Series({'ratio' : (x.Value * x.C).sum() / x.Value.sum()}))
print(result)

输出

          ratio
Group          
1      0.333333
2      0.571429