scipy的差值和优化主要在interpolate类中

(1)一维差值 interp1d

x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 4, 9, 16])
f= interpolate.interp1d(x, y, kind='linear')
x_new=np.linspace(0,4,100)
y_new=f(x_new)

interp1d要关注的参数有三个,第一个是要插值数据的x值,第二个是要插值数据的y值,第三个kind是插值方式,常用的有以下方式:

#'nearest':最近邻插值
#'zero':零阶插值
#'slinear':一阶样条插值
#'quadratic':二阶样条插值
#'cubic':三阶样条插值
#'linear':线性插值
#'polynomial':多项式插值

其他方式:

#二次插值
f2=interpolate.interp1d(x, y, kind='quadratic')
y_new2=f2(x_new)

#三次插值
f3=interpolate.interp1d(x, y, kind='cubic')
y_new3=f3(x_new)
#最近邻插值
f4=interpolate.interp1d(x, y, kind='nearest')
y_new4=f4(x_new)

显示出来:

plt.plot(x_new,y_new4,'b--')
plt.plot(x,y,'o',x_new,y_new,'k--')
plt.plot(x_new,y_new2,'r--')
plt.plot(x_new,y_new3,'g--')
plt.show()

(2)二维插值RegularGridInterpolator

自变量是x y 函数值是z

# 原始数据
x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 4, 9, 16])
z = np.array([[0, 1, 4, 9, 16], [1, 2, 5, 10, 17],
              [4, 5, 8, 13, 20], [9, 10, 13, 18, 25],
              [16, 17, 20, 25, 32]])
# 创建插值函数
interp_func = interpolate.RegularGridInterpolator((x, y), z, method='linear')

# 生成插值点
x_new = np.linspace(0, 4, 100)
y_new = np.linspace(0, 16, 100)
x_mesh, y_mesh = np.meshgrid(x_new, y_new)
points = np.vstack([x_mesh.ravel(), y_mesh.ravel()]).T
z_new = interp_func(points).reshape(100, 100)

# 可视化插值结果
plt.imshow(z_new, extent=[0, 4, 0, 16], origin='lower', cmap='viridis')
plt.colorbar(label='z')
plt.xlabel('x')
plt.ylabel('y')
plt.title('2D Interpolation with RegularGridInterpolator')
plt.show()

其中RegularGridInterpolator的参数主要有三个 第一个为自变量的取值(x,y),第二个为因变量的取值z,method为插值方法。

这里讲解一下,x_mesh,y_mesh=np.meshgrid(x,y)函数,x在垂直方向复制len(y)次得到x_mesh

y在水平方向复制len(x)次得到y_mesh。

np.vstack([x_mesh.ravel(),y_mesh.ravel()]).T 首先 ravel将 x_mesh和y_mesh变成一个一维数组,vstack将 变成的一维数组垂直堆起来,变成x 在上 y在下,之后在转置变为nx2的矩阵,每一行对应一个数据点。

(3)网格数据

#网格数据
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata
# 1. 创建一些不规则的源数据点 (模拟测量数据)
np.random.seed(42) # 保证每次运行结果一致
n_points = 200
# 在一个圆形区域内随机生成点
angles = np.random.rand(n_points) * 2 * np.pi
radii = np.sqrt(np.random.rand(n_points)) * 10
#column_stack函数将两个数组按列合并
points = np.column_stack((radii * np.cos(angles), radii * np.sin(angles)))

# 为这些点生成一个值 (模拟湿度值,比如一个复杂的函数)
values = np.sin(points[:, 0] / 2) * np.cos(points[:, 1] / 2)

# 2. 创建我们想要插值的目标网格
grid_x, grid_y = np.mgrid[-10:10:100j, -10:10:100j] # 100x100 的规则网格
#这里的j的意思是不要当成步长,而是-10到10 之间插100个数,如果没有j那么就是步长

# 3. 使用 griddata 进行插值
# 我们分别用三种方法进行插值,以便比较
#参数:1 源数据点 2 源数据点的值 3 目标网格 4 插值方法
grid_z_nearest = griddata(points, values, (grid_x, grid_y), method='nearest')
grid_z_linear = griddata(points, values, (grid_x, grid_y), method='linear')
grid_z_cubic = griddata(points, values, (grid_x, grid_y), method='cubic')

# 4. 可视化结果
plt.figure(figsize=(15, 5))

# 原始数据点
plt.subplot(1, 4, 1)
plt.scatter(points[:, 0], points[:, 1], c=values, s=50, cmap='viridis')
plt.title("Original Scattered Data")
plt.axis('equal')

# 最近邻插值结果
plt.subplot(1, 4, 2)
plt.imshow(grid_z_nearest.T, extent=(-10, 10, -10, 10), origin='lower', cmap='viridis')
plt.title("Nearest Neighbor")
plt.axis('equal')

# 线性插值结果
plt.subplot(1, 4, 3)
plt.imshow(grid_z_linear.T, extent=(-10, 10, -10, 10), origin='lower', cmap='viridis')
plt.title("Linear Interpolation")
plt.axis('equal')

# 三次样条插值结果
plt.subplot(1, 4, 4)
plt.imshow(grid_z_cubic.T, extent=(-10, 10, -10, 10), origin='lower', cmap='viridis')
plt.title("Cubic Interpolation")
plt.axis('equal')

plt.tight_layout()
plt.show()

griddata需要传入的参数有:点(x,y)值以及插值目标范围(grid_x.grid_y)和插值方法

矩形二元样条网格插值spline = RectBivariateSpline(x, y, Z.T, kx=3, ky=3)

#矩形二元样条网格插值
# 先拟合,后查询
"""
x: 1-D array,网格的 x 坐标轴,必须是单调递增的。例如 [1, 2, 3, 4]。
y: 1-D array,网格的 y 坐标轴,也必须是单调递增的。例如 [10, 20, 30]。
z: 2-D array,形状必须为 (len(x), len(y))。z[i, j] 是点 (x[i], y[j]) 上的值。注意顺序。
kx, ky: 样条的阶数(degree)。默认为 3,表示三次样条,这是最常用且最平滑的选择。你也可以设为 1(线性插值)或 2(二次样条)。
s: 平滑因子。这是一个非常重要的参数。
s=0:强制插值。样条曲线必须精确穿过所有数据点。这是最常用的设置,相当于“完美拟合”。
s > 0:平滑样条。允许样条曲线不穿过某些数据点,以换取一个更平滑的整体曲面。
s 越大,曲面越平滑,但与原始数据的偏差也越大。这在数据本身含有噪声时非常有用。
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import RectBivariateSpline

# 1. 创建规则网格上的源数据
# 定义一个 20x20 的稀疏网格
x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 20)
X, Y = np.meshgrid(x, y)
# 在网格上计算一个函数值,比如一个带尖峰的函数
Z = np.sin(np.sqrt(X**2 + Y**2)) / (1 + np.sqrt(X**2 / 4 + Y**2 / 4))
#x的每一个分别与Y的每一个计算,按列计算,X的第一个计算的都放在第一列
#故行数是y的长度

# 2. 使用 RectBivariateSpline 创建样条对象
# 注意:RectBivariateSpline 要求 Z 的形状是 (len(x), len(y))
# 我们的 meshgrid 默认是 'xy' 索引,所以 Z.T 才是正确的
spline = RectBivariateSpline(x, y, Z.T, kx=3, ky=3)
# 3. 创建一个更密集的查询网格
x_new = np.linspace(-5, 5, 200)
y_new = np.linspace(-5, 5, 200)
# 使用样条对象进行评估
Z_spline = spline(x_new, y_new, grid=True)

# 4. 可视化
plt.figure(figsize=(15, 5))

# 原始稀疏数据
plt.subplot(1, 3, 1)
plt.pcolormesh(X, Y, Z, shading='auto', cmap='viridis')
plt.title("Original Sparse Data (20x20)")
plt.axis('equal')

# RectBivariateSpline 插值结果
plt.subplot(1, 3, 2)
plt.pcolormesh(x_new, y_new, Z_spline, shading='auto', cmap='viridis')
plt.title("RectBivariateSpline (Cubic)")
plt.axis('equal')

# 为了对比,我们用 griddata 的线性插值也做一遍
from scipy.interpolate import griddata
points = np.column_stack((X.ravel(), Y.ravel()))
values = Z.ravel()
grid_x, grid_y = np.mgrid[-5:5:200j, -5:5:200j]
Z_griddata = griddata(points, values, (grid_x, grid_y), method='linear')

plt.subplot(1, 3, 3)
plt.pcolormesh(grid_x, grid_y, Z_griddata, shading='auto', cmap='viridis')
plt.title("Griddata (Linear) for Comparison")
plt.axis('equal')

plt.show()

更多推荐