不规则点间的直观插值

4
我有以下图表,我想用Python和Matplotlib将其数字化为高质量的出版物级别的图表:

enter image description here

我使用了一个数字化程序,从其中一个数据集中获取了一些样本:

x_data = np.array([
1,
1.2371,
1.6809,
2.89151,
5.13304,
9.23238,
])

y_data = np.array([
0.0688824,
0.0490012,
0.0332843,
0.0235889,
0.0222304,
0.0245952,
])

我已经尝试了三种不同的方法来拟合这些数据点。第一种方法是使用scipy.interpolate import spline通过数据点绘制样条曲线,结果如下(实际数据点用蓝色标记): enter image description here 显然这个结果不好。
我的第二次尝试是使用scipy.optimize import curve_fit绘制曲线拟合,使用一系列不同阶数的多项式,即使是四次多项式的答案也是无用的(低阶的更加无用): enter image description here 最后,我使用scipy.interpolate import interp1d来尝试在数据点之间进行插值。线性插值显然会产生预期的结果,但线条是直的,这个练习的整个目的是得到一个漂亮的平滑曲线: enter image description here 如果我使用三次插值,结果是垃圾,但二次插值结果略好: enter image description here 但还不够好,我认为interp1d不能进行高阶插值。
有没有人有一个好的方法来做到这一点?也许我最好尝试在IPE或其他什么地方做这个?谢谢!
1个回答

11

标准的三次样条插值在非均匀间距数据点之间的合理外观插值不太好。幸运的是,有许多其他的插值算法,Scipy提供了其中的一些。以下是应用于您的数据的一些示例:

输入图像描述

import numpy as np
from scipy.interpolate import spline, UnivariateSpline, Akima1DInterpolator, PchipInterpolator
import matplotlib.pyplot as plt

x_data = np.array([1, 1.2371, 1.6809, 2.89151, 5.13304, 9.23238])

y_data = np.array([0.0688824, 0.0490012, 0.0332843, 0.0235889, 0.0222304, 0.0245952])

x_data_smooth = np.linspace(min(x_data), max(x_data), 1000)
fig, ax = plt.subplots(1,1)

spl = UnivariateSpline(x_data, y_data, s=0, k=2)
y_data_smooth = spl(x_data_smooth)
ax.plot(x_data_smooth, y_data_smooth, 'b')

bi = Akima1DInterpolator(x_data, y_data)
y_data_smooth = bi(x_data_smooth)
ax.plot(x_data_smooth, y_data_smooth, 'g')

bi = PchipInterpolator(x_data, y_data)
y_data_smooth = bi(x_data_smooth)
ax.plot(x_data_smooth, y_data_smooth, 'k')

ax.plot(x_data_smooth, y_data_smooth)
ax.scatter(x_data, y_data)

plt.show()

我建议您查看这些,以及其他一些,并找到与您认为正确的外观相匹配的一个。但是,您可能还想尝试更多的点。例如,我认为PCHIP算法想要保持数据点之间的拟合单调性,因此数字化您的最小点将很有用(无论您使用哪种算法,这都是个好主意)。


1
谢谢 @tom10 提供的详尽答案!我一定会仔细查看,你所做的所有适配对我的需求来说都足够好! - Jonny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接