为什么在scipy中使用interp1d函数时,当x数组的前两个值相同时会返回NaN?(fill_value = 0)

6
import numpy as np
from scipy.interpolate import interp1d

x = np.array([ 0,  0,   0,  0,   0,  30])
time = np.array([ 5,  5,  10,  10,  10,  20])

intx = interp1d(time,x,'linear', 0, True, False, 0)
print intx([4,5,5,6,10,11,20, 20.0001])

>>> [  0.  nan  nan   0.   0.   3.  30.   0.]

正如你所见,在除了时间值等于第一对值的所有情况下,插值器都会返回一个实数。

我知道有numpy.unique()这个函数,但这只是一个学术问题。这是在iPython中运行的Anaconda Python 2.7。

谢谢!

2个回答

8

您的问题在于您正在尝试插值不在区间内的点,这将导致scipy.interpolate.interp1d在尝试计算两个点之间的斜率时发出RuntimeWarning警告(它在interpolate.py大约416行左右发生):

slope = (y_hi - y_lo) / (x_hi - x_lo)[:, None]

当你在区间内移动你的点时,会发生什么:

>>> import numpy as np
>>> from scipy.interpolate import interp1d
>>> x = np.array([ 5,  5,  10,  10,  10,  20])
>>> y = np.array([ 0,  0,   0,  0,   0,  30])
>>> X = np.array([5.1,5.1,5.1,6,10,11,20, 19.999])
>>> f = interp1d(x,y,'linear', 0, True, False, 0)
>>> Y = f(X)
 [  0.      0.      0.      0.      0.      3.     30.     29.997]

如果你绘制出它,你会看到一切都是有意义的: enter image description here 这就是interp1d的工作原理:
  1. You pass x and yto interp1d and it creates a f callable method
  2. Then you pass the new x_new values in which you want to evaluate f and it performs the following steps:

    • Find where in the original data, the values to interpolate would be inserted.

      >>> x_new_indices = np.searchsorted(x, X)
      
    • Clip x_new_indices so that they are within the range of x indices and at least 1. Removes mis-interpolation of x_new[n] = x[0]

      >>> x_new_indices = x_new_indices.clip(1, len(x)-1).astype(int)
      
    • Calculate the slope of regions that each x_new value falls in.

      >>> lo = x_new_indices - 1
      >>> hi = x_new_indices
      >>> x_lo = x[lo]
      >>> x_hi = x[hi]
      >>> y_lo = y[lo]
      >>> y_hi = y[hi]
      
    • Calculate the actual value for each entry in x_new.

      >>> slope = (y_hi - y_lo) / (x_hi - x_lo)[:, None]
      >>> y_new = slope*(x_new - x_lo)[:, None] + y_lo
      

好的回答!让我确认一下我的理解。所以,当我将5作为“x_new”(我们称之为five)输入时,interp1d会将five排序到我的数组中,使得[5 5 10 10 10 20] 变成 [five 5 5 10 10 10 20]。我的假设是出于微不足道的原因,新的重复项总是放在现有相同条目的左侧。然后您提到的进程,确保索引至少为1,重新排列该数组以变成[5 five 5 10 10 10 20]。因此,斜率为“NaN”,因为“x_lo”=5且“x_hi”=5。最后,“y_new = NaN*0” =“NaN”。 - SkinnyTony

1
在上述情况下,我建议仅对Y变量进行采样点。例如,请考虑以下点。
x= [275, 275]
y= [120, 120]

上述点表示与Y轴平行的直线。因此,该直线的斜率未定义。因此,您可以仅为Y变量取样点,并为每个样本复制X变量的值。您会发现以下情节很直观。
图1- Two initial points 图2- Sample only y points keeping x same!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接