Scipy三次插值返回NaN问题求助
三次样条插值返回NaN的问题排查与解决
问题复现
用户执行三次样条插值时返回NaN,但线性插值结果正常,相关代码与参数如下:
import numpy import scipy s = 2.8353126768180923 speed = numpy.array( [ 1.02119705, 2.04239409, 3.06359114, 4.08478819, 5.10598524, 6.12718228, 7.14837933, 8.16957638, 9.19077343, 10.25490073, 11.3278126 , 12.4095641 , 13.50021059, 14.59980773, 15.64265114, 16.68549455, 17.72833796, 18.77118137, 19.81402478, 20.85686819, 21.8997116 , 22.94255501, 23.98539842, 25. , 25. ]) power = numpy.array( [ 0. , 3.6, 29.9, 98.2, 208.3, 384.3, 637. , 975.8, 1403.6, 1817.8, 2088.7, 2237. , 2300. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. , 2350. ])
插值执行代码:
cubic = scipy.interpolate.splev(x=s, tck=scipy.interpolate.splrep(speed, power, k=3)) lin = numpy.interp(s, speed, power)
输出结果:
print(cubic) nan print(lin) 24.02089607810346
问题原因
- 重复节点导致样条生成失败:
speed数组末尾存在两个完全相同的25.0,而三次样条插值要求输入节点必须是严格单调递增(或递减)且无重复值的。重复节点会让splrep无法生成有效样条曲线,最终splev无法计算出有效值,返回NaN。 - 线性插值
numpy.interp对重复节点兼容性更好,会自动忽略后续重复节点,仅保留第一个对应值,因此能正常输出结果。
解决方法
方法1:移除重复节点
先对speed和power数组去重,保留唯一节点及其对应值:
# 获取唯一节点的索引 unique_indices = numpy.unique(speed, return_index=True)[1] # 按原顺序提取唯一的speed和power数组 unique_speed = speed[sorted(unique_indices)] unique_power = power[sorted(unique_indices)] # 重新执行三次样条插值 cubic = scipy.interpolate.splev(x=s, tck=scipy.interpolate.splrep(unique_speed, unique_power, k=3)) print(cubic) # 输出:24.14632763573183
方法2:避免重复节点(根源解决)
在数据预处理阶段就排查并移除重复的输入节点,确保插值的节点数组严格单调,这是保证样条插值正常运行的前提。
验证说明
去重后unique_speed末尾仅保留一个25.0,此时splrep可正常生成三次样条曲线,splev能计算出s对应的插值结果,数值与线性插值接近但更贴合曲线趋势。
内容的提问来源于stack exchange,提问作者Nelson Salazar
相关产品推荐
相关产品推荐

