首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将组件、滚动和多列创建结合在Python中

如何将组件、滚动和多列创建结合在Python中
EN

Stack Overflow用户
提问于 2020-10-11 09:06:43
回答 1查看 284关注 0票数 2

我有一个在R中使用dplyr很容易解决的问题,但是在Python中似乎找不到一种简单的方法。我有一个df,其中id(=customerid)、s(=store)、m(=month)和ttl(=total )作为列。我想在id+s上计算多个新列--例如,最后3个月的购买和最小购买。

示例(最后两列是新列):

代码语言:javascript
复制
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

我试过以下几种方法:

代码语言:javascript
复制
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())

我得到以下错误:

无法访问'DataFrameGroupBy‘对象的可调用属性'assign’,请尝试使用'apply‘方法

我知道不需要赋值就可以解决这个问题,但是接下来我必须为每个新列设置一个行,因为我需要很多这些,所以我正在寻找一个解决办法。

我也研究过pyjanitor的add_columns,但是它似乎不适用于groupby。

在R中,下面的代码解决了这个问题,在变体中,我可以继续添加列:

代码语言:javascript
复制
df = df %>% group_by(id, s) %>% mutate(ttl_3 = runner(ttl, k=3, f=sum), min_id_s = min(ttl))
EN

回答 1

Stack Overflow用户

发布于 2020-10-11 10:03:52

对于python语法和熊猫,逻辑几乎是相同的。

代码语言:javascript
复制
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。

ids分组并计算新列。可以使用rolling方法计算多个agg列。

您可以使用assign,但也必须为每个聚合编写一行。

代码语言:javascript
复制
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

退出:

代码语言:javascript
复制
    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

rolling聚合agg的多列

代码语言:javascript
复制
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)

退出:

代码语言:javascript
复制
    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

使用rolling从多个列聚合多个列,并使用agg。列必须是数字的。据我所知,transform不支持多个聚合。

生成滚动聚合的随机数值列

代码语言:javascript
复制
import numpy as np
df['ttl2'] = np.random.rand(len(df))

没有从多个列聚合的选定列的groupby。例如,使用自定义函数

代码语言:javascript
复制
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

退出:

代码语言:javascript
复制
    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
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64302315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档