插值方法的Python实现
1. 线性插值(Linear Interpolation)
-
原理:用直线连接相邻数据点,计算中间点的值。
-
实现:
import numpy as np from scipy.interpolate import interp1dx = np.array([0, 1, 2, 3, 4]) y = np.array([0, 2, 1, 3, 4]) f = interp1d(x, y, kind='linear') # 创建插值函数 x_new = np.linspace(0, 4, 10) y_new = f(x_new) # 插值结果
-
优点:计算快,结果稳定。
-
缺点:曲线不平滑,不适用于高波动数据。
-
场景:实时数据处理、简单填充缺失值。
2. 多项式插值(Polynomial Interpolation)
-
原理:通过多项式拟合所有数据点(如拉格朗日多项式)。
-
实现:
from scipy.interpolate import lagrangepoly = lagrange(x, y) # 生成拉格朗日多项式 y_new = poly(x_new)
-
优点:严格通过所有数据点。
-
缺点:高阶多项式易过拟合(龙格现象)。
-
场景:理论分析、低阶多项式插值。
3. 三次样条插值(Cubic Spline)
-
原理:分段三次多项式,保证一阶和二阶导数连续。
-
实现:
f = interp1d(x, y, kind='cubic') y_new = f(x_new)
-
优点:曲线平滑,适合连续数据。
-
缺点:计算量较大。
-
场景:自然信号(如音频、图像)、平滑曲线生成。
4. 最近邻插值(Nearest-neighbor)
-
原理:取距离最近的已知点的值。
-
实现:
f = interp1d(x, y, kind='nearest') y_new = f(x_new)
-
优点:保留数据离散特性。
-
缺点:阶梯状不连续。
-
场景:分类数据插值、图像像素处理。
5. Pandas 内置插值
-
原理:直接对
Series
或DataFrame
进行缺失值填充。 -
实现:
import pandas as pds = pd.Series([1, np.nan, 3, np.nan, 5]) s_interp = s.interpolate(method='linear') # 可选 cubic, quadratic, spline 等
-
方法参数:
-
method='time'
:按时间索引插值。 -
method='spline'
:需指定order
(多项式阶数)。
-
-
场景:时间序列数据清洗、缺失值填充。
进阶功能
1. 外推(Extrapolation)
-
功能:允许对超出原始数据范围的点进行插值。
-
实现:
f = interp1d(x, y, kind='cubic', fill_value='extrapolate') y_ext = f([-1, 5]) # 外推 x=-1 和 x=5 的值
2. 非均匀数据插值
-
问题:当数据点非均匀分布时,需指定插值轴参数。
-
示例:
x = np.array([0, 2, 5, 9]) # 非均匀分布 y = np.array([3, 1, 4, 2]) f = interp1d(x, y, kind='linear', assume_sorted=False)
3. Akima 插值
-
特点:避免三次样条的过度震荡。
-
实现:
from scipy.interpolate import Akima1DInterpolatorakima = Akima1DInterpolator(x, y) y_new = akima(x_new)
方法对比与选型
方法 | 平滑性 | 计算速度 | 外推支持 | 适用场景 |
---|---|---|---|---|
线性插值 | 低 | 快 | 否 | 实时计算、简单填充 |
三次样条 | 高 | 中 | 是 | 自然信号、平滑曲线 |
多项式插值 | 高 | 慢 | 否 | 理论分析、低阶数据 |
最近邻 | 无 | 极快 | 否 | 离散分类数据 |
Pandas 插值 | 可调 | 快 | 部分支持 | 时间序列、表格数据清洗 |
注意事项
-
单调性要求
大多数插值方法要求x
数据单调递增,否则会报错。若数据无序,需先排序:sorted_idx = np.argsort(x) x_sorted = x[sorted_idx] y_sorted = y[sorted_idx]
-
缺失值处理
SciPy插值函数不支持输入含NaN
的数据,需预先删除或填充:y_clean = y[~np.isnan(y)]
-
性能优化
对超大数据(如百万级数据点),优先使用kind='linear'
或kind='nearest'
。
完整示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d# 原始数据
x = np.array([0, 2, 3, 5, 8])
y = np.array([1, 4, 2, 6, 3])# 生成插值函数(三次样条)
f_cubic = interp1d(x, y, kind='cubic', fill_value='extrapolate')
x_new = np.linspace(0, 8, 100)
y_cubic = f_cubic(x_new)# 绘图对比
plt.scatter(x, y, color='red', label='原始数据')
plt.plot(x_new, y_cubic, label='三次样条插值')
plt.legend()
plt.show()