HoRain云--SciPy插值:从入门到精通
🎬 HoRain 云小助手:个人主页
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
目录
⛳️ 推荐
📈 SciPy 插值完整指南
🎯 什么是插值?
🔷 scipy.interpolate 模块概览
一维插值
多维插值
1️⃣ 一维插值详解
方法一:interp1d(最常用)
interp1d 参数详解
不同插值类型的效果对比
方法二:CubicSpline(推荐)
方法三:PchipInterpolator(保持单调性)
方法四:UnivariateSpline(带平滑)
2️⃣ 多维插值详解
griddata(散乱数据插值)
griddata 参数
RegularGridInterpolator(规则网格)
Rbf(径向基函数)
⚡ 实用案例
案例一:填补缺失数据
案例二:提高图像分辨率
案例三:时间序列插值
📊 各插值方法特性对比
⚠️ 注意事项
💡 最佳实践总结
📈 SciPy 插值完整指南
根据搜索到的最新信息(2024-2025),我为您整理了SciPy 插值的详细说明和使用方法。
🎯 什么是插值?
| 类型 | 定义 | 与拟合的区别 |
|---|---|---|
| 插值 (Interpolation) | 通过已知数据点构建一个函数,该函数必须经过所有已知点 | 严格要求曲线通过所有原始数据点 |
| 拟合 (Fitting) | 找到最佳匹配数据的函数模型 | 不要求通过所有点,只追求整体最优 |
# 应用场景 # ✅ 填补缺失数据 # ✅ 平滑离散数据曲线 # ✅ 预测未知点的值 # ✅ 提高数据分辨率🔷 scipy.interpolate 模块概览
SciPy 提供了多种插值方法,按维度分类如下:
一维插值
| 类/函数 | 特点 | 适用场景 |
|---|---|---|
interp1d | 简单直接,多种插值方式 | 快速一维插值 |
UnivariateSpline | 带平滑参数的样条插值 | 有噪声数据 |
Akima1DInterpolator | Akima样条,局部适应性好 | 局部变化剧烈数据 |
PchipInterpolator | 保持单调性 | 物理意义重要的数据 |
CubicSpline | 三次样条,二阶导数连续 | 需要平滑曲线 |
BarycentricInterpolator | 重心插值 | 高精度要求 |
多维插值
| 类/函数 | 特点 | 适用场景 |
|---|---|---|
griddata | 不规则网格点插值 | 散乱数据插值 |
RegularGridInterpolator | 规则网格插值 | 规则采样数据 |
RectBivariateSpline | 矩形区域双变量样条 | 规则二维数据 |
Rbf | 径向基函数插值 | 不规则三维及以上 |
1️⃣ 一维插值详解
方法一:interp1d(最常用)
from scipy.interpolate import interp1d import numpy as np # 原始数据点 x = np.array([0, 1, 2, 3, 4]) y = np.array([0, 1, 4, 9, 16]) # y = x² # 创建插值函数 # kind: 'linear'(线性), 'nearest', 'zero', 'slinear', 'quadratic', 'cubic' f_linear = interp1d(x, y, kind='linear') f_cubic = interp1d(x, y, kind='cubic') # 生成新的x点进行插值 x_new = np.linspace(0, 4, 20) # 计算插值结果 y_linear = f_linear(x_new) y_cubic = f_cubic(x_new) print(y_linear[:5]) # 查看前几个插值结果interp1d 参数详解
| 参数 | 说明 | 默认值 |
|---|---|---|
x | 自变量数组(一维) | 必需 |
y | 因变量数组(一维或多维) | 必需 |
kind | 插值类型 | 'linear' |
axis | 沿哪个轴进行插值 | -1 |
copy | 是否复制数据 | True |
bounds_error | 超出范围是否报错 | False |
fill_value | 超出范围的值 | np.nan |
assume_sorted | 是否假设已排序 | False |
不同插值类型的效果对比
import matplotlib.pyplot as plt x = np.array([0, 1, 2, 3, 4]) y = np.array([0, 1, 4, 9, 16]) x_new = np.linspace(0, 4, 100) fig, ax = plt.subplots(figsize=(10, 6)) # 绘制原始数据点 ax.plot(x, y, 'ro', label='原始数据') # 线性插值 f_linear = interp1d(x, y, kind='linear') ax.plot(x_new, f_linear(x_new), 'b-', label='线性插值') # 三次插值 f_cubic = interp1d(x, y, kind='cubic') ax.plot(x_new, f_cubic(x_new), 'g--', label='三次插值') ax.legend() plt.title('不同插值类型对比') plt.show()方法二:CubicSpline(推荐)
from scipy.interpolate import CubicSpline # 创建三次样条插值 cs = CubicSpline(x, y) # 插值 x_new = np.linspace(0, 4, 100) y_new = cs(x_new) # 也可以求导数 dy_dx = cs.derivative()(x_new) # 一阶导数 d2y_dx2 = cs.derivative(n=2)(x_new) # 二阶导数 print(f"在 x=2.5 处的值: {cs(2.5)}") print(f"在 x=2.5 处的斜率: {cs.derivative()(2.5)}")方法三:PchipInterpolator(保持单调性)
from scipy.interpolate import PchipInterpolator # 对于可能非单调变化的数据,避免过冲 pchip = PchipInterpolator(x, y) x_new = np.linspace(0, 4, 100) y_new = pchip(x_new) # PCHIP不会引入额外的极值点,适合物理意义重要的数据方法四:UnivariateSpline(带平滑)
from scipy.interpolate import UnivariateSpline # s 参数控制平滑程度,越大越平滑 # 如果数据有噪声,这个很重要 spline = UnivariateSpline(x, y, s=2.0) x_new = np.linspace(0, 4, 100) y_new = spline(x_new) # 调整平滑参数 # s = 0 → 精确插值 # s > len(x) → 更平滑但可能偏离原数据2️⃣ 多维插值详解
griddata(散乱数据插值)
from scipy.interpolate import griddata import numpy as np # 原始散乱数据点 points = np.array([[0, 0], [1, 0], [0, 1], [1, 1], [0.5, 0.5]]) values = np.array([0, 1, 1, 2, 1]) # 创建插值网格 xi = np.linspace(0, 1, 100) yi = np.linspace(0, 1, 100) XI, YI = np.meshgrid(xi, yi) # 插值三种方法对比 # 'nearest': 最近邻插值 - 速度快,但不平滑 # 'linear': 线性插值 - 平衡速度与质量 # 'cubic': 三次插值 - 最平滑,速度较慢 ZI_nearest = griddata(points, values, (XI, YI), method='nearest') ZI_linear = griddata(points, values, (XI, YI), method='linear') ZI_cubic = griddata(points, values, (XI, YI), method='cubic')griddata 参数
| 参数 | 说明 |
|---|---|
points | 原始数据点坐标 (N, ndim) |
values | 原始数据值 (N,) |
xi | 插值点坐标 ((M,) 或 (M, M) 等) |
method | 'nearest','linear','cubic' |
fill_value | 外推区域的填充值 |
rescale | 是否先缩放数据到单位超立方体 |
RegularGridInterpolator(规则网格)
from scipy.interpolate import RegularGridInterpolator # 规则网格数据 xi = np.array([0, 1, 2]) yi = np.array([0, 1, 2]) zi = np.array([0, 1, 2]) # Z[i,j,k] 对应于 xi[i], yi[j], zi[k] Z = np.zeros((3, 3, 3)) Z[0, 0, 0] = 0; Z[1, 0, 0] = 1; Z[2, 0, 0] = 2 Z[0, 1, 0] = 1; Z[1, 1, 0] = 2; Z[2, 1, 0] = 3 Z[0, 2, 0] = 2; Z[1, 2, 0] = 3; Z[2, 2, 0] = 4 # 创建插值器 interp_func = RegularGridInterpolator((xi, yi, zi), Z) # 查询任意点的值 query_points = np.array([[1.5, 1.5, 1.5], [0.5, 0.5, 0.5]]) result = interp_func(query_points) print(result) # [[2.5] [0.5]]Rbf(径向基函数)
from scipy.interpolate import Rbf # 散乱点插值 xi = [1.2, 3.2, 4.7, 7.9] yi = [3.8, 6.7, 7.1, 3.4] zi = [5.9, 7.8, 9.3, 4.2] # 创建径向基插值对象 r = Rbf(xi, yi, zi, function='thin_plate') # 查询新点 x_new = 2.0 y_new = 5.0 z_new = r(x_new, y_new) print(f"预测高度: {z_new}") # 可用的function选项 # 'linear', 'multiquadric', 'inverse', 'gaussian', 'thin_plate', etc.⚡ 实用案例
案例一:填补缺失数据
import numpy as np from scipy.interpolate import interp1d # 模拟有缺失的数据 time = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) temp = np.array([20.1, 21.5, np.nan, 24.3, 25.8, np.nan, 28.1, 29.0, 30.2, 31.0]) # 有效数据索引 valid_mask = ~np.isnan(temp) t_valid = time[valid_mask] temp_valid = temp[valid_mask] # 创建插值函数 f = interp1d(t_valid, temp_valid, kind='cubic') # 填补缺失值 temp_filled = np.where(np.isnan(temp), f(time), temp) print("填补后的数据:", temp_filled)案例二:提高图像分辨率
import numpy as np from scipy.interpolate import griddata import matplotlib.pyplot as plt # 低分辨率图像数据 low_res_x = np.linspace(0, 10, 10) low_res_y = np.linspace(0, 10, 10) X_low, Y_low = np.meshgrid(low_res_x, low_res_y) # 示例:温度场数据 Z_low = np.sin(X_low * np.pi / 10) * np.cos(Y_low * np.pi / 10) # 高分辨率目标 high_res_x = np.linspace(0, 10, 100) high_res_y = np.linspace(0, 10, 100) XI_high, YI_high = np.meshgrid(high_res_x, high_res_y) # 网格转换为点 points = np.column_stack((X_low.flatten(), Y_low.flatten())) values = Z_low.flatten() # 插值到高空间分辨率 Z_high = griddata(points, values, (XI_high, YI_high), method='cubic') # 可视化 fig, axes = plt.subplots(1, 2, figsize=(12, 5)) axes[0].contourf(X_low, Y_low, Z_low, 20) axes[0].set_title('低分辨率') axes[1].contourf(XI_high, YI_high, Z_high, 50) axes[1].set_title('高分辨率插值后') plt.tight_layout() plt.show()案例三:时间序列插值
import pandas as pd import numpy as np from scipy.interpolate import interp1d # 创建有缺失的时间序列 df = pd.DataFrame({ 'date': pd.date_range('2024-01-01', periods=10, freq='D'), 'value': [1.0, 1.5, np.nan, 2.5, np.nan, 3.5, np.nan, 4.5, 5.0, 5.5] }) # 方法一:使用 DataFrame 内置方法 df_interpolated = df.copy() df_interpolated['value'] = df_interpolated['value'].interpolate(method='cubic') # 方法二:使用 scipy df['days'] = (df['date'] - df['date'].min()).dt.days valid_idx = df['value'].notna() f = interp1d(df.loc[valid_idx, 'days'], df.loc[valid_idx, 'value']) df['value_scipy'] = f(df['days']) print(df)📊 各插值方法特性对比
| 方法 | 平滑度 | 速度 | 单调性 | 外推能力 | 适用场景 |
|---|---|---|---|---|---|
| 线性插值 | 低 | 最快 | ✅ | ❌ | 简单快速需求 |
| 三次插值 | 高 | 中等 | ❌ | ⚠️ | 需要平滑曲线 |
| PCHIP | 中 | 快 | ✅ | ❌ | 保持物理意义 |
| 最近邻 | 最低 | 最快 | ✅ | ✅ | 分类数据 |
| 径向基 | 高 | 慢 | ❌ | ⚠️ | 多維散乱数据 |
| UnivariateSpline | 可调 | 快 | 取决于参数 | ❌ | 有噪声数据 |
⚠️ 注意事项
| 问题 | 建议 |
|---|---|
| 数据点太少 | 至少需要4个点用于三次插值 |
| 数据有噪声 | 使用 UnivariateSpline 加平滑参数 |
| 超出范围 | 设置 fill_value 或 bounds_error=False |
| 数据不单调 | 使用 PchipInterpolator 而不是 cubic |
| 大矩阵插值 | RegularGridInterpolator 比 griddata 快 |
| 边界行为 | 三次插值可能在边界产生过冲 |
💡 最佳实践总结
- 简单一维插值→
interp1d(kind='linear') - 需要平滑曲线→
CubicSpline或interp1d(kind='cubic') - 保持单调性→
PchipInterpolator - 有噪声数据→
UnivariateSpline(s=参数) - 散乱多点插值→
griddata - 规则网格插值→
RegularGridInterpolator
如需针对特定应用场景的详细代码,请告诉我您的具体需求!
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
