Python中Cubic Spline插值报错:`x`必须仅含有限值,如何解决?
问题
我想在Python中对数据应用二阶低通Butterworth滤波器,之后用三次样条插值按每1米间隔重采样。已经尝试处理非有限值,但仍收到如下ValueError:
cs_v = CubicSpline(distance, filtered_v) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ raise ValueError("`x` must contain only finite values.") ValueError: `x` must contain only finite values.
相关代码
import numpy as np import pandas as pd from scipy.signal import butter, filtfilt from scipy.interpolate import CubicSpline, interp1d import matplotlib.pyplot as plt import plotly.graph_objects as go # Butterworth滤波器 def butterworth_filter(data, cutoff, fs, order=2): nyquist = 0.5 * fs normal_cutoff = cutoff / nyquist b, a = butter(order, normal_cutoff, btype='low', analog=False) y = filtfilt(b, a, data) return y # 确保数据数组为有限值 def ensure_finite(data): nans = np.isnan(data) | np.isinf(data) if np.any(nans): interp_func = interp1d(np.arange(len(data))[~nans], data[~nans], kind='linear', fill_value="extrapolate") data[nans] = interp_func(np.arange(len(data))[nans]) return data def handle_infinite(data, t): nans = np.isnan(data) | np.isinf(data) if np.any(nans): valid_mask = ~nans if valid_mask.sum() < 2: raise ValueError("No valid data.") interp_func = interp1d(t[valid_mask], data[valid_mask], kind='linear', fill_value="extrapolate") data[nans] = interp_func(t[nans]) return data # ... data = pd.read_excel(r"xy") t = data['Time'].values x = data['X'].values y = data['Y'].values v = data['speed'].values z = data['altitude'].values a = data['acceleration'].values distance = data['distance'].values # 将distance的初始NaN值设为0 if np.isnan(distance[0]): distance[0] = 0 # 确保distance数组递增 sorted_indices = np.argsort(distance) distance = distance[sorted_indices] x = x[sorted_indices] y = y[sorted_indices] v = v[sorted_indices] z = z[sorted_indices] a = a[sorted_indices] # 确保数据数组为有限值 v = ensure_finite(v) a = ensure_finite(a) z = ensure_finite(z) x = ensure_finite(x) y = ensure_finite(y) # Butterworth滤波 fs = 1 / (t[1] - t[0]) # 采样频率 cutoff = 0.3 # 截止频率 filtered_v = butterworth_filter(v, cutoff, fs) filtered_a = butterworth_filter(a, cutoff, fs) filtered_z = butterworth_filter(z, cutoff, fs) filtered_v = handle_infinite(filtered_v, t) filtered_a = handle_infinite(filtered_a, t) filtered_z = handle_infinite(filtered_z, t) print(filtered_v) print(filtered_z) # 重采样 distance_new = np.arange(0, distance[0], 1) # 每1米间隔 cs_v = CubicSpline(distance, filtered_v) cs_a = CubicSpline(distance, filtered_a) cs_z = CubicSpline(distance, filtered_z) cs_x = CubicSpline(distance, x) cs_y = CubicSpline(distance, y) v_cubic = cs_v(distance_new) a_cubic = cs_a(distance_new) z_cubic = cs_z(distance_new) x_cubic = cs_x(distance_new) y_cubic = cs_y(distance_new)
解决方案
错误核心是distance数组中仍存在非有限值(NaN/Inf),你仅处理了其他数据数组的异常值,未对distance做完整处理,同时代码还存在两处逻辑疏漏,修复步骤如下:
1. 完整处理distance的非有限值
在排序后,对distance应用你已有的异常值处理函数,同步修正时间数组t的对应关系:
# 确保distance数组递增 sorted_indices = np.argsort(distance) distance = distance[sorted_indices] t = t[sorted_indices] # 必须同步排序t,否则后续插值对应关系错乱 x = x[sorted_indices] y = y[sorted_indices] v = v[sorted_indices] z = z[sorted_indices] a = a[sorted_indices] # 处理distance的非有限值 distance = handle_infinite(distance, t)
2. 修正重采样范围逻辑
当前distance_new = np.arange(0, distance[0], 1)会生成空数组或仅覆盖极小范围,应改为覆盖整个distance的取值区间:
distance_new = np.arange(np.min(distance), np.max(distance)+1, 1)
3. 添加有效性检查(可选但推荐)
在创建三次样条前,添加断言确保distance无异常值:
assert np.all(np.isfinite(distance)), "distance数组存在非有限值"
4. 处理distance重复值(可选)
如果distance存在重复值,CubicSpline也会报错,可添加去重逻辑:
# 去重并保留首次出现的索引 unique_indices = np.unique(distance, return_index=True)[1] distance = distance[unique_indices] t = t[unique_indices] x = x[unique_indices] y = y[unique_indices] v = v[unique_indices] z = z[unique_indices] a = a[unique_indices]
内容的提问来源于stack exchange,提问作者Márton Horváth
相关产品推荐
相关产品推荐

