我有以下图表,我想使用 Python 和 Matplotlib 将其数字化为高质量的出版物级图表:
我使用数字化仪程序从 3 个数据集之一中获取了一些样本:
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,
])
我已经尝试了 3 种不同的方法来通过这些数据点拟合曲线。第一种方法是使用 scipy.interpolate import spline
通过点绘制样条这导致(实际数据点绘制为蓝色标记):
这显然不好。
我的第二次尝试是使用
scipy.optimize import curve_fit
使用一系列不同阶的多项式绘制曲线拟合。即使是四阶多项式,答案也毫无用处(低阶多项式更没用):最后,我使用
scipy.interpolate import interp1d
尝试在数据点之间进行插值。线性插值显然会产生预期的结果,但这条线是直的,这个练习的全部目的是获得一个很好的平滑曲线:如果我然后使用三次插值,我会得到一个垃圾结果,但是二次插值会产生稍微好一点的结果:
但它还没有完全到位,我不认为
interp1d
可以进行高阶插值。有没有人有这样做的好方法?也许我最好尝试在 IPE 或其他东西中做到这一点?
谢谢!
最佳答案
标准三次样条在间距非常不均匀的数据点之间进行合理的插值时不是很好。幸运的是,还有很多其他插值算法和 Scipy provides a number of them 。以下是一些适用于您的数据的方法:
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 算法希望保持数据点之间的拟合单调,因此数字化您的最小点将很有用(无论您使用何种算法,这可能都是一个好主意)。
关于python - 不均匀间隔点之间的直观插值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31221444/