Python 中的三次样条插值 - 为什么它不起作用?

问题描述 投票:0回答:1

我想对我的数据应用二阶低通巴特沃斯滤波器,然后使用三次样条插值在Python中每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 filter
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

# ensuring data arrays are finite
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


# Set initial NaN value in distance to 0
if np.isnan(distance[0]):
    distance[0] = 0


# Ensuring distance array is increasing
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]

# Ensuring data arrays are finite 
v = ensure_finite(v)
a = ensure_finite(a)
z = ensure_finite(z)
x = ensure_finite(x)
y = ensure_finite(y)

# Butterworth filter
fs = 1 / (t[1] - t[0])  # sampling frequency
cutoff = 0.3  # frequency

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)


# Resampling
distance_new = np.arange(0, distance[0], 1)  # at every 1 meter


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)
python interpolation spline butterworth
1个回答
0
投票

很明显,我可以解决这个问题。

请找到我的脚本中有关二阶低通巴特沃斯滤波器的相关部分,该滤波器具有可调截止频率和重采样,使用三次样条插值,以实现更高的精度。

该方法可用于GPS数据处理。

 import numpy as np
import pandas as pd
from scipy.signal import butter, filtfilt
from scipy.interpolate import CubicSpline
import matplotlib.pyplot as plt

# Butterworth filter
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


# Load data
data = pd.read_excel(r"")

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

# Set initial NaN value in distance to 0
if np.isnan(distance[0]):
    distance[0] = 0

# Ensuring distance array is increasing
unique_distances, indices = np.unique(distance, return_index=True)
unique_values = {dist: {'x': [], 'y': [], 'v': [], 'a': [], 'z': []} for dist in unique_distances}

for i in range(len(distance)):
    unique_values[distance[i]]['x'].append(x[i])
    unique_values[distance[i]]['y'].append(y[i])
    unique_values[distance[i]]['v'].append(v[i])
    unique_values[distance[i]]['a'].append(a[i])
    unique_values[distance[i]]['z'].append(z[i])

distance = np.array(list(unique_distances))
x = np.array([np.mean(unique_values[d]['x']) for d in distance])
y = np.array([np.mean(unique_values[d]['y']) for d in distance])
v = np.array([np.mean(unique_values[d]['v']) for d in distance])
a = np.array([np.mean(unique_values[d]['a']) for d in distance])
z = np.array([np.mean(unique_values[d]['z']) for d in distance])



# Butterworth filtering
fs = 1 / (t[1] - t[0])  # sampling frequency
cutoff = 0.1  # frequency

filtered_y = butterworth_filter(y, cutoff, fs)
filtered_x = butterworth_filter(x, cutoff, fs)
filtered_v = butterworth_filter(v, cutoff, fs)
filtered_a = butterworth_filter(a, cutoff, fs)
filtered_z = butterworth_filter(z, cutoff, fs)


# Resampling
if np.any(np.diff(distance) <= 0):
    raise ValueError("Distance array must be strictly increasing.")

distance_new = np.arange(0, distance[-1], 1)  # at every 1 meter

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)


min_len = min(len(t), len(x), len(y), len(v), len(z), len(filtered_x), len(filtered_y), len(filtered_v), len(filtered_z), len(filtered_a))
t = t[:min_len]
x = x[:min_len]
y = y[:min_len]
v = v[:min_len]
z = z[:min_len]
filtered_x = filtered_x[:min_len]
filtered_y = filtered_y[:min_len]
filtered_v = filtered_v[:min_len]
filtered_z = filtered_z[:min_len]
filtered_a = filtered_a[:min_len]
© www.soinside.com 2019 - 2024. All rights reserved.