SciPy 插值:原理与代码实例
SciPy 的 interpolate 模块提供了多种插值方法,用于从离散数据点构建连续函数。以下是常用插值方法及其代码示例。
一维插值:interp1d
interp1d 是 SciPy 中最基础的一维插值工具,支持线性、最近邻、二次和三次插值。
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
# 原始数据点
x = np.linspace(0, 10, num=10)
y = np.sin(x)
# 创建插值函数
f_linear = interp1d(x, y, kind='linear')
f_cubic = interp1d(x, y, kind='cubic')
# 生成密集采样点
x_new = np.linspace(0, 10, num=100)
# 绘图
plt.plot(x, y, 'o', label='原始数据')
plt.plot(x_new, f_linear(x_new), '-', label='线性插值')
plt.plot(x_new, f_cubic(x_new), '--', label='三次插值')
plt.legend()
plt.show()
样条插值:UnivariateSpline
样条插值通过分段多项式拟合数据,适合噪声较大的数据集。
from scipy.interpolate import UnivariateSpline
# 带噪声的数据
np.random.seed(0)
y_noisy = y + np.random.normal(0, 0.1, size=len(x))
# 创建样条插值
spline = UnivariateSpline(x, y_noisy, s=0.5) # s 控制平滑度
plt.plot(x, y_noisy, 'o', label='噪声数据')
plt.plot(x_new, spline(x_new), 'r-', label='样条插值')
plt.legend()
plt.show()
多维插值:griddata
对于多维散点数据,griddata 提供不规则网格插值功能。
from scipy.interpolate import griddata
# 生成二维随机数据
points = np.random.rand(100, 2)
values = np.sin(points[:, 0] * 4) + np.cos(points[:, 1] * 4)
# 定义规则网格
grid_x, grid_y = np.mgrid[0:1:20j, 0:1:20j]
# 执行插值
grid_linear = griddata(points, values, (grid_x, grid_y), method='linear')
# 绘图
plt.imshow(grid_linear.T, extent=(0,1,0,1), origin='lower')
plt.scatter(points[:,0], points[:,1], c=values, edgecolor='white')
plt.colorbar()
plt.show()
径向基函数插值:Rbf
径向基函数(RBF)适用于高维空间插值。
from scipy.interpolate import Rbf
# 创建RBF插值器
rbf = Rbf(points[:,0], points[:,1], values, function='multiquadric')
# 在网格上评估
grid_rbf = rbf(grid_x, grid_y)
plt.imshow(grid_rbf.T, extent=(0,1,0,1), origin='lower')
plt.colorbar()
plt.show()
参数化插值:splprep 和 splev
用于参数化曲线插值,常见于路径规划。
from scipy.interpolate import splprep, splev
# 生成螺旋线数据
t = np.linspace(0, 4*np.pi, 20)
x_spiral = np.cos(t)
y_spiral = np.sin(t)
# 参数化B样条拟合
tck, u = splprep([x_spiral, y_spiral], s=0)
# 密集采样
u_new = np.linspace(0, 1, 100)
x_new, y_new = splev(u_new, tck)
plt.plot(x_spiral, y_spiral, 'ro')
plt.plot(x_new, y_new, 'b-')
plt.axis('equal')
plt.show()
性能优化:正则网格插值
对于规则网格数据,RegularGridInterpolator 效率更高。
from scipy.interpolate import RegularGridInterpolator
# 创建3D规则网格数据
x = np.linspace(0, 1, 5)
y = np.linspace(0, 2, 7)
z = np.linspace(0, 3, 9)
data = np.random.rand(5, 7, 9)
# 构建插值器
interp = RegularGridInterpolator((x, y, z), data)
# 在新点评估
pts = np.array([[0.5, 1.5, 2.5], [0.1, 0.2, 0.3]])
print(interp(pts))
实际应用案例
图像放大
from scipy.ndimage import zoom
import matplotlib.image as mpimg
# 加载小图像
img = mpimg.imread('small_image.png') # 假设100x100像素
# 使用样条插值放大5倍
img_large = zoom(img, 5, order=3) # order=3表示三次样条
plt.imshow(img_large)
plt.show()
缺失数据处理
# 创建有缺失值的时间序列
x = np.linspace(0, 10, 20)
y = np.sin(x)
y[5:10] = np.nan # 模拟缺失数据
# 获取有效点索引
valid = ~np.isnan(y)
x_valid = x[valid]
y_valid = y[valid]
# 插值填充缺失值
f = interp1d(x_valid, y_valid, kind='cubic', fill_value='extrapolate')
y_filled = f(x)
plt.plot(x, y, 'o', label='原始(含缺失)')
plt.plot(x, y_filled, '-', label='插值填充')
plt.legend()
plt.show()
以上代码示例展示了 SciPy 插值在不同场景中的应用,读者可根据实际需求选择合适的方法并调整参数。注意插值方法的选择需考虑数据特性(如平滑度、噪声水平)和计算效率的平衡。
945

被折叠的 条评论
为什么被折叠?



