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

Python 这是scipy.interpolate.interp1d中的错误吗?,python,scipy,Python,Scipy,当使用零阶插值时,我发现输入数组中的最后一个Y值没有为X数组中的最后一个值返回: from scipy.interpolate import interp1d xx = [0.0, 1.0, 2.0] xi = interp1d(xx, xx, kind='zero') print(xi(xx)) 看起来它应该返回[0,1,2],但它返回[0,1,1]。xx中的最后一个值被视为在插值范围内,但不会作为最后一个点的值返回。该文档没有提供“零”的详细信息,但我希望它可以: a) 由于输入值被视为

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

from scipy.interpolate import interp1d

xx = [0.0, 1.0, 2.0]
xi = interp1d(xx, xx, kind='zero')
print(xi(xx))
看起来它应该返回[0,1,2],但它返回[0,1,1]。xx中的最后一个值被视为在插值范围内,但不会作为最后一个点的值返回。该文档没有提供“零”的详细信息,但我希望它可以:

a) 由于输入值被视为定义半封闭范围[0,1]和[1,2]上的值,从而导致2.0未定义,因此引发ValueError,或

b) 返回2.0,因为范围是[0,1]、[1,2]和[2,2]

函数看起来是正确的答案是:

c) 返回1.0,因为最后一个范围是一个特例,定义为闭合区间[1,2]


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

零阶样条曲线是分段常数,并且在节点处具有不连续性,这里是插值点,因此
xi(1.0-1e-13)==0
xi(1.0+1e-13)==1

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

然而,正如上面的评论所指出的,这里的样条线实现来自FITPACK,它将k=0样条线定义为从右侧开始在节点处连续,除了最后一个不同的间隔。我不知道原因——Fortran代码可以追溯到80年代。我猜它的工作方式没有具体的原因这可能是因为这样编写代码时使用B样条表示稍微方便一些

这种行为在我看来是A,但是由于x值中的任何舍入误差使得它的影响为零,所以它优先于地址。(一方面考虑到它没有做什么,它是由实现定义的;反向向后的COMPAT可能比问题本身更坏。)


编辑:如另一个答案中所述,样条曲线实际上是由
splmake
构造的;此例程不是来自FITPACK。如果不查看最终的间隔行为是由拟合还是构造造成的,则不能不说。

根据参数,间隔介于[0,2]之间,包括2。创建样条曲线的返回值是cvals
splmake(xx,xx,0)[1]-->array([0.0,1.0])
。在源代码之后,我们将调用在一个点上计算样条曲线,结果是
spleval(splmake(xx,xx,0),2)-->array(1.0)
。要回答您的问题,没有真正的答案,它只是以这种方式实现的,如果您认为原始数组包含有效范围,我认为这是有意义的-但也许应该有一个关于此特定评估的说明,在这种情况下,您可以始终提交一个请求。我不能评论,否则我会希望它能回答您的问题。

在本例中,
interp1d
只需将任务传递给FITPACK,请求一个零阶样条曲线。这是一个FORTRAN库,有自己的历史记录和文档。是的,这是一个正确的语句,所有数据在调用_FITPACK之前都与预期一致。_bspleval()来自spleval()在scipy中。您的评论是指FITPACK的答案在定义上是正确的,还是仅仅意味着它是一个寻找答案的更好的地方?谢谢!FITPACK将是寻找答案的地方。值得一提的是,Spline的Wiki定义使用了一个封闭的最终区间。我没有看到Python代码实现其自身边界的证据检查。请注意,此行为似乎在scipy 0.18.1(屈服[0.1.1.])和0.19.0(屈服[0.1.2])之间发生了变化