这是 scipy.interpolate.interp1d 中的错误吗?

Is this an error in scipy.interpolate.interp1d?

当使用零阶插值时,我发现输入数组中的最后一个 Y 值没有return编辑为 X 数组中的最后一个值:

from scipy.interpolate import interp1d

xx = [0.0, 1.0, 2.0]
xi = interp1d(xx, xx, kind='zero')
print(xi(xx))

似乎应该 return [0., 1., 2.] 但它 return 是 [0., 1., 1.]。 xx 中的最后一个值被认为在插值范围内,但未被 return 编辑为最后一个点的值。该文档没有提供 'zero' 的详细信息,但我希望它会:

a) 引发 ValueError 因为输入值被认为定义了半封闭范围 [0., 1.) 和 [1., 2.) 上的值,从而使 2.0 未定义,或

b) return 2.0 因为范围是 [0., 1.), [1., 2.) 和 [2., 2.)

interp1d 函数似乎认为正确答案是:

c) return 1.0 因为最后一个区间是特例,定义为闭区间 [1., 2.]

有没有正确的选择?如果有,是interp1d实现的吗?

零阶样条是分段常量,在节点处有不连续点,这里是插值点,所以xi(1.0-1e-13) == 0xi(1.0+1e-13) == 1

interp1d中的插值区间定义为闭合的,[0, 2]。原则上人们会期望有一个浮点值,x=2.0,它给出结果 2.0

然而,正如上面的评论所述,这里的样条实现来自 FITPACK,它将 k=0 样条定义为从右边的结处连续,除了最后一个间隔不同。我不知道原因 --- Fortran 代码可以追溯到 80 年代。我的猜测是它的工作方式没有特定原因,可能除了使用 B 样条表示编写这样的代码稍微方便一些之外。

我认为这种行为是 bug/quirk,但由于 x 值中存在的任何舍入误差都会使其影响为零,因此它的解决优先级一直很低。 (要考虑的一个方面是,由于没有具体说明它的作用,它是由实现定义的;破坏向后兼容可能比问题本身更糟糕。)

编辑:如另一个答案中所述,样条实际上是由splmake构造的;这个例程不是来自 FITPACK。不看最后的间隔行为是由于拟合还是构造就不能说。

根据source the interval is between [0, 2], including 2. The return from creating the spline is the cvals splmake(xx, xx, 0)[1] --> array([0.0, 1.0]). Following the source through we'll get to a call to evaluate the spline at a point which results in spleval(splmake(xx, xx, 0), 2) --> array(1.0). To answer your question, there's not really an answer it was just implemented this way, and if you think if the original array as encompassing the valid range I think it makes sense - but perhaps there should be a note about this particular evaluation, in which case you could always submit a request here。我不能发表评论,否则我会但希望它能回答你的问题。