巴特沃斯滤波器在Pandas数据帧中的应用

2024-09-27 09:35:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个像这样的数据帧(只是大得多,x的步长更小):

      x   val1   val2   val3
0    0.0  10.0   NaN    NaN
1    0.5  10.5   NaN    NaN
2    1.0  11.0   NaN    NaN
3    1.5  11.5   NaN  11.60
4    2.0  12.0   NaN  12.08
5    2.5  12.5  12.2  12.56
6    3.0  13.0  19.8  13.04
7    3.5  13.5  13.3  13.52
8    4.0  14.0  19.8  14.00
9    4.5  14.5  14.4  14.48
10   5.0   NaN  19.8  14.96
11   5.5  15.5  15.5  15.44
12   6.0  16.0  19.8  15.92
13   6.5  16.5  16.6  16.40
14   7.0  17.0  19.8  18.00
15   7.5  17.5  17.7    NaN
16   8.0  18.0  19.8    NaN
17   8.5  18.5  18.8    NaN
18   9.0  19.0  19.8    NaN
19   9.5  19.5  19.9    NaN
20  10.0  20.0  19.8    NaN

我最初的问题是计算每个列的导数,这个问题解决了:How to get indexes of values in a Pandas DataFrame? Alexander发布的解决方案与我之前的代码如下:

^{pr2}$

但是,我需要做一些平滑处理(假设这里是2米,从原来的0.5米间距x),因为导数的值在精细的尺度上变得疯狂。 我试过scipy函数filtfiltbutter(我想使用butterworth过滤器,这在我的专业中是一种常见的做法),但可能我没有正确地使用它们。更新:也尝试了savgol_过滤器。在

我应该如何在这段代码中实现这些函数?

(我是这样修改代码的:

step = 0.5
relevant_scale = 2
order_butterworth = 4
b, a = butter(order_butterworth, step/relevant_scale, btype='low', analog=False)
smoothed=filtfilt(b,a,data.iloc[:, 1:]) # the first column is x
dVal = smoothed.diff()  
dz = data['Depth'].diff()
derivative = (dVal.apply(lambda series: series / dz))*1000 

但是我得到的平滑结果是一个nan数组,得到一个错误AttributeError: 'numpy.ndarray' object has no attribute 'diff'

这个问题通过答案-https://stackoverflow.com/a/38691551/5553319得到了解决,代码确实可以处理连续的数据。然而,我在源数据中所做的几乎不明显的改变会发生什么呢?(中间值为南值)。 enter image description here

所以,即使我们在一个连续的数据数组中遗漏了一个数据点,我们怎样才能使这个解决方案稳定呢? 好的,在评论中也有回答。这种缺失的数据点需要插值。在


Tags: 数据函数代码过滤器stepdiffordernan
1条回答
网友
1楼 · 发布于 2024-09-27 09:35:04

您看到的错误是因为您试图对filtfilt的结果调用方法.diff(),这是一个没有该方法的numpy数组。如果您真的想使用一阶差分,可以使用np.gradient(smoothed)

现在,你的真正目标似乎是获得噪声信号导数的无滞后估计。我建议您使用类似于Savitzky Golay filter的方法,这样可以在一个过滤器应用程序中获得导数估计值。你可以看到一个关于噪声信号here的导数估计的例子

您还需要容纳数据中的NaN。以下是我如何处理您的数据:

import scipy.signal
import matplotlib.pyplot as plt

# Intelligent use of the index allows us to keep track of the x for the data.
df = df.set_index('x')
dx = df.index[1]

for col in df:
    # Get rid of nans
    # NOTE: If you have nans in between your data points, this does the wrong thing, 
    # but for the data you show for contiguous data this is fine.
    nonans = df[col].dropna()
    smoothed = scipy.signal.savgol_filter(nonans, 5, 2, deriv=1, delta=dx)
    plt.plot(nonans.index, smoothed, label=col)
plt.legend()

结果如下图:

Sample plot

相关问题 更多 >

    热门问题