按ID分组重采样月度数据并计算滚动求和的技术问题
嘿,我来帮你搞定这个问题!结合你的大数据场景需求和预期输出,咱们一步步来实现:
步骤1:整理并排序原始数据
首先得把数据按id分组,并且每个id下的日期按降序排列(这样才能计算“最近4个季度行”的和,也就是最新的4条数据),同时把val转成数值类型方便计算:
import pandas as pd # 你的原始数据 df1 = pd.DataFrame({ 'id': ['SE0000195570','SE0000195570','SE0000195570','SE0000195570','SE0000191827','SE0000191827','SE0000191827','SE0000191827', 'SE0000191827'], 'val': ['1','2','3','4','5','6','7','8', '9'], 'date': pd.to_datetime(['2014-10-23','2014-07-16','2014-04-29','2014-01-31','2018-10-19','2018-07-11','2018-04-20','2018-02-16','2018-12-29']) }) # 按id升序、date降序排序,确保每个id的最新数据在前 df_sorted = df1.sort_values(['id', 'date'], ascending=[True, False]).reset_index(drop=True) # 将val转为整数类型 df_sorted['val'] = df_sorted['val'].astype(int)
步骤2:计算每个季度行的滚动4值之和
对每个id分组后,用rolling计算最近4个季度行的val之和,min_periods=4保证只有当至少有4个数据时才计算,否则返回NaN:
df_sorted['calc'] = df_sorted.groupby('id')['val'].rolling(window=4, min_periods=4).sum().reset_index(drop=True)
这一步处理后,SE0000191827最早的那条季度行(2018-02-16)的calc正好是8+7+6+5=26,完全符合你的预期!
步骤3:生成每个id的完整月度序列
为了覆盖每个id首尾日期范围内的所有月度,我们用groupby+date_range生成完整的月度月末日期序列(避免循环,提升大数据处理效率):
# 生成每个id的首尾日期,再生成期间的所有月度月末 date_ranges = df_sorted.groupby('id').agg( start_date=('date', 'min'), end_date=('date', 'max') ).assign( month_end=lambda x: x.apply(lambda row: pd.date_range(row['start_date'], row['end_date'], freq='M'), axis=1) ).explode('month_end').reset_index() # 提取需要的列 monthly_df = date_ranges[['id', 'month_end']]
步骤4:将滚动和映射到月度行
用merge_asof把月度序列和带有calc的季度数据匹配,确保每个月度行取到最近的不晚于该月的季度行的calc值:
# 将原始数据的日期转为月度月末,方便匹配 df_sorted['month_end'] = df_sorted['date'].dt.to_period('M').dt.end_time # 确保两个数据集都按id和month_end排序(merge_asof要求) df_sorted_matched = df_sorted.sort_values(['id', 'month_end']) monthly_df_sorted = monthly_df.sort_values(['id', 'month_end']) # 执行匹配,direction='backward'表示取最近的不晚于当前月度的季度行 result = pd.merge_asof( monthly_df_sorted, df_sorted_matched[['id', 'month_end', 'calc']], on='month_end', by='id', direction='backward' )
最终结果示例
你查看result时,SE0000191827的2018-02-28行的calc就是26,而那些不足4个季度行的月度行(比如SE0000195570的前3个月度行)的calc会是NaN,完全符合你的需求!
性能说明
整个流程全用pandas的矢量化操作,没有循环,groupby、rolling、merge_asof都是pandas针对大数据优化过的方法,完全能适配10万+唯一id、1200万行的场景。
内容的提问来源于stack exchange,提问作者Jokab
相关产品推荐
相关产品推荐

