如何按时间分组用滚动均值填充Pandas DataFrame缺失值?
按时间分组用滚动均值填充Pandas缺失值
问题描述
现有带datetime字段的Pandas DataFrame,需按time(提取自datetime的时分部分)分组,用缺失值前后行的滚动均值填充NaN。尝试的代码无法正常运行:
import pandas as pd import numpy as np df = pd.DataFrame({'datetime':['2023-04-20 13:00', '2023-04-21 13:00','2023-04-22 13:00', '2023-04-23 13:00','2023-04-21 14:00', '2023-04-22 14:00', '2023-04-23 14:00'], 'var':[1, 2, np.nan, 3, np.nan, 4, 5]}) df = df.assign(datetime=pd.to_datetime(df.datetime)) df = df.assign(time=df['datetime'].dt.time) # 无法正常运行的代码 df.assign(var=df.groupby('time', sort=False).var.apply(lambda col: col.fillna(col.rolling(window=2, center=2).mean())))
当前数据
datetime var 0 2023-04-20 13:00 1.0 1 2023-04-21 13:00 2.0 2 2023-04-22 13:00 NaN 3 2023-04-23 13:00 3.0 4 2023-04-21 14:00 NaN 5 2023-04-22 14:00 4.0 6 2023-04-23 14:00 5.0
期望结果
datetime var 0 2023-04-20 13:00 1.0 1 2023-04-21 13:00 2.0 2 2023-04-22 13:00 2.5 3 2023-04-23 13:00 3.0 4 2023-04-21 14:00 4.0 5 2023-04-22 14:00 4.0 6 2023-04-23 14:00 5.0
同时询问:是否可以调整计算均值的窗口大小?
解决方案
原代码问题点
rolling的center参数应为布尔值(True/False),而非数值2,这会导致参数错误。- 仅用
rolling(window=2).mean()无法覆盖边界缺失值(如14:00组的首个NaN,无前置数据),需结合前后向填充或扩展窗口逻辑。
修正后的代码
import pandas as pd import numpy as np df = pd.DataFrame({'datetime':['2023-04-20 13:00', '2023-04-21 13:00','2023-04-22 13:00', '2023-04-23 13:00','2023-04-21 14:00', '2023-04-22 14:00', '2023-04-23 14:00'], 'var':[1, 2, np.nan, 3, np.nan, 4, 5]}) df['datetime'] = pd.to_datetime(df['datetime']) df['time'] = df['datetime'].dt.time # 分组后用滚动均值填充,结合前后向填充处理边界 def fill_missing_with_rolling_mean(col): # 先计算中心滚动均值(window=3,取当前行+前后各一行),填充中间缺失 rolling_mean = col.rolling(window=3, center=True, min_periods=1).mean() # 再用前后向填充处理剩余边界缺失 return col.fillna(rolling_mean).fillna(method='bfill').fillna(method='ffill') df['var'] = df.groupby('time', sort=False)['var'].apply(fill_missing_with_rolling_mean) print(df)
代码说明
rolling(window=3, center=True, min_periods=1):窗口大小为3(当前行+前后各一行),center=True表示以当前行为中心计算均值,min_periods=1保证即使窗口内只有1个有效值也能计算均值,适配边界情况。- 先通过滚动均值填充中间缺失,再用
bfill(后向填充)和ffill(前向填充)处理剩余的边界NaN,匹配期望结果。
关于窗口大小调整
完全可以调整窗口大小:
- 若想扩大计算均值的范围,比如取前后2行+当前行,可将
window设为5,同时保持center=True。 - 若只想取前一行和当前行的均值,将
window=2且center=False(默认),但需注意这种情况无法覆盖中间缺失的前后值计算(如13:00组的NaN)。 - 调整后需配合
min_periods参数,避免因窗口内有效值不足导致生成新的NaN。
内容的提问来源于stack exchange,提问作者corianne1234
相关产品推荐
相关产品推荐

