首页 > 解决方案 > 如何按,在哪里,总和做一个适当的熊猫组

问题描述

我很难使用 group by + where 将总和应用于更广泛的范围。

鉴于此代码:

from io import StringIO
import numpy as np

f = pd.read_csv(StringIO("""
fund_id,l_s,val
fund1,L,10
fund1,L,20
fund1,S,30
fund2,L,15
fund2,L,25
fund2,L,35
"""))


# fund total - works as expected
f['fund_total'] = f.groupby('fund_id')['val'].transform(np.sum)
# fund L total - applied only to L rows. 
f['fund_total_l'] = f[f['l_s'] == "L"].groupby('fund_id')['val'].transform(np.sum)
f

这段代码让我接近: 在此处输入图像描述

数字是正确的,但我希望fund_total_l列显示30fund1 的所有行(不仅仅是L)。我想要一个基金水平摘要,但总和按l_s列过滤

我知道我可以通过多个步骤来做到这一点,但这需要一个单一的操作。如果有帮助,我可以使用单独的通用函数。

操场:https ://repl.it/repls/UnusualImpeccableDaemons

标签: pandas

解决方案


使用Series.where, 来创建NaN,这些将在您的sum:

f['val_temp'] = f['val'].where(f['l_s'] == "L")
f['fund_total_l'] = f.groupby('fund_id')['val_temp'].transform('sum')
f = f.drop(columns='val_temp')

或在一行中使用assign

df['fun_total_l'] = (
    f.assign(val_temp=f['val'].where(f['l_s'] == "L"))
    .groupby('fund_id')['val_temp'].transform('sum')
)

另一种方法是部分使用您的解决方案,然后使用DataFrame.reindex来获取原始索引,然后使用ffillbfill填充我们的NaN

f['fund_total_l'] = (
    f[f['l_s'] == "L"]
    .groupby('fund_id')['val']
    .transform('sum')
    .reindex(f.index)
    .ffill()
    .bfill()
)

  fund_id l_s  val  fund_total_l
0   fund1   L   10          30.0
1   fund1   L   20          30.0
2   fund1   S   30          30.0
3   fund2   L   15          75.0
4   fund2   L   25          75.0
5   fund2   L   35          75.0

推荐阅读