如何用跨年度对应日期均值填补时间序列的长周期缺失值?
用同期日期均值填补时间序列缺失值
问题描述
我拥有2015-2022年的日度时间序列数据集:
- 2015-2018年仅包含1-6月数据,7-12月全为NA
- 2019-2022年数据完整
需要利用2019-2022年的数据,计算缺失月份对应日期的均值,填补NA值。
模拟数据集
以下是模拟场景的代码:2019年7-8月全为缺失值,需要用2020、2021年对应日期的均值填补;此前尝试过pandas插值方法,但因缺失周期过长效果不佳。
import numpy as np import pandas as pd np.random.seed(1) rows,cols = 1000,3 # 数据集共1000行,对应2019-01-01至2021-09-26的日度数据 data = np.random.rand(rows,cols) tidx = pd.date_range('2019-01-01', periods=rows, freq='D') df = pd.DataFrame(data, columns=['a','b','c'], index=tidx) # 包含3个数据列 date_list =pd.date_range(start='2019-07-01', end='2019-08-31') df[df.index.isin(date_list)] = np.nan # 2019年7-8月全为缺失,2020、2021年对应月份有数据 print(df)
解决方案
核心逻辑是通过月-日特征匹配不同年份的同一天,用后续年份的同期均值填补缺失。
步骤1:提取月-日标识
为每个日期生成month_day列(格式MM-DD),用于跨年份匹配同一天:
df['month_day'] = df.index.strftime('%m-%d')
步骤2:计算同期日期均值
筛选2020-2021年的数据,按month_day分组计算各列的均值:
# 筛选2020和2021年的有效数据 year_mask = (df.index.year >= 2020) & (df.index.year <= 2021) daily_means = df[year_mask].groupby('month_day')[['a','b','c']].mean()
步骤3:填补缺失值
定位2019年7-8月的缺失行,通过month_day匹配均值完成填补:
# 定位需要填补的缺失行 fill_mask = df.index.isin(date_list) # 按月-日匹配均值,填充缺失值 df.loc[fill_mask, ['a','b','c']] = df.loc[fill_mask].apply( lambda row: daily_means.loc[row['month_day']], axis=1 )
步骤4:清理辅助列
填补完成后,可删除用于匹配的month_day列:
df.drop('month_day', axis=1, inplace=True)
完整可运行代码
import numpy as np import pandas as pd np.random.seed(1) rows,cols = 1000,3 data = np.random.rand(rows,cols) tidx = pd.date_range('2019-01-01', periods=rows, freq='D') df = pd.DataFrame(data, columns=['a','b','c'], index=tidx) date_list =pd.date_range(start='2019-07-01', end='2019-08-31') df[df.index.isin(date_list)] = np.nan # 提取月-日标识 df['month_day'] = df.index.strftime('%m-%d') # 计算2020-2021年同期日期均值 year_mask = (df.index.year >= 2020) & (df.index.year <= 2021) daily_means = df[year_mask].groupby('month_day')[['a','b','c']].mean() # 填补缺失值 fill_mask = df.index.isin(date_list) df.loc[fill_mask, ['a','b','c']] = df.loc[fill_mask].apply( lambda row: daily_means.loc[row['month_day']], axis=1 ) # 删除辅助列 df.drop('month_day', axis=1, inplace=True) # 查看填补后的结果 print(df.loc[date_list])
内容的提问来源于stack exchange,提问作者dev-charodeyka
相关产品推荐
相关产品推荐

