如何在不排序x数组的情况下使用make_interp_spline进行曲线插值?
解决make_interp_spline要求x有序无重复的问题
make_interp_spline的底层实现依赖严格单调且无重复的x数组,这是硬性要求,无法直接绕过。以下两种方案可以解决你的问题:
方案一:处理数据后继续使用make_interp_spline
如果你的需求是基于x的单值函数(每个x对应唯一y),需要先清理x数组的重复值,再排序:
- 去重并处理重复x对应的y:对相同x的y值取均值、中位数,或保留第一个/最后一个值(根据业务需求选择)
- 排序:将去重后的x和对应的y按x排序,满足
make_interp_spline的输入要求
示例代码:
from scipy.interpolate import make_interp_spline import numpy as np import matplotlib.pyplot as plt x = np.array([-31,-30,-30,-32,-36,-39]) y = np.array([60,62,64,65,64,64]) # 处理重复x:对相同x的y取均值 unique_x, indices = np.unique(x, return_inverse=True) mean_y = np.bincount(indices, weights=y) / np.bincount(indices) # 按x排序 sorted_idx = np.argsort(unique_x) sorted_x = unique_x[sorted_idx] sorted_y = mean_y[sorted_idx] # 生成平滑曲线 X_Y_Spline = make_interp_spline(sorted_x, sorted_y) X_ = np.linspace(sorted_x.min(), sorted_x.max(), 500) Y_ = X_Y_Spline(X_) # 绘图 plt.plot(x, y, 'o', label='原始点') plt.plot(X_, Y_, label='平滑曲线') plt.legend() plt.show()
方案二:使用参数化样条插值(无需排序x)
如果只是要绘制经过原始点的平滑曲线(不要求x是函数的自变量),可以用splprep做参数化插值。它将曲线视为参数t的函数,不要求x有序或无重复:
示例代码:
from scipy.interpolate import splprep, splev import numpy as np import matplotlib.pyplot as plt x = np.array([-31,-30,-30,-32,-36,-39]) y = np.array([60,62,64,65,64,64]) # 参数化拟合,s=0表示严格经过所有点,调大s可增加平滑度 tck, u = splprep([x, y], s=0) # 生成更多采样点 u_new = np.linspace(u.min(), u.max(), 500) x_new, y_new = splev(u_new, tck) # 绘图 plt.plot(x, y, 'o', label='原始点') plt.plot(x_new, y_new, label='平滑曲线') plt.legend() plt.show()
注意事项
- 如果你的场景要求x作为自变量(即每个x对应唯一y值),必须选择方案一,因为函数的定义不允许x重复或无序
- 方案二适合绘制路径类曲线,不关注x是否为单值自变量的场景
内容的提问来源于stack exchange,提问作者wabash
相关产品推荐
相关产品推荐

