np.array intersection // AttributeError:'module'对象没有属性'PiecewisePolynomial'

时间:2016-11-13 23:37:15

标签: python numpy scipy interpolation

作为python的初学者,我开始实现我已经在Matlab中实现的想法。我想识别数组的交叉点(x,y坐标),没有给出明确的函数。也就是说,只有int值的数组可能与float-coordinates有交集。因此,www提供以下代码,请参阅附件。

通过点击scipyinterpolate安装后,我无法解决即将到来的

ERROR: AttributeError: 'module' object has no attribute 'PiecewisePolynomial'.

搜索功能没有帮助。

我很乐意接受

的帮助
  1. 解决错误
  2. 或/和

    1. 以不同方式计算交叉点(scipy是唯一的方法吗?)
    2. 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))))
      

1 个答案:

答案 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))

除了来自算法中更有问题的部分的一些运行时警告之外,上面找到了函数的两个交叉点:

plot of functions

关键步骤是检查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的函数。由于零搜索期间的大量功能评估,这可能不如上述效率低。