numpy.interp周期插值代码解析及可视化结果疑问
Numpy周期插值结果不在绘制曲线上的原因解析
问题背景
用户参考Numpy官方文档的周期插值示例:
Interpolation with periodic x-coordinates:
x = [-180, -170, -185, 185, -10, -5, 0, 365]
xp = [190, -190, 350, -350]
fp = [5, 10, 3, 4]
np.interp(x, xp, fp, period=360)
array([7.5 , 5. , 8.75, 6.25, 3. ,3.25, 3.5 , 3.75])
自行编写复现代码后,用plt.plot(xp, fp)绘制原始节点连线,却发现插值得到的橙色点不在这条线上,对此产生疑惑。用户复现代码如下:
import matplotlib.pyplot as plt import numpy as np x = [-180, -170, -185, 185, -10, -5, 0, 365] xp = [190, -190, 350, -350] fp = [5, 10, 3, 4] y=np.interp(x, xp, fp, period=360) print(x) print(y) plt.grid() plt.plot(xp, fp) plt.plot(x,y,'o') plt.show()
核心原因
Numpy的周期插值不是直接使用原始xp的顺序进行连线插值,而是先完成两个关键步骤:
- 将所有x坐标(包括xp和待插值的x)映射到周期等价区间内(默认是
[-period/2, period/2),即[-180, 180)) - 对映射后的xp按从小到大排序,再基于排序后的节点进行线性插值,同时因为周期性,排序后的首尾节点是相连的
具体拆解验证
以周期360为例,先处理原始xp的等价坐标:
| 原始xp | 等价坐标(映射到[-180,180)) | fp |
|---|---|---|
| 190 | 190-360 = -170 | 5 |
| -190 | -190+360 = 170 | 10 |
| 350 | 350-360 = -10 | 3 |
| -350 | -350+360 = 10 | 4 |
将等价后的xp按从小到大排序,得到插值用的节点序列:xp_sorted = [-170, -10, 10, 170],对应fp_sorted = [5, 3, 4, 10]
再处理待插值x的等价坐标:
| 原始x | 等价坐标 | 插值计算逻辑 | 结果y |
|---|---|---|---|
| -180 | 180(等价于-180) | 在170(y=10)和-170(y=5)的周期中点,取平均值 | 7.5 |
| -170 | -170 | 匹配节点,直接取fp值 | 5 |
| -185 | 175 | 在170(y=10)和-170(y=5)之间插值,距离170为5,总周期跨度360,计算得(5-10)/( -170-170 )*(175-170)+10=8.75 | 8.75 |
| 185 | -175 | 在-170(y=5)和-10(y=3)之间插值,距离-170为5,跨度160,计算得(3-5)/( -10+170 )*(-175+170)+5=6.25 | 6.25 |
剩余x的插值逻辑类似,结果完全匹配官方输出。
修正后的可视化代码
要看到插值点落在曲线上,需要基于周期等价且排序后的节点绘制插值曲线:
import matplotlib.pyplot as plt import numpy as np x = [-180, -170, -185, 185, -10, -5, 0, 365] xp = [190, -190, 350, -350] fp = [5, 10, 3, 4] period = 360 # 转换xp到周期等价区间并排序 xp_periodic = np.mod(xp + period/2, period) - period/2 sorted_idx = np.argsort(xp_periodic) xp_sorted = xp_periodic[sorted_idx] fp_sorted = np.array(fp)[sorted_idx] # 计算插值结果 y = np.interp(x, xp, fp, period=period) # 生成密集x值绘制完整插值曲线 x_dense = np.linspace(-180, 180, 1000) y_dense = np.interp(x_dense, xp, fp, period=period) plt.grid(True) plt.scatter(xp_sorted, fp_sorted, color='blue', label='周期等价节点(排序后)') plt.plot(x_dense, y_dense, color='blue', linestyle='--', label='周期插值曲线') plt.scatter(x, y, marker='o', color='orange', label='插值结果点') plt.legend() plt.xlabel('x(周期等价坐标)') plt.ylabel('y') plt.title('Numpy周期插值可视化') plt.show()
运行这段代码后,所有橙色插值点都会落在蓝色的周期插值曲线上,完全符合Numpy内部的插值逻辑。
内容的提问来源于stack exchange,提问作者KansaiRobot
相关产品推荐
相关产品推荐

