首页 > 解决方案 > 时间序列的傅里叶变换 (fft),但已清理数据的两端相互靠近

问题描述

我有一个时间序列,它代表虚拟环境中的 X 和 Z 坐标。

X = np.array(df["X"])
Z = np.array(df["Z"])

X 和 Z 坐标都包含来自不同来源的噪声。为了滤除噪音,我想使用傅立叶变换。经过一番研究,我使用了https://medium.com/swlh/5-tips-for-working-with-time-series-in-python-d889109e676d中的代码对我的数据进行去噪。

def fft_denoiser(x, n_components, to_real=True):
    n = len(x)

    # compute the fft
    fft = np.fft.fft(x, n)

    # compute power spectrum density
    # squared magnitud of each fft coefficient
    PSD = fft * np.conj(fft) / n

    # keep high frequencies
    _mask = PSD > n_components
    fft = _mask * fft

    # inverse fourier transform
    clean_data = np.fft.ifft(fft)

    if to_real:
        clean_data = clean_data.real

    return clean_data

设置 n_components 后,我喜欢使用清理后的数据。正如我为 X 坐标绘制的那样,这非常好:

在此处输入图像描述

只有在开始和结束时,清理后的数据突然朝着彼此的值移动......有人可以帮助或解释一下是什么原因造成的,我该如何克服这个问题?

标签: pythontimecoordinatesfftseries

解决方案


您遇到此问题的原因是因为 FFT 隐含地假定提供的输入信号是周期性的。如果您重复原始数据,您会发现在每个周期都存在很大的不连续性(当信号从 ~20 回落到 ~5 时)。一旦去除了一些较高频率的分量,您就会看到边缘处的不那么尖锐的不连续性(开始时有几个样本,结束时有几个样本)。

为了避免这种情况,您可以使用线性 FIR 滤波器在时域中进行滤波,该滤波器可以在没有周期性假设的情况下处理数据序列。

出于这个答案的目的,我构建了一个合成测试信号(您可以使用它来重新创建相同的条件),但您显然可以使用自己的数据来代替:

# Generate synthetic signal for testing purposes
fs = 1 # Hz
f0 = 0.002/fs
f1 = 0.01/fs
dt = 1/fs
t = np.arange(200, 900)*dt
m = (25-5)/(t[-1]-t[0])
phi = 4.2
x = 5 + m*(t-t[0]) + 2*np.sin(2*np.pi*f0*t) + 1*np.sin(2*np.pi*f1*t+phi) + 0.2*np.random.randn(len(t))

现在要设计过滤器,我们可以对_mask(而不是应用掩码)进行逆变换:

import numpy as np

# Design denoising filter
def freq_sampling_filter(x, n_components):
  n = len(x)

  # compute the fft
  fft = np.fft.fft(x, n)

  # compute power spectrum density
  # squared magnitud of each fft coefficient
  PSD = fft * np.conj(fft) / n

  # keep frequencies with large contributions
  _mask = PSD > n_components
  _coff = np.fft.fftshift(np.real(np.fft.ifft(_mask)))
  return _coff

coff = freq_sampling_filter(x, threshold)

然后我们可以简单地应用过滤器scipy.signal.filtfilt

from scipy.signal import filtfilt

# apply the denoising filter
cleaned = filtfilt(coff, 1, x, padlen=len(x)-1, padtype='constant')

在此处输入图像描述

padtypeto的选择'constant'确保过滤的值在未过滤数据的开始和结束值处开始和结束。


推荐阅读