含缺失值的多级分组滚动平均计算:缺失行补0方案求助
问题解答
关于多级索引上采样的问题
是的,直接通过resample('1M', level=0)对包含datetime的多级索引做上采样是不被支持的——resample要求索引必须是单一的datetime类型索引,或者你先将datetime列设为唯一索引后再操作,不能直接指定多级索引中的某一层来做上采样。
可行解决方案(支持任意分组数量)
核心思路是先为每个分组补全所有缺失的月度行并将N填充为0,再基于补全后的完整数据计算滚动平均,确保边界位置无法计算的结果为np.nan。
步骤1:确保日期列格式正确
首先确认month列是datetime类型,如果是字符串格式先转换:
import pandas as pd import numpy as np # 转换month列为datetime(根据实际格式调整format参数) df['month'] = pd.to_datetime(df['month'], format='%Y-%m')
步骤2:补全每个分组的缺失月度数据
生成每个分组的完整月度时间序列,将缺失月份的N填充为0:
# 获取全局时间范围(从数据最早到最晚的月份) all_months = pd.date_range(start=df['month'].min(), end=df['month'].max(), freq='M') # 为每个分组生成完整的月度索引,并合并原始数据 full_df = ( df.groupby(['from', 'to', 'subset']) .apply(lambda g: g.set_index('month').reindex(all_months, fill_value=0).reset_index()) .rename(columns={'index': 'month'}) .reset_index(drop=True) )
这里用groupby.apply为每个分组单独补全缺失月份,reindex自动填充N为0,适合任意数量的分组列。
步骤3:计算3期中心滚动平均
在补全后的数据集上,按分组计算滚动平均,设置min_periods=3确保只有凑够3期(包括补的0)才返回有效值,边界位置自动为np.nan:
# 计算滚动平均并添加到结果中 full_df['rolling_avg'] = full_df.groupby(['from', 'to', 'subset'])['N'].transform( lambda x: x.rolling(window=3, center=True, min_periods=3).mean() )
替代方案:用透视表简化操作
如果分组列较多,也可以用透视表生成宽表后计算滚动平均,再转回长格式:
# 生成月度-分组的透视表,缺失值填充为0 pivot_df = df.pivot_table( index='month', columns=['from', 'to', 'subset'], values='N', fill_value=0 ) # 对每个分组列计算滚动平均 rolling_result = pivot_df.rolling(window=3, center=True, min_periods=3).mean() # 转回长格式,得到最终结果 final_df = rolling_result.unstack().reset_index().rename(columns={0: 'rolling_avg'}) # 可选:合并原始N值 final_df = final_df.merge(full_df[['month', 'from', 'to', 'subset', 'N']], on=['month', 'from', 'to', 'subset'], how='left')
结果说明
- 所有原本缺失的月度行已被补全,
N值为0 - 滚动平均仅在有完整3期数据的位置计算,首尾两个月(边界)的
rolling_avg为np.nan - 方案支持任意数量的分组列,只需修改
groupby或columns中的分组字段即可
内容的提问来源于stack exchange,提问作者FooBar
相关产品推荐
相关产品推荐

