scipy.signal 的 medfilt 和 pandas 的 rolling().median 有什么区别?

What is the difference between medfilt from scipy.signal and rolling().median from pandas?

我想使用中值滤波器来平滑信号,我看到 Python 中有两种方法可以使用:

通过为这两种方法选择相同的 window 大小,我得到了不同的结果。我附上了一个示例数据集。此外,在第二种方法中,数据点的数量在应用过滤器时发生变化(根据 window 大小),我希望这种情况会发生,但是在第二种方法中,平滑数据的数量与原始数据。

这两种方法有什么区别,为什么会得到不同的结果?

import pandas as pd
import scipy.signal as ss

signal = [4, 3.8, 3.75, 3.9, 3.53, 3.26, 2.33, 2.8, 2.5, 2.4, 2, 2.2, 1.5, 1.7]

# First method
SmoothedSignal = ss.medfilt(signal, kernel_size=5)
print(SmoothedSignal)
print(len(SmoothedSignal))

# Second method
signal = pd.DataFrame(signal)
RollingMedian = signal.rolling(5).median()
print(RollingMedian)
print(len(RollingMedian))

中值不同的原因是核的对齐。 pandas.DataFrame.rolling right aligns the kernel by default, while scipy.signal.medfit 默认居中对齐内核。

您可以通过将 center 关键字参数设置为 True 来居中对齐 DataFrame.rolling

import pandas as pd
import scipy.signal as ss

signal = [4, 3.8, 3.75, 3.9, 3.53, 3.26, 2.33, 2.8, 2.5, 2.4, 2, 2.2, 1.5, 1.7]

# scipy
size = len(signal)
smoothed = ss.medfilt(signal, kernel_size=5)

# rolling - right aligned
signal = pd.DataFrame(signal)
rolling_right = signal.rolling(5).median()

# rolling - center aligned
signal = pd.DataFrame(signal)
rolling_center = signal.rolling(5 ,center = True).median()


df = pd.DataFrame()
df[ 'smooth' ] = smoothed 
df[ 'rolling_center' ] = rolling_center
df[ 'rolling_right' ] = rolling_right

df

# output
    smooth  rolling_center  rolling_right
0   3.75    NaN             NaN
1   3.80    NaN             NaN
2   3.80    3.80            NaN
3   3.75    3.75            NaN
4   3.53    3.53            3.80
5   3.26    3.26            3.75
6   2.80    2.80            3.53
7   2.50    2.50            3.26
8   2.40    2.40            2.80
9   2.40    2.40            2.50
10  2.20    2.20            2.40
11  2.00    2.00            2.40
12  1.70    NaN             2.20
13  1.50    NaN             2.00

您还会注意到 nan 填充与使用 rolling 的差异。