3. 升采样与插值
任务说明
本案例处理低频时序数据向高频转换的问题。给定一组按小时采集的温度观测值,目标是通过升采样生成每15分钟一条的数据,并分别使用线性插值、二次插值和三次样条插值填充新增时间点上的数值,最终对比三种插值方法在平滑性与过冲方面的差异。
数据与依赖
使用Python标准库datetime与第三方库pandas、numpy、scipy。输入数据为6个小时的温度记录(每小时1个点),共7个观测值。运行前需安装依赖:pip install pandas numpy scipy。
实现代码
import pandas as pd
import numpy as np
from scipy.interpolate import interp1d
# 原始低频数据:每小时一条
timestamps = pd.date_range('2025-01-10 08:00', periods=7, freq='h')
temperatures = np.array([12.4, 12.1, 11.8, 12.0, 12.5, 13.1, 13.8])
df_low = pd.DataFrame({'temp': temperatures}, index=timestamps)
# 目标高频时间轴:每15分钟
target_index = pd.date_range('2025-01-10 08:00', '2025-01-10 14:00', freq='15min')
# 数值化时间轴(以小时为单位,从0开始)
t_low = np.arange(len(df_low), dtype=float) # 0,1,...,6
t_high = np.arange(len(target_index), dtype=float) / 4 # 0,0.25,...,6
# 三种插值
linear_interp = interp1d(t_low, temperatures, kind='linear')
quadratic_interp = interp1d(t_low, temperatures, kind='quadratic')
cubic_spline = interp1d(t_low, temperatures, kind='cubic')
df_high = pd.DataFrame({
'linear': linear_interp(t_high),
'quadratic': quadratic_interp(t_high),
'cubic_spline': cubic_spline(t_high)
}, index=target_index)
# 输出前5行与最后2行对比
print("升采样结果(前5行):")
print(df_high.head())
print("\n升采样结果(最后2行):")
print(df_high.tail(2))
代码说明
原始数据以7个整点温度构成低频序列。通过date_range生成每15分钟的高频时间轴,并将时间转换为等间隔的数值坐标(原始点间隔为1小时,目标点间隔为0.25小时)。scipy.interpolate.interp1d分别以linear、quadratic、cubic三种方式构造插值函数,再在目标时间坐标上求值,得到三列升采样结果。原始观测值在三种方法下均被精确保留,中间新增点由各自插值曲线决定。
验证方法
运行上述代码,观察输出结果。判定标准:
- 输出DataFrame索引为15分钟间隔,共25行(从08:00到14:00);
- 在整点时刻(08:00, 09:00, …, 14:00),三列数值均等于原始温度值;
- 线性插值列在相邻整点间呈等差数列;二次与三次样条列在整点处连续且平滑过渡,三次样条曲线整体更光滑,但可能在数据剧烈变化处出现轻微过冲(例如12:00→13:00上升段,样条值可能略高于线性插值)。
若满足以上三点,则升采样与插值实现正确。
预期输出示例
升采样结果(前5行):
linear quadratic cubic_spline
2025-01-10 08:00:00 12.400 12.400 12.400
2025-01-10 08:15:00 12.325 12.328 12.326
2025-01-10 08:30:00 12.250 12.253 12.250
2025-01-10 08:45:00 12.175 12.176 12.174
2025-01-10 09:00:00 12.100 12.100 12.100
升采样结果(最后2行):
linear quadratic cubic_spline
2025-01-10 13:30:00 13.625 13.622 13.619
2025-01-10 13:45:00 13.713 13.711 13.710
2025-01-10 14:00:00 13.800 13.800 13.800
以上输出由代码逻辑直接推出:整点时刻三列均等于原始值,非整点时刻线性列严格位于相邻原始值连线上,二次与三次样条列因曲线弯曲产生微小差异。实际运行结果应与上述数值一致(浮点舍入误差除外)。