You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Scipy或Numpy对分段常值点集进行插值?

分段常值信号插值问题解决方法

问题原因

UnivariateSpline默认采用平滑三次样条插值,其核心目标是生成平滑拟合曲线,而非复现阶跃式的分段常值信号。它会自动对采样数据进行平滑处理,因此插值结果必然偏离原信号的阶跃特征,无法与原曲线重合。

解决方案

要复现分段常值的阶跃信号,需使用阶跃插值(Piecewise Constant Interpolation)。以下是几种替代interp1d的现代实现方式:

方案1:用NearestNDInterpolator实现最近邻插值

该方法将每个点映射到最近的采样点值,对于你的采样密度,结果会与原信号高度吻合:

import numpy as np
from scipy.interpolate import NearestNDInterpolator
import matplotlib.pyplot as plt

N = 30
Ts = 0.2

times = np.arange(0.0, N * Ts, Ts)
signal = np.concatenate((1.5 * np.ones(10), -0.5 * np.ones(10), np.ones(10)))

# 准备采样点(需转为二维数组适配NearestNDInterpolator)
sample_times = times[::3].reshape(-1, 1)
sample_signal = signal[::3]

# 构建插值器并生成结果
interp = NearestNDInterpolator(sample_times, sample_signal)
signal_interp = interp(times.reshape(-1, 1))

plt.plot(times, signal, label='原信号')
plt.plot(times, signal_interp, label='插值结果', linestyle='--')
plt.legend()
plt.show()

方案2:手动构建分段常值插值

若明确知道原信号的分段规则,可直接通过区间判断生成完全匹配的插值结果:

import numpy as np
import matplotlib.pyplot as plt

N = 30
Ts = 0.2

times = np.arange(0.0, N * Ts, Ts)
signal = np.concatenate((1.5 * np.ones(10), -0.5 * np.ones(10), np.ones(10)))

# 定义分段断点与对应常数值
breakpoints = [0.0, 2.0, 4.0, 6.0]
segment_values = [1.5, -0.5, 1.0]

# 生成插值信号
signal_interp = np.piecewise(times, 
                            [times < breakpoints[1], 
                             (times >= breakpoints[1]) & (times < breakpoints[2]), 
                             times >= breakpoints[2]],
                            segment_values)

plt.plot(times, signal, label='原信号')
plt.plot(times, signal_interp, label='插值结果', linestyle='--')
plt.legend()
plt.show()

方案3:用PPoly构建0次分段多项式

若需要类似UnivariateSpline的可复用插值器接口,可通过PPoly创建严格的分段常值插值器:

import numpy as np
from scipy.interpolate import PPoly
import matplotlib.pyplot as plt

N = 30
Ts = 0.2

times = np.arange(0.0, N * Ts, Ts)
signal = np.concatenate((1.5 * np.ones(10), -0.5 * np.ones(10), np.ones(10)))

sample_times = times[::3]
sample_signal = signal[::3]

# 构建0次分段多项式(每个区间系数为常数值)
coeffs = sample_signal[:-1].reshape(1, -1)
interp = PPoly(coeffs, sample_times)

signal_interp = interp(times)

plt.plot(times, signal, label='原信号')
plt.plot(times, signal_interp, label='插值结果', linestyle='--')
plt.legend()
plt.show()

方案选择建议

  • 方案1适合未知原信号分段规则的场景,仅依赖采样点即可生成近似结果;
  • 方案2适合已知分段规则的场景,实现简单且完全匹配原信号;
  • 方案3提供标准化插值器接口,适合需要多次复用插值逻辑的场景。

内容的提问来源于stack exchange,提问作者Barzi2001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:30:15