本文目录导读:

我来介绍几种在Python中实现数据插值的常用方法。
一维插值
使用 SciPy 的 interp1d
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
# 原始数据点
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([0, 2, 1, 4, 3, 6])
# 创建插值函数
f_linear = interpolate.interp1d(x, y, kind='linear') # 线性插值
f_cubic = interpolate.interp1d(x, y, kind='cubic') # 三次样条插值
f_quadratic = interpolate.interp1d(x, y, kind='quadratic') # 二次插值
# 创建新的x值用于插值
x_new = np.linspace(0, 5, 50)
# 计算插值结果
y_linear = f_linear(x_new)
y_cubic = f_cubic(x_new)
y_quadratic = f_quadratic(x_new)
# 可视化结果
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'o', label='原始数据', markersize=8)
plt.plot(x_new, y_linear, '-', label='线性插值', linewidth=2)
plt.plot(x_new, y_cubic, '--', label='三次样条插值', linewidth=2)
plt.plot(x_new, y_quadratic, ':', label='二次插值', linewidth=2)
plt.legend()
plt.xlabel('x')
plt.ylabel('y')'一维插值示例')
plt.grid(True)
plt.show()
使用 NumPy 的插值函数
import numpy as np
# 原始数据
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([0, 2, 1, 4, 3, 6])
# 使用 numpy 的 interp 函数(线性插值)
x_new = np.array([0.5, 1.5, 2.5, 3.5, 4.5])
y_new = np.interp(x_new, x, y)
print("原始数据点:")
for i in range(len(x)):
print(f"({x[i]}, {y[i]})")
print(f"\n插值点:")
for i in range(len(x_new)):
print(f"x={x_new[i]}, y={y_new[i]:.2f}")
二维插值
使用 griddata 进行散点插值
import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt
# 生成原始散点数据
np.random.seed(42)
n_points = 100
x = np.random.uniform(-3, 3, n_points)
y = np.random.uniform(-3, 3, n_points)
# 生成真实函数值
z = np.sin(x) * np.cos(y) + 0.1 * np.random.randn(n_points)
# 创建网格用于插值
xi = np.linspace(-3, 3, 100)
yi = np.linspace(-3, 3, 100)
xi, yi = np.meshgrid(xi, yi)
# 不同的插值方法
zi_linear = griddata((x, y), z, (xi, yi), method='linear')
zi_cubic = griddata((x, y), z, (xi, yi), method='cubic')
zi_nearest = griddata((x, y), z, (xi, yi), method='nearest')
# 可视化结果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 原始散点图
axes[0, 0].scatter(x, y, c=z, cmap='viridis', edgecolor='black', s=50)
axes[0, 0].set_title('原始散点数据')
axes[0, 0].set_xlabel('x')
axes[0, 0].set_ylabel('y')
# 线性插值
im1 = axes[0, 1].contourf(xi, yi, zi_linear, cmap='viridis')
axes[0, 1].set_title('线性插值')
axes[0, 1].set_xlabel('x')
axes[0, 1].set_ylabel('y')
plt.colorbar(im1, ax=axes[0, 1])
# 三次样条插值
im2 = axes[1, 0].contourf(xi, yi, zi_cubic, cmap='viridis')
axes[1, 0].set_title('三次样条插值')
axes[1, 0].set_xlabel('x')
axes[1, 0].set_ylabel('y')
plt.colorbar(im2, ax=axes[1, 0])
# 最近邻插值
im3 = axes[1, 1].contourf(xi, yi, zi_nearest, cmap='viridis')
axes[1, 1].set_title('最近邻插值')
axes[1, 1].set_xlabel('x')
axes[1, 1].set_ylabel('y')
plt.colorbar(im3, ax=axes[1, 1])
plt.tight_layout()
plt.show()
使用 RectBivariateSpline 进行规则网格插值
import numpy as np
from scipy.interpolate import RectBivariateSpline
import matplotlib.pyplot as plt
# 创建规则网格数据
x = np.linspace(-2, 2, 10)
y = np.linspace(-2, 2, 10)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y) + 0.1 * np.random.randn(10, 10)
# 创建样条插值函数
spline = RectBivariateSpline(x, y, Z.T, kx=3, ky=3) # kx, ky是样条阶数
# 创建更密的网格用于插值
x_new = np.linspace(-2, 2, 50)
y_new = np.linspace(-2, 2, 50)
Z_new = spline(x_new, y_new)
# 可视化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# 原始数据
im1 = ax1.pcolormesh(X, Y, Z, cmap='viridis')
ax1.set_title('原始规则网格数据')
plt.colorbar(im1, ax=ax1)
# 插值后的数据
X_new, Y_new = np.meshgrid(x_new, y_new)
im2 = ax2.pcolormesh(X_new, Y_new, Z_new, cmap='viridis')
ax2.set_title('三次样条插值')
plt.colorbar(im2, ax=ax2)
plt.tight_layout()
plt.show()
实际应用案例:缺失数据填充
import numpy as np
import pandas as pd
from scipy import interpolate
import matplotlib.pyplot as plt
# 创建包含缺失值的时间序列数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=30, freq='D')
values = np.sin(np.linspace(0, 3*np.pi, 30)) + np.random.normal(0, 0.3, 30)
# 人为加入缺失值
missing_indices = [5, 6, 12, 13, 14, 20, 21]
values[missing_indices] = np.nan
# 提取非缺失值
valid_mask = ~np.isnan(values)
x_valid = np.arange(len(values))[valid_mask]
y_valid = values[valid_mask]
# 使用插值填充缺失值
x_all = np.arange(len(values))
# 线性插值
f_linear = interpolate.interp1d(x_valid, y_valid, kind='linear',
fill_value='extrapolate')
y_filled_linear = f_linear(x_all)
# 三次样条插值
f_cubic = interpolate.interp1d(x_valid, y_valid, kind='cubic',
fill_value='extrapolate')
y_filled_cubic = f_cubic(x_all)
# 可视化结果
plt.figure(figsize=(12, 6))
# 原始数据(包含缺失值)
plt.plot(dates, values, 'o-', label='原始数据(含缺失值)',
linewidth=2, markersize=6)
# 填充后的数据
plt.plot(dates, y_filled_linear, 's-', label='线性插值填充',
linewidth=2, markersize=4, alpha=0.7)
plt.plot(dates, y_filled_cubic, '^--', label='三次样条插值填充',
linewidth=2, markersize=4, alpha=0.7)
# 标记缺失位置
plt.scatter(dates[missing_indices], y_filled_linear[missing_indices],
color='red', s=100, label='插值点', zorder=5)
plt.xlabel('日期')
plt.ylabel('值')'时间序列数据缺失值插值填充')
plt.legend()
plt.xticks(rotation=45)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 输出插值结果
print("缺失值插值结果:")
for idx in missing_indices:
print(f"日期 {dates[idx].strftime('%Y-%m-%d')}: "
f"线性插值 = {y_filled_linear[idx]:.3f}, "
f"三次样条插值 = {y_filled_cubic[idx]:.3f}")
插值方法选择指南
| 插值方法 | 适用场景 | 特点 |
|---|---|---|
| 线性插值 | 数据变化平缓 | 简单快速,但导数不连续 |
| 三次样条 | 需要平滑曲线 | 二阶导数连续,结果平滑 |
| 最近邻 | 分类数据 | 简单,但结果不连续 |
| 多项式插值 | 数据点较少 | 可能产生振荡(龙格现象) |
| 径向基函数 | 散乱数据 | 灵活,适用于高维数据 |
Python中数据插值的主要工具:
- NumPy:
np.interp()用于简单线性插值 - SciPy:
interp1d(),griddata(),RectBivariateSpline() - Pandas:
DataFrame.interpolate()用于时间序列插值
选择插值方法时需考虑数据特性、精度要求和计算效率。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播