我有以下图表,我想使用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
使用一系列不同的顺序polinimials绘制曲线拟合。即使是四阶多项式,答案也是无用的(低阶的更无用):
最后,我使用scipy.interpolate import interp1d
尝试在数据点之间进行插值。线性插值显然会产生预期的结果,但线条是直线的,本练习的目的是获得一条漂亮的平滑曲线:
如果我然后使用三次插值,我得到一个rubish结果,但是二次插值会产生稍微好一点的结果:
但它还没有完全存在,我认为interp1d
不能进行更高阶的插值。
那里有没有人有这么好的方法?也许我会尝试在IPE或其他什么方面做得更好?
谢谢!
答案 0 :(得分:8)
标准三次样条曲线在非常不均匀间隔的数据点之间的合理外观上并不是很好。幸运的是,还有很多其他插值算法和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算法希望保持数据点之间的拟合单调,因此将最小点数字化将是有用的(无论您使用何种算法,这可能都是个好主意。)