不均匀间隔点之间的直观插值
Intuitive interpolation between unevenly spaced points
我有下面的图表,我想使用 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 和 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 算法希望保持数据点之间的拟合单调,因此将最小点数字化会很有用(无论您使用哪种算法,这都可能是个好主意)。