我有一个问题,可以使用 R 中的 dplyr 轻松解决,但似乎无法在 Python 中找到简单的方法。 我有一个 df,其中 id(=customerid)、s(=store)、m(=month) 和 ttl(=total buy) 作为列。 我想计算 id+s 上的多个新列 - 例如最近 3 个月的购买量和最低购买量。
示例(最后两列是新列):
id s m ttl ttl_3 min_id_s
1 A 1/1/2020 7 nan 3
1 A 2/1/2020 3 nan 3
1 A 3/1/2020 7 17 3
1 A 4/1/2020 6 16 3
1 A 5/1/2020 7 20 3
1 A 6/1/2020 7 20 3
1 B 1/1/2020 6 nan 6
1 B 2/1/2020 10 nan 6
1 B 3/1/2020 8 24 6
1 B 4/1/2020 8 26 6
1 B 5/1/2020 10 26 6
1 B 6/1/2020 8 26 6
2 A 1/1/2020 4 nan 1
2 A 2/1/2020 3 15 1
2 A 3/1/2020 10 17 1
2 A 4/1/2020 6 19 1
2 A 5/1/2020 4 20 1
2 A 6/1/2020 1 11 1
我尝试过以下方法:
grp = df.groupby(['id','s'])
df = df.assign(ttl_3 = grp['ttl'].apply(lambda x: x.rolling(window=3)).sum(), min_id_s = grp['ttl'].min())
我收到以下错误:
Cannot access callable attribute 'assign' of 'DataFrameGroupBy' objects, try using the 'apply' method
我知道它可以在不分配的情况下解决,但随后我必须为每个新列添加一行,并且由于我需要大量这样的行,所以我正在寻找解决方法。
我还使用 pyjanitor 研究了 add_columns,但它似乎不适用于 groupby。
在 R 中,以下代码解决了该问题,并且在 mutate 中我可以继续添加列:
df = df %>% group_by(id, s) %>% mutate(ttl_3 = runner(ttl, k=3, f=sum), min_id_s = min(ttl))
最佳答案
Python 语法和 pandas 的逻辑几乎相同
t = '''
id s m ttl
1 A 1/1/2020 7
1 A 2/1/2020 3
1 A 3/1/2020 7
1 A 4/1/2020 6
1 A 5/1/2020 7
1 A 6/1/2020 7
1 B 1/1/2020 6
1 B 2/1/2020 10
1 B 3/1/2020 8
1 B 4/1/2020 8
1 B 5/1/2020 10
1 B 6/1/2020 8
2 A 1/1/2020 4
2 A 2/1/2020 3
2 A 3/1/2020 10
2 A 4/1/2020 6
2 A 5/1/2020 4
2 A 6/1/2020 1 '''
import pandas as pd
import io
df = pd.read_csv(io.StringIO(t), sep='\s+')
尝试尽可能接近 dplyr。
按 id
和 s
分组并计算新列。可以使用 agg
方法计算多个滚动
列。
您可以使用分配
,但您还必须为每个聚合编写一行。
group = df.groupby(['id','s'])['ttl']
df['ttl_3'] = group.rolling(3).sum().reset_index(level=(0,1), drop=True)
df['min_id_s'] = group.transform('min')
#df = df.assign(
# ttl_3 = group.rolling(3).sum().reset_index(level=(0,1), drop=True),
# min_id_s = group.transform('min'))
df
输出:
id s m ttl ttl_3 min_id_s
0 1 A 1/1/2020 7 NaN 3
1 1 A 2/1/2020 3 NaN 3
2 1 A 3/1/2020 7 17.0 3
3 1 A 4/1/2020 6 16.0 3
4 1 A 5/1/2020 7 20.0 3
5 1 A 6/1/2020 7 20.0 3
6 1 B 1/1/2020 6 NaN 6
7 1 B 2/1/2020 10 NaN 6
8 1 B 3/1/2020 8 24.0 6
9 1 B 4/1/2020 8 26.0 6
10 1 B 5/1/2020 10 26.0 6
11 1 B 6/1/2020 8 26.0 6
12 2 A 1/1/2020 4 NaN 1
13 2 A 2/1/2020 3 NaN 1
14 2 A 3/1/2020 10 17.0 1
15 2 A 4/1/2020 6 19.0 1
16 2 A 5/1/2020 4 20.0 1
17 2 A 6/1/2020 1 11.0 1
使用agg
聚合多列以进行滚动
group = df.groupby(['id','s'])['ttl']
df[['ttl_3_sum','ttl_3_mean']] = group.rolling(3).agg(['sum','mean']).reset_index(level=(0,1), drop=True)
输出:
id s m ttl ttl_3_sum ttl_3_mean
0 1 A 1/1/2020 7 NaN NaN
1 1 A 2/1/2020 3 NaN NaN
2 1 A 3/1/2020 7 17.0 5.666667
3 1 A 4/1/2020 6 16.0 5.333333
4 1 A 5/1/2020 7 20.0 6.666667
5 1 A 6/1/2020 7 20.0 6.666667
6 1 B 1/1/2020 6 NaN NaN
7 1 B 2/1/2020 10 NaN NaN
8 1 B 3/1/2020 8 24.0 8.000000
9 1 B 4/1/2020 8 26.0 8.666667
10 1 B 5/1/2020 10 26.0 8.666667
11 1 B 6/1/2020 8 26.0 8.666667
12 2 A 1/1/2020 4 NaN NaN
13 2 A 2/1/2020 3 NaN NaN
14 2 A 3/1/2020 10 17.0 5.666667
15 2 A 4/1/2020 6 19.0 6.333333
16 2 A 5/1/2020 4 20.0 6.666667
17 2 A 6/1/2020 1 11.0 3.666667
使用agg
从多个列聚合多个列以进行滚动
。列必须是数字。据我所知,transform
不支持多重聚合。
为滚动聚合生成随机数值列
import numpy as np
df['ttl2'] = np.random.rand(len(df))
groupby
没有选择要从多列聚合的列。例如使用自定义函数
group = df.groupby(['id','s'])
df[['ttl_3_sum', 'ttl2_lambda']] = (group.rolling(3)
.agg({'ttl':'sum', 'ttl2': lambda x: x.sum()/x.min()})
.reset_index(level=(0,1), drop=True))
df
输出:
id s m ttl ttl2 ttl_3_sum ttl2_lambda
0 1 A 1/1/2020 7 0.032482 NaN NaN
1 1 A 2/1/2020 3 0.998115 NaN NaN
2 1 A 3/1/2020 7 0.689431 17.0 52.953016
3 1 A 4/1/2020 6 0.897444 16.0 3.749456
4 1 A 5/1/2020 7 0.484360 20.0 4.276231
5 1 A 6/1/2020 7 0.971768 20.0 4.859138
6 1 B 1/1/2020 6 0.238363 NaN NaN
7 1 B 2/1/2020 10 0.740311 NaN NaN
8 1 B 3/1/2020 8 0.641598 24.0 6.797507
9 1 B 4/1/2020 8 0.984911 26.0 3.688945
10 1 B 5/1/2020 10 0.043379 26.0 38.495141
11 1 B 6/1/2020 8 0.700253 26.0 39.847293
12 2 A 1/1/2020 4 0.437082 NaN NaN
13 2 A 2/1/2020 3 0.465313 NaN NaN
14 2 A 3/1/2020 10 0.698976 17.0 3.663777
15 2 A 4/1/2020 6 0.430087 19.0 3.707103
16 2 A 5/1/2020 4 0.949536 20.0 4.832976
17 2 A 6/1/2020 1 0.904986 11.0 5.311974
关于python - 如何在Python中结合groupby、rolling和多列创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64302315/