如何在DataFrame中的groupby中递增行计数

23

我需要计算pandas DataFrame中每个产品的activity_months数量。这是目前我的数据和代码:

from pandas import DataFrame
from datetime import datetime
data = [
('product_a','08/31/2013')
,('product_b','08/31/2013')
,('product_c','08/31/2013')
,('product_a','09/30/2013')
,('product_b','09/30/2013')
,('product_c','09/30/2013')
,('product_a','10/31/2013')
,('product_b','10/31/2013')
,('product_c','10/31/2013')
]

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

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

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

product_df['month_num'] = product_df.groupby(['prod_desc']).size()

然而,这会返回月份数的NaN值。

这是我想要得到的:

prod_desc    activity_month   month_num 
product_a       2014-08-31         1 
product_a       2014-09-30         2         
product_a       2014-10-31         3         
product_b       2014-08-31         1 
product_b       2014-09-30         2         
product_b       2014-10-31         3         
product_c       2014-08-31         1 
product_c       2014-09-30         2         
product_c       2014-10-31         3     

在Python中,当迭代时修改值是不可取的(虽然在单个dtype情况下iter rows会返回一个视图,但通常是个坏主意);始终返回一个新框架(或复制并修改副本)。 - Jeff
使用 pd.to_datetime() 一次性转换所有日期。 - Jeff
我还不清楚你想要实现什么:month_num是否只是等于activity_month中的月份?你的最终目标是什么? - ojdo
@ojdo 说得好。我会编辑示例以使其更清晰。我想要计算活动月数。这与月份无关。如果一个产品有5个活动月,我需要在该组内将行计数从1到5。我将添加逻辑来分别计算第一个月、第二个月等等…… - analyticsPierce
1个回答

33

使用groupby是正确的想法,但正确的方法是cumcount

>>> product_df['month_num'] = product_df.groupby('product_desc').cumcount()
>>> product_df

  product_desc activity_month  prod_count    pct_ch  month_num
0    product_a     2014-01-01          53       NaN          0
3    product_a     2014-02-01          52 -0.018868          1
6    product_a     2014-03-01          50 -0.038462          2
1    product_b     2014-01-01          44       NaN          0
4    product_b     2014-02-01          43 -0.022727          1
7    product_b     2014-03-01          41 -0.046512          2
2    product_c     2014-01-01          36       NaN          0
5    product_c     2014-02-01          35 -0.027778          1
8    product_c     2014-03-01          34 -0.028571          2

如果你真的想让它以1开头,那么只需这样做:

>>> product_df['month_num'] = product_df.groupby('product_desc').cumcount() + 1

  product_desc activity_month  prod_count    pct_ch  month_num
0    product_a     2014-01-01          53       NaN          1
3    product_a     2014-02-01          52 -0.018868          2
6    product_a     2014-03-01          50 -0.038462          3
1    product_b     2014-01-01          44       NaN          1
4    product_b     2014-02-01          43 -0.022727          2
7    product_b     2014-03-01          41 -0.046512          3
2    product_c     2014-01-01          36       NaN          1
5    product_c     2014-02-01          35 -0.027778          2
8    product_c     2014-03-01          34 -0.028571          3

完美!谢谢。 - igorkf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接