如何在 pct_change 计算中对 pandas DataFrame 中的多列进行分组

Posted

技术标签:

【中文标题】如何在 pct_change 计算中对 pandas DataFrame 中的多列进行分组【英文标题】:How to groupby multiple columns in pandas DataFrame in pct_change calculation 【发布时间】:2014-07-10 12:32:04 【问题描述】:

我正在将 pct_change 计算应用于 pandas 数据框。订购月份列时一切正常。如果不是,则计算结果不正确。

这是我现在的代码:

data = [
('product_a','1/31/2014',53)
,('product_b','1/31/2014',44)
,('product_c','1/31/2014',36)
,('product_a','11/30/2013',52)
,('product_b','11/30/2013',43)
,('product_c','11/30/2013',35)
,('product_a','3/31/2014',50)
,('product_b','3/31/2014',41)
,('product_c','3/31/2014',34)
,('product_a','12/31/2013',50)
,('product_b','12/31/2013',41)
,('product_c','12/31/2013',34)
,('product_a','2/28/2014',52)
,('product_b','2/28/2014',43)
,('product_c','2/28/2014',35)
]

product_df = DataFrame( data, columns=['prod_desc','activity_month','prod_count'] )

for index, row in product_df.iterrows():
  row['activity_month']= datetime.strptime(row['activity_month'],'%m/%d/%Y')
  product_df.loc[index, 'activity_month'] = date.strftime(row['activity_month'],'%Y-%m-%d')

product_df['pct_ch'] = product_df.groupby('prod_desc')['prod_count'].pct_change()

product_df = product_df.sort(['prod_desc','activity_month'])

我得到的回报:

   prod_desc activity_month  prod_count    pct_ch
3      product_a     2013-11-30         52 -0.018868
9      product_a     2013-12-31         50  0.000000
0      product_a     2014-01-31         53       NaN
12     product_a     2014-02-28         52  0.040000
6      product_a     2014-03-31         50 -0.038462
4      product_b     2013-11-30         43 -0.022727
10     product_b     2013-12-31         41  0.000000
1      product_b     2014-01-31         44       NaN
13     product_b     2014-02-28         43  0.048780
7      product_b     2014-03-31         41 -0.046512
5      product_c     2013-11-30         35 -0.027778
11     product_c     2013-12-31         34  0.000000
2      product_c     2014-01-31         36       NaN
14     product_c     2014-02-28         35  0.029412
8      product_c     2014-03-31         34 -0.028571

这里的计算是无序的,因为每个产品第一个月的 pct_change 应该是 NaN。

我认为问题在于 pct_change 计算不包括 groupby 中的“activity_month”。当我尝试添加它时,我得到以下输出。

product_df['pct_ch'] = product_df.groupby(['prod_desc','activity_month'])['prod_count'].pct_change() 

   prod_desc activity_month  prod_count  pct_ch
3      product_a     2013-11-30         52     NaN
9      product_a     2013-12-31         50     NaN
0      product_a     2014-01-31         53     NaN
12     product_a     2014-02-28         52     NaN
6      product_a     2014-03-31         50     NaN
4      product_b     2013-11-30         43     NaN
10     product_b     2013-12-31         41     NaN
1      product_b     2014-01-31         44     NaN
13     product_b     2014-02-28         43     NaN
7      product_b     2014-03-31         41     NaN
5      product_c     2013-11-30         35     NaN
11     product_c     2013-12-31         34     NaN
2      product_c     2014-01-31         36     NaN
14     product_c     2014-02-28         35     NaN
8      product_c     2014-03-31         34     NaN

【问题讨论】:

您是否有理由不只对数据框进行排序? df = df.sort(['prod_desc', 'activity_month']); df.groupby('prod_desc')['prod_count'].pct_change() 一个明显的问题是product_df.groupby('prod_desc','activity_month')。查看groupby 的函数签名。编辑:实际上,这只发生在你最后一次调用它时。两列都需要作为第一个参数传递。 @acushner 是的,这是一个不起作用的例子。作为示例不清楚,因此我将其删除。谢谢。 @TomAugspurger 你是对的,我将排序移到了上面的计算和 activity_month 格式之后,它工作正常。你想添加它作为我愚蠢问题的答案吗? 【参考方案1】:

所以我认为您遇到的问题是 groupby 正在计算相同 prod_desc 的相邻行之间的百分比差异,并且当您执行操作时,这不是按日期顺序排序的,因此将排序移到 groupby 上方将修复那个问题。您还可以删除 for 循环并使用 pandas 将其写为一行。

import pandas as pd 

data = [
('product_a','1/31/2014',53)
,('product_b','1/31/2014',44)
,('product_c','1/31/2014',36)
,('product_a','11/30/2013',52)
,('product_b','11/30/2013',43)
,('product_c','11/30/2013',35)
,('product_a','3/31/2014',50)
,('product_b','3/31/2014',41)
,('product_c','3/31/2014',34)
,('product_a','12/31/2013',50)
,('product_b','12/31/2013',41)
,('product_c','12/31/2013',34)
,('product_a','2/28/2014',52)
,('product_b','2/28/2014',43)
,('product_c','2/28/2014',35)
]

product_df = pd.DataFrame( data, columns=['prod_desc','activity_month','prod_count'])

product_df['activity_month'] = pd.to_datetime(product_df['activity_month'],
 format='%m/%d/%Y')

product_df = product_df.sort_values(['prod_desc','activity_month'])
product_df['pct_ch'] = product_df.groupby('prod_desc')['prod_count'].pct_change()

我认为这应该会产生您想要的答案。

    prod_desc activity_month  prod_count    pct_ch
3   product_a     2013-11-30          52       NaN
9   product_a     2013-12-31          50 -0.038462
0   product_a     2014-01-31          53  0.060000
12  product_a     2014-02-28          52 -0.018868
6   product_a     2014-03-31          50 -0.038462
4   product_b     2013-11-30          43       NaN
10  product_b     2013-12-31          41 -0.046512
1   product_b     2014-01-31          44  0.073171
13  product_b     2014-02-28          43 -0.022727
7   product_b     2014-03-31          41 -0.046512
5   product_c     2013-11-30          35       NaN
11  product_c     2013-12-31          34 -0.028571
2   product_c     2014-01-31          36  0.058824
14  product_c     2014-02-28          35 -0.027778
8   product_c     2014-03-31          34 -0.028571

【讨论】:

以上是关于如何在 pct_change 计算中对 pandas DataFrame 中的多列进行分组的主要内容,如果未能解决你的问题,请参考以下文章

pandas使用pct_change函数计算数据列的百分比变化:计算当前元素和前一个元素之间的百分比变化(包含NaN值的情况以及数据填充方法)

ValueError:无法使用 groupy 从重复轴重新索引并在 Pandas 中应用 pct_change

pandas使用resample函数计算特定疾病按月花费总和pct_change函数计算特定疾病按月花费总和环比变化率并使用matplotlib可视化疾病按月花费总和环比变化率

pandas使用pivot_table函数计算特定疾病总花费在不同医疗服务实体下的跨年度费用环比变化率(pct_change function to compute change rate)

pandas使用pct_change计算数据列的百分比变化环比变化率:计算当前元素和前一个元素之间的百分比变化使用style函数指定format的格式:百分比缺失值替换用颜色标注极大值和极小值

pandas 中的pct_change的用法