如何在Pandas中按组计算月份差值并获取月度频次
问题
给定如下Pandas DataFrame:
import pandas as pd data = pd.DataFrame([['1001','2020-03-06'], ['1001','2020-04-06'], ['1002','2021-04-02'], ['1003','2022-07-08'], ['1001','2020-09-06'], ['1003','2022-04-04'], ['1002','2021-06-05'], ['1007','2020-09-08'], ['1002','2021-12-07'], ['1003','2022-12-06'], ['1007','2020-02-10'], ], columns=['Type', 'Date'])
需要按Type分组,计算每组内每个日期对应的月度频次数值(即该日期到组内下一个较晚日期的月份差值,最后一个日期差值为0),期望输出如下:
pd.DataFrame([['1007','2020-09-08', 0], ['1007','2020-02-10', 7], ['1003','2022-12-06', 0], ['1003','2022-07-08', 5], ['1003','2022-04-04', 3], ['1002','2021-12-07', 0], ['1002','2021-06-05', 6], ['1002','2021-04-02', 2], ['1001','2020-09-06', 0], ['1001','2020-04-06', 5], ['1001','2020-03-06', 1], ], columns=['Type', 'Date', 'MonthlyFreq'])
当前尝试的代码未得到期望结果:
data['Date'] = pd.to_datetime(data['Date']) data['diff'] = data.groupby(['Type'])['Date'].apply(lambda x:(x.max() - x)/np.timedelta64(1, 'M')) data['diff'] = data['diff'].astype(int) data = data.sort_values('Type')
解决方案
你的代码计算的是每个日期与组内最大日期的月份差,但需求是每个日期到下一个最近的较晚日期的月份差。可以通过以下步骤实现:
- 转换日期为datetime类型,按
Type分组后对每组内日期降序排序; - 使用
shift(-1)获取下一行的日期,计算两者的月份差值; - 填充最后一行的空值为0并转为整数,最后调整排序匹配期望输出。
完整代码:
import pandas as pd import numpy as np # 初始化数据 data = pd.DataFrame([['1001','2020-03-06'], ['1001','2020-04-06'], ['1002','2021-04-02'], ['1003','2022-07-08'], ['1001','2020-09-06'], ['1003','2022-04-04'], ['1002','2021-06-05'], ['1007','2020-09-08'], ['1002','2021-12-07'], ['1003','2022-12-06'], ['1007','2020-02-10'], ], columns=['Type', 'Date']) # 转换日期格式 data['Date'] = pd.to_datetime(data['Date']) # 定义分组计算逻辑 def compute_monthly_freq(group): # 组内按日期降序排列 group_sorted = group.sort_values('Date', ascending=False).reset_index(drop=True) # 计算当前日期与下一个日期的月份差 group_sorted['MonthlyFreq'] = (group_sorted['Date'].shift(-1) - group_sorted['Date']) / np.timedelta64(1, 'M') # 最后一行差值设为0,转为整数 group_sorted['MonthlyFreq'] = group_sorted['MonthlyFreq'].fillna(0).astype(int) return group_sorted # 应用分组计算 result = data.groupby('Type', group_keys=False).apply(compute_monthly_freq) # 按Type降序、Date降序排序,匹配期望输出顺序 result = result.sort_values(['Type', 'Date'], ascending=[False, False]) # 可选:将日期转回字符串格式 result['Date'] = result['Date'].dt.strftime('%Y-%m-%d') print(result)
运行后输出与期望一致:
Type Date MonthlyFreq 7 1007 2020-09-08 0 10 1007 2020-02-10 7 9 1003 2022-12-06 0 3 1003 2022-07-08 5 5 1003 2022-04-04 3 8 1002 2021-12-07 0 6 1002 2021-06-05 6 2 1002 2021-04-02 2 4 1001 2020-09-06 0 1 1001 2020-04-06 5 0 1001 2020-03-06 1
内容的提问来源于stack exchange,提问作者Hussain Madarwala
相关产品推荐
相关产品推荐

