作为python的初学者,我开始实现我已经在Matlab中实现的想法。我想识别数组的交叉点(x,y坐标),没有给出明确的函数。也就是说,只有int值的数组可能与float-coordinates有交集。因此,www提供以下代码,请参阅附件。
通过点击scipy
和interpolate
安装后,我无法解决即将到来的
ERROR: AttributeError: 'module' object has no attribute 'PiecewisePolynomial'.
搜索功能没有帮助。
我很乐意接受
的帮助或/和
PS:由于某些间隔中交叉点的唯一性,在matlab上通过差异计算交叉点是不合适的
import scipy.interpolate as interpolate
import scipy.optimize as optimize
import numpy as np
x1=np.array([1.4,2.1,3,5.9,8,9,23])
y1=np.array([2.3,3.1,1,3.9,8,9,11])
x2=np.array([1,2,3,4,6,8,9])
y2=np.array([4,12,7,1,6.3,8.5,12])
p1 = interpolate.PiecewisePolynomial(x1,y1[:,np.newaxis])
p2 = interpolate.PiecewisePolynomial(x2,y2[:,np.newaxis])
def pdiff(x):
return p1(x)-p2(x)
xs=np.r_[x1,x2]
xs.sort()
x_min=xs.min()
x_max=xs.max()
x_mid=xs[:-1]+np.diff(xs)/2
roots=set()
for val in x_mid:
root,infodict,ier,mesg = optimize.fsolve(pdiff,val,full_output=True)
# ier==1 indicates a root has been found
if ier==1 and x_min<root<x_max:
roots.add(root[0])
roots=list(roots)
print(np.column_stack((roots,p1(roots),p2(roots))))
答案 0 :(得分:1)
正如我在评论中指出的那样,您尝试使用的方法在较新版本的scipy中不可用,但它并没有按照您的预期执行。
我的建议是使用numpy.interp
1 或scipy.interpolate.interp1d
构建函数的线性插值器,然后使用fsolve
来查找所有可能的函数交叉点。由于fsolve
(非常类似于MATLAB&#39; s fzero
)一次只能找到一个交叉点,因此您确实需要遍历数据中的部分以查找交叉点。
import scipy.interpolate as interpolate
import scipy.optimize as optimize
import numpy as np
x1 = np.array([1.4,2.1,3,5.9,8,9,23])
y1 = np.array([2.3,3.1,1,3.9,8,9,11])
x2 = np.array([1,2,3,4,6,8,9])
y2 = np.array([4,12,7,1,6.3,8.5,12])
# linear interpolators
opts = {'fill_value': 'extrapolate'}
f1 = interpolate.interp1d(x1,y1,**opts)
f2 = interpolate.interp1d(x2,y2,**opts)
# possible range for an intersection
xmin = np.min((x1,x2))
xmax = np.max((x1,x2))
# number of intersections
xuniq = np.unique((x1,x2))
xvals = xuniq[(xmin<=xuniq) & (xuniq<=xmax)]
# note that it's bad practice to compare floats exactly
# but worst case here is a bit of redundance, no harm
# for each combined interval there can be at most 1 intersection,
# so looping over xvals should hopefully be enough
# one can always err on the safe side and loop over a `np.linspace`
intersects = []
for xval in xvals:
x0, = optimize.fsolve(lambda x: f1(x)-f2(x), xval)
if (xmin<=x0<=xmax
and np.isclose(f1(x0),f2(x0))
and not any(np.isclose(x0,intersects))):
intersects.append(x0)
print(intersects)
print(f1(intersects))
print(f2(intersects))
除了来自算法中更有问题的部分的一些运行时警告之外,上面找到了函数的两个交叉点:
关键步骤是检查fsolve
的结果是否为新结果(不接近您以前的根),并确实找到了给定x0
的根。
或者,您可以使用xvals
中定义的区间,检查每个区间的分段线性函数,并分析检查具有这些参数的两条线(我的意思是x1=xvals[i],x2=xvals[i+1], y11=f1[x1], y12=f1[x2]
等)是否有交点给定的部分。您可能能够对此方法进行矢量化,您不必担心结果中的随机性,并且您只需要注意数据中可能存在的奇点(np.diff(xvals)
很小,而您被这除掉了。)
1 numpy.interp
没有定义插值函数,而是直接计算网格上的插值。为了使用此函数执行相同操作,您必须为给定的numpy.interp
值定义一个调用x
的函数。由于零搜索期间的大量功能评估,这可能不如上述效率低。