如何为groupby DataFrame创建滚动百分比

5 投票
1 回答
5806 浏览
提问于 2025-04-18 07:03

我正在尝试计算每个产品按月的百分比变化。到目前为止,我已经有了一个只涉及单个产品的数据框的计算方法。但我现在不知道如何将这个计算应用到包含多个产品和多个月份的结果集中。

下面是一个示例数据框:

product_desc    activity_month    prod_count
product_a       1/1/2014          53
product_b       1/1/2014          42
product_c       1/1/2014          38
product_a       2/1/2014          26
product_b       2/1/2014          48
product_c       2/1/2014          39
product_a       3/1/2014          41
product_b       3/1/2014          35
product_c       3/1/2014          50

我需要得到的是一个数据框,里面增加了按产品描述和月份计算的百分比变化:

product_desc    activity_month   prod_count pct_change
product_a       1/1/2014         53 
product_a       2/1/2014         26         0.490566038
product_a       3/1/2014         41         1.576923077
product_b       1/1/2014         42 
product_b       2/1/2014         48         1.142857143
product_b       3/1/2014         35         0.729166667
product_c       1/1/2014         38 
product_c       2/1/2014         39         1.026315789
product_c       3/1/2014         50         1.282051282

我可以用以下方法在一个只包含单个产品描述的数据框上计算这个:

df['change_rate1'] = df['prod_count'].shift(-1)/df['prod_count']
df['pct_change'] = df['change_rate1'].shift(1)
df = df.drop('change_rate1',1)

现在我尝试的是:

df_grouped = df.groupby(['product_desc','activity_month'])

for product_desc, activity_month in df_grouped:
   df['change_rate1'] = df_grouped['prod_count'].shift(-1)/df_grouped['prod_count']

但是,在for语句的最后一行,我得到了一个'NotImplementedError'的错误。

如果有任何建议能让我正确计算这个,我会非常感激。

1 个回答

5

看起来在这些组里面,每个月都有一个数据点,你想要计算每个月之间的百分比变化。你可以通过使用 groupby/apply 来实现,先按照 'product_desc' 进行分组,然后使用内置的 pct_change() 方法:

>>> df['pct_ch'] = df.groupby('product_desc')['prod_count'].pct_change() + 1

注意,我在 pct_change() 方法里加了1,因为它计算的是净百分比变化。我会打印出一个排序后的版本,这样就能和你预期的结果匹配了:

>>> df.sort('product_desc')

  product_desc activity_month  prod_count    pct_ch
0    product_a     2014-01-01          53       NaN
3    product_a     2014-02-01          26  0.490566
6    product_a     2014-03-01          41  1.576923
1    product_b     2014-01-01          42       NaN
4    product_b     2014-02-01          48  1.142857
7    product_b     2014-03-01          35  0.729167
2    product_c     2014-01-01          38       NaN
5    product_c     2014-02-01          39  1.026316
8    product_c     2014-03-01          50  1.282051

在旧版本的 pandas 中,你可能需要这样做:

>>> df['pct_ch'] = df.groupby('product_desc')['prod_count'].apply(lambda x: x.pct_change() + 1)

或者你可以像你建议的那样使用 shift,只需稍作修改:

>>> df['pct_ch'] = df['prod_count'] / df.groupby('product_desc')['prod_count'].shift(1)
>>> df.sort('product_desc')

  product_desc activity_month  prod_count    pct_ch
0    product_a     2014-01-01          53       NaN
3    product_a     2014-02-01          26  0.490566
6    product_a     2014-03-01          41  1.576923
1    product_b     2014-01-01          42       NaN
4    product_b     2014-02-01          48  1.142857
7    product_b     2014-03-01          35  0.729167
2    product_c     2014-01-01          38       NaN
5    product_c     2014-02-01          39  1.026316
8    product_c     2014-03-01          50  1.282051

groupby 中,你不需要引用 df['prod_count'],因为你并没有对那个列做任何操作。

在旧版本的 pandas 中,你可能需要这样做:

>>> df['pct_ch'] = df.groupby('product_desc')['prod_count'].apply(lambda x: x/x.shift(1))

撰写回答