Python数值分析:一维与二维插值算法实现详解

阿澈
阿澈
发布时间:2026-10-13 | 3人浏览过
原创

本文详解Python中一维与二维插值的实现方法。涵盖拉格朗日、分段及样条插值原理,重点解析利用SciPy库进行一维数据平滑处理及二维网格三次样条插值的代码逻辑。通过对比原始粗糙数据与插值后光滑曲面,展示如何提升数据可视化精度与平滑度。

一维插值原理与代码实现

一维插值

插值与拟合存在本质区别。插值函数要求严格经过所有给定的样本点,而拟合函数通常基于最小二乘法,旨在使曲线尽可能贴近所有样本点分布。在常见的插值方法中,主要包括拉格朗日插值法、分段插值法以及样条插值法。

  • 对于拉格朗日插值多项式,当节点数量n较大时,多项式的次数会随之升高,这可能导致收敛性不一致的问题,且计算复杂度显著增加。随着样点数量的增加,高次插值容易引发误差剧烈震荡,这一现象在数值计算中被称为龙格现象。
  • 分段插值虽然能够保证收敛性,但其光滑程度相对较差,无法提供高阶连续性的曲线表现。
  • 样条插值采用一种特殊的分段多项式进行构造。由于低阶多项式样条能够有效减小插值误差,从而避免了高次多项式带来的龙格现象,因此样条插值在应用中广受欢迎。

# -*-coding:utf-8 -*-
import numpy as np
from scipy import interpolate
import pylab as pl

x=np.linspace(0,10,11)
#x=[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
y=np.sin(x)
xnew=np.linspace(0,10,101)
pl.plot(x,y,"ro")

for kind in ["nearest","zero","slinear","quadratic","cubic"]:#插值方式
 #"nearest","zero"为阶梯插值
 #slinear 线性插值
 #"quadratic","cubic" 为2阶、3阶B样条曲线插值
 f=interpolate.interp1d(x,y,kind=kind)
 # ‘slinear', ‘quadratic' and ‘cubic' refer to a spline interpolation of first, second or third order)
 ynew=f(xnew)
 pl.plot(xnew,ynew,label=str(kind))
pl.legend(loc="lower right")
pl.show()

运行上述代码可得一维插值结果对比图。

二维插值与三维可视化

二维插值

二维数据插值的原理与一维情况类似,通常采用二维样条插值方法进行处理。


# -*- coding: utf-8 -*-
"""
演示二维插值。
"""
import numpy as np
from scipy import interpolate
import pylab as pl
import matplotlib as mpl

def func(x, y):
 return (x+y)*np.exp(-5.0*(x**2 + y**2))

# X-Y轴分为15*15的网格
y,x= np.mgrid[-1:1:15j, -1:1:15j]

fvals = func(x,y) # 计算每个网格点上的函数值 15*15的值
print len(fvals[0])

#三次样条二维插值
newfunc = interpolate.interp2d(x, y, fvals, kind='cubic')

# 计算100*100的网格上的插值
xnew = np.linspace(-1,1,100)#x
ynew = np.linspace(-1,1,100)#y
fnew = newfunc(xnew, ynew)#仅仅是y值 100*100的值

# 绘图
# 为了更明显地比较插值前后的区别,使用关键字参数interpolation='nearest'
# 关闭imshow()内置的插值运算。
pl.subplot(121)
im1=pl.imshow(fvals, extent=[-1,1,-1,1], cmap=mpl.cm.hot, interpolation='nearest', origin="lower")#pl.cm.jet
#extent=[-1,1,-1,1]为x,y范围 favals为
pl.colorbar(im1)

pl.subplot(122)
im2=pl.imshow(fnew, extent=[-1,1,-1,1], cmap=mpl.cm.hot, interpolation='nearest', origin="lower")
pl.colorbar(im2)
pl.show()

 

左侧图像展示原始离散数据分布,右侧图像为经过二维插值处理后的结果。

二维插值的三维可视化展示


# -*- coding: utf-8 -*-
"""
演示二维插值。
"""
# -*- coding: utf-8 -*-
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
from scipy import interpolate
import matplotlib.cm as cm
import matplotlib.pyplot as plt

def func(x, y):
 return (x+y)*np.exp(-5.0*(x**2 + y**2))

# X-Y轴分为20*20的网格
x = np.linspace(-1, 1, 20)
y = np.linspace(-1,1,20)
x, y = np.meshgrid(x, y)#20*20的网格数据

fvals = func(x,y) # 计算每个网格点上的函数值 15*15的值

fig = plt.figure(figsize=(9, 6))
#Draw sub-graph1
ax=plt.subplot(1, 2, 1,projection = '3d')
surf = ax.plot_surface(x, y, fvals, rstride=2, cstride=2, cmap=cm.coolwarm,linewidth=0.5, antialiased=True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
plt.colorbar(surf, shrink=0.5, aspect=5)#标注

#二维插值
newfunc = interpolate.interp2d(x, y, fvals, kind='cubic')#newfunc为一个函数

# 计算100*100的网格上的插值
xnew = np.linspace(-1,1,100)#x
ynew = np.linspace(-1,1,100)#y
fnew = newfunc(xnew, ynew)#仅仅是y值 100*100的值 np.shape(fnew) is 100*100
xnew, ynew = np.meshgrid(xnew, ynew)
ax2=plt.subplot(1, 2, 2,projection = '3d')
surf2 = ax2.plot_surface(xnew, ynew, fnew, rstride=2, cstride=2, cmap=cm.coolwarm,linewidth=0.5, antialiased=True)
ax2.set_xlabel('xnew')
ax2.set_ylabel('ynew')
ax2.set_zlabel('fnew(x, y)')
plt.colorbar(surf2, shrink=0.5, aspect=5)#标注

plt.show()

左图所示的二维数据集因样本点较少,函数值分布显得较为粗糙。右图则对二维样本数据应用三次样条插值,通过拟合生成更多中间数据点的样本值,使得绘图后的图像在视觉上明显更加光滑连续。

以上内容涵盖了本文的核心知识点,希望能为读者的学习提供有效帮助,也欢迎大家继续支持本站获取更多技术资源。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表