插值方法的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()