如何使用Groupby()。Sum()创建新列?
有两种方法-一种简单明了,另一种更有趣。
每个人都喜欢的:GroupBy.transform()
与'sum'
@Ed Chum的答案可以简化一点。致电DataFrame.groupby
而不是Series.groupby
。这样可以简化语法。
df[['Date', 'Data3']]
Date Data3
0 2015-05-08 5
1 2015-05-07 8
2 2015-05-06 6
3 2015-05-05 1
4 2015-05-08 50
5 2015-05-07 100
6 2015-05-06 60
7 2015-05-05 120
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
快一点
df2 = pd.concat([df] * 12345)
%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')
10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
非常规,但值得您考虑:GroupBy.sum()
+Series.map()
我偶然发现了API中的一个有趣的特质。据我所知,您可以在0.20以上的任何主要版本上重现它(我在0.23和0.24上进行了测试)。transform
如果您改为使用的直接功能GroupBy
并使用进行广播,则似乎可以始终节省几毫秒的时间map
:
df.Date.map(df.groupby('Date')['Data3'].sum())
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Date, dtype: int64
与之比较
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
我的测试表明,map
有点更快,如果你能负担得起使用直接GroupBy
函数(如mean
,min
,max
,first
,等)。在大多数情况下,大约20万条记录或多或少会更快。在那之后,性能实际上取决于数据。
(左:v0.23,右:v0.24)
更好的选择,如果您的框架较小且组数较少,则更好。。。但我建议您将其transform
作为首选。认为这还是值得分享的。
基准测试代码,以供参考:
import perfplot
perfplot.show(
setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}),
kernels=[
lambda df: df.groupby('A')['B'].transform('sum'),
lambda df: df.A.map(df.groupby('A')['B'].sum()),
],
labels=['GroupBy.transform', 'GroupBy.sum + map'],
n_range=[2**k for k in range(5, 20)],
xlabel='N',
logy=True,
logx=True
)