给出两条曲线的交点我有两个数据集:(X,Y 1)和(x,y2)上。我想找到这两条曲线相互交叉的位置。我们的目标是类似这样的问题:Intersection of two graphs in Python, find the x value:查找(X,Y)数据以高精度在Python
然而,所描述的方法只发现交点到最接近的数据点。我想找到比原始数据间距具有更高精度的曲线的交点。一种选择是简单地重新插值到更精细的网格。这是有效的,但是然后精度由我选择用于重新插值的点的数量决定,这是任意的,并且需要在精度和效率之间进行权衡。
可替换地,我可以使用scipy.optimize.fsolve
查找数据集的所述两个花键插补的确切交集。这很好,但它不容易找到多个交点,要求我为交点提供合理的猜测,并且可能不能很好地缩放。 (最后,我想找到的几千套(X,Y1,Y2)的交叉点,所以一个有效的算法将是很好的。)
这是我到目前为止所。任何改进想法?
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate, scipy.optimize
x = np.linspace(1, 4, 20)
y1 = np.sin(x)
y2 = 0.05*x
plt.plot(x, y1, marker='o', mec='none', ms=4, lw=1, label='y1')
plt.plot(x, y2, marker='o', mec='none', ms=4, lw=1, label='y2')
idx = np.argwhere(np.diff(np.sign(y1 - y2)) != 0)
plt.plot(x[idx], y1[idx], 'ms', ms=7, label='Nearest data-point method')
interp1 = scipy.interpolate.InterpolatedUnivariateSpline(x, y1)
interp2 = scipy.interpolate.InterpolatedUnivariateSpline(x, y2)
new_x = np.linspace(x.min(), x.max(), 100)
new_y1 = interp1(new_x)
new_y2 = interp2(new_x)
idx = np.argwhere(np.diff(np.sign(new_y1 - new_y2)) != 0)
plt.plot(new_x[idx], new_y1[idx], 'ro', ms=7, label='Nearest data-point method, with re-interpolated data')
def difference(x):
return np.abs(interp1(x) - interp2(x))
x_at_crossing = scipy.optimize.fsolve(difference, x0=3.0)
plt.plot(x_at_crossing, interp1(x_at_crossing), 'cd', ms=7, label='fsolve method')
plt.legend(frameon=False, fontsize=10, numpoints=1, loc='lower left')
plt.savefig('curve crossing.png', dpi=200)
plt.show()
是不是总有精度和效率之间的权衡?您可以继续插入更细的网格,直到您的答案收敛到可容忍的数量范围内。 – Crispin
是不是来自网格交叉点的近似信息正是您设置样条交叉问题所需的信息?我能看到的唯一问题就是如果在单个网格单元中有多个交点。我将运行网格交叉点,然后使用其中的答案来解决样条交集,使用样条线限制到发现的网格交点附近的几个单元格。 – mcdowella
waterboy5281,我想你是对的,在给定相同算法的情况下,通常会在效率和精度之间进行权衡。但是,更好的算法通常既快速又精确。 @mcdowella,我喜欢通过“最近的数据点”法求交点的近似位置,然后使用该信息以使其更容易找到精确交叉点的想法。我会尽力实现这一点。 – DanHickstein