Python Numpy polyfit结果与SciPy插值不同

时间:2018-05-26 12:39:38

标签: python numpy scipy extrapolation

我必须使用较旧的scipy版本,不能推断。 在scipy 1.1.0中,推断按预期工作,给出了正确的结果。 由于我不能在我的应用程序中使用它,我想使用numpy polyfit。 但结果是不同的,而scipy和bisect结果的插值是相同的。

class InterExtraPolate(object):
  def __init__(self, x_list, y_list):
    if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
      raise ValueError("x_list must be in strictly ascending order!")
    self.x_list = map(float, x_list)
    self.y_list = map(float, y_list)
  def __getitem__(self, x):
    from scipy import interpolate
    f=interpolate.interp1d(self.x_list,self.y_list, fill_value='extrapolate')
    return f(x)


class npInterExraPolate(object):
  def __init__(self, x_list, y_list):
    import numpy as np
    if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
      raise ValueError("x_list must be in strictly ascending order!")
    self.x_list = map(float, x_list)
    self.y_list = map(float, y_list)
    self.fit=np.polyfit(self.x_list,self.y_list, 1)

  def __getitem__(self, x):
    import numpy as np
    f=np.poly1d(self.fit)
    return f(x)

##Main


ie   =  InterExtraPolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4])
npie = npInterExraPolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4])

my_xl = [0.5,1.1,6.3]

print ie[my_xl]

print npie[my_xl]

==== 如何使numpy polyfit / poly1d结果等于scipy外推结果?

2 个答案:

答案 0 :(得分:3)

如果您绘制实际结果,您将很快看到为什么线性插值不是线性拟合:插值在点到点之间起作用,而拟合则考虑所有点: enter image description here

这并没有解释如何正确地做到这一点,但应解释为什么它会失败。

我认为没有办法使用多项式拟合作为插值的替代方法,结果完全相同。

您必须自己编写插值代码,或者找到安装更新版SciPy的方法。

对于初学者,请查看在安装SciPy时是否可以使用--user选项。你没有提到为什么你必须使用旧版本,以及阻止你安装新版本的原因。这可能是另一个要问的问题:如何规避安装最新版SciPy时的任何限制。

答案 1 :(得分:0)

我使用bisect_left解决了我的需求,并在与外斜坡相同的斜坡中添加了外推部分。

class bsInterExtraPolate(object):
  def __init__(self, x_list, y_list):
    if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
      raise ValueError("x_list must be in strictly ascending order!")
    x_list = self.x_list = map(float, x_list)
    y_list = self.y_list = map(float, y_list)
    intervals = zip(x_list, x_list[1:], y_list, y_list[1:])
    self.slopes = [(y2 - y1)/(x2 - x1) for x1, x2, y1, y2 in intervals]

  def __getitem__(self, x):
    #-- expanding for lin extrapolation using outer slopes
    from bisect import bisect_left
    if type(x)==list:
      yval=[]
      for xval in x:
        if xval < self.x_list[0]:
          i=0
        elif xval > self.x_list[-1]:
          i=len(self.x_list)-2
        else:
          i = bisect_left(self.x_list, xval) - 1
        ytmp=self.y_list[i] + self.slopes[i] * (xval - self.x_list[i])
        yval.append(ytmp)
    else:
      xval=float(x)
      if xval < self.x_list[0]:
        i=0
      elif xval > self.x_list[-1]:
        i=len(self.x_list)-2
      else:
        i = bisect_left(self.x_list, xval) - 1
      ytmp=self.y_list[i] + self.slopes[i] * (xval - self.x_list[i])
      yval=ytmp
    return yval