如何在Pandas中实现最小观测期大于滚动窗口的滚动平均?
解决方案
要解决min_periods大于窗口导致的报错,同时满足累计x个有效非零观测后才生成滚动平均值的需求,可以通过以下高效的矢量化操作实现(避免循环,适配大数据量):
核心思路
- 先对每个分组计算累计有效非零观测数,确认何时满足"累计x个有效数据"的条件;
- 正常计算指定窗口的滚动平均值;
- 过滤掉累计有效数不足x的行,仅保留符合条件的滚动结果。
可复用函数
def rolling_mean_min_cum_valid(df, window, min_cum_valid, group_col='NAME', value_col='SIZE'): # 按分组计算累计有效非零观测数 cum_valid = df.groupby(group_col)[value_col].transform(lambda s: s.ne(0).cumsum()) # 计算指定窗口的滚动平均(min_periods设为1,确保窗口内有有效数据就计算) rolling_avg = df.groupby(group_col)[value_col].rolling(window, min_periods=1).mean() # 仅保留累计有效数达标后的结果,其余设为NaN return rolling_avg.where(cum_valid >= min_cum_valid)
调用示例
x = 400 # 处理各个DataFrame df1_rolling = rolling_mean_min_cum_valid(df1, window=100, min_cum_valid=x) df2_rolling = rolling_mean_min_cum_valid(df2, window=300, min_cum_valid=x) df3_rolling = rolling_mean_min_cum_valid(df3, window=700, min_cum_valid=x) df4_rolling = rolling_mean_min_cum_valid(df4, window=1000, min_cum_valid=x)
注意事项
- 如果你的"有效观测"指的是非NaN值而非"非零值",只需将函数中的
s.ne(0)替换为s.notna()即可; - 该方案完全使用pandas内置的矢量化操作,底层基于优化过的C实现,处理大数据量时效率远高于自定义循环;
- 原代码报错的原因是pandas的
rolling函数强制要求min_periods ≤ window(窗口内最多只能有window个观测,无法满足比窗口更大的最小观测数要求),本方案通过先累计全局有效数再过滤的方式绕开了这个限制。
内容的提问来源于stack exchange,提问作者StormsEdge
相关产品推荐
相关产品推荐

