日期格式时间序列插值结果异常(含NaN/线性化)的解决方法
时间序列插值问题:NaN值或线性结果的解决方法
问题描述
我有一组时间序列数据,想要按月或按年做插值处理,写了如下Python代码,但运行后结果不理想,要么出现NaN值,要么得到完全线性的结果:
df = pd.read_csv('Data/data_processing.csv', encoding='latin1') df['Date'] = pd.to_datetime(df['Date']) sns.scatterplot(data=df, x=df['Date'], y=df['Value']) plt.show() df['Date'] = pd.to_datetime(df['Date']) # 重复转换无意义 df.set_index('Date', inplace=True) # Resample and interpolate df_resampled = df.resample('1Y') df_interp = df_resampled.interpolate(method='time') df_interp.to_csv(f'interpolated_data_polynomial.csv', index=True)
核心问题分析&修复方案
1. 先确认原始数据的有效性
- 检查
Date列转换是否成功:用df['Date'].isna().sum()统计无效日期数量,若有异常值需先清洗。 - 确保数据按时间排序:插值依赖有序的时间索引,执行
df = df.sort_values('Date').set_index('Date')完成排序+索引设置。
2. 修正重采样+插值的逻辑
原代码直接对重采样对象调用interpolate的逻辑有误,需根据目标需求调整流程:
场景A:生成按年/月的均匀时间点并插值填充
如果目标是得到每年(或每月)一个插值后的数值,正确流程是先生成目标频率的时间索引,再用原始数据插值填充:
df = pd.read_csv('Data/data_processing.csv', encoding='latin1') df['Date'] = pd.to_datetime(df['Date']) df = df.sort_values('Date').set_index('Date') # 生成目标频率的时间索引('1Y'为每年,替换为'1M'可按月) target_index = pd.date_range(start=df.index.min(), end=df.index.max(), freq='1Y') # 重新索引到目标频率,再用时间插值填充 df_interp = df.reindex(target_index).interpolate(method='time') df_interp.to_csv('interpolated_data_yearly.csv', index=True)
场景B:先补全细粒度插值,再按年/月聚合
如果需要先补全原始数据的时间间隔(比如补全每日数据),再按年/月聚合:
df = pd.read_csv('Data/data_processing.csv', encoding='latin1') df['Date'] = pd.to_datetime(df['Date']) df = df.sort_values('Date').set_index('Date') # 先插值补全到每日数据(可替换为'H'小时等细粒度) df_fine = df.resample('D').interpolate(method='time') # 再按年聚合,可选last()/mean()等聚合方式 df_yearly = df_fine.resample('1Y').last() df_yearly.to_csv('interpolated_aggregated_yearly.csv', index=True)
3. 选择适配数据的插值方法
method='time'仅适合时间间隔均匀的线性插值,若数据间隔不均或需要非线性结果:- 用
method='polynomial', order=2:二次多项式插值,适配有趋势的数据 - 用
method='spline', order=3:三次样条插值,生成更平滑的曲线
注意:使用非线性插值前,需确保数据无连续NaN段,否则仍会出现空值。
- 用
4. 处理边缘NaN值
若插值后首尾仍有NaN,可通过填充补全:
# 先向后填充,再向前填充,确保首尾无空值 df_interp = df_interp.bfill().ffill()
内容的提问来源于stack exchange,提问作者Mehdi MA
相关产品推荐
相关产品推荐

