pandas 非常嘈杂的信号的 Scipy FFT 频率分析

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29992174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 23:18:04  来源:igfitidea点击:

Scipy FFT Frequency Analysis of very noisy signal

pythonnumpypandasfft

提问by Ashish

I have noisy datafor which I want to calculate frequency and amplitude. The samples were collected every 1/100th sec. From trends, I believe frequency to be ~ 0.3

我有噪声数据,我想为其计算频率和幅度。每 1/100 秒收集一次样品。从趋势来看,我相信频率是 ~ 0.3

enter image description here

在此处输入图片说明

When I use numpyfftmodule, I end up getting very high frequency (36.32 /sec) which is clearly not correct. I tried to filter the data with pandasrolling_meanto remove the noise before fft, but that too didn't work.

当我使用numpyfft模块时,我最终得到了非常高的频率 (36.32 /sec),这显然是不正确的。我试图pandasrolling_mean在 fft 之前过滤数据以去除噪声,但这也不起作用。

import pandas as pd
from numpy import fft
import numpy as np
import matplotlib.pyplot as plt

Moisture_mean_x = pd.read_excel("signal.xlsx", header = None)
Moisture_mean_x = pd.rolling_mean(Moisture_mean_x, 10) # doesn't helps
Moisture_mean_x = Moisture_mean_x.dropna()
Moisture_mean_x = Moisture_mean_x -Moisture_mean_x.mean()
frate = 100. #/sec           
Hn = fft.fft(Moisture_mean_x)
freqs = fft.fftfreq(len(Hn), 1/frate)
idx = np.argmax(np.abs(Hn))
freq_in_hertz = freqs[idx]

Can someone guide me how to fix this?

有人可以指导我如何解决这个问题吗?

采纳答案by tillsten

You are right there is something wrong. One needs to explictiy ask pandas for the zeroth column:

你是对的,有什么不对的。需要明确地向大Pandas询问第零列:

Hn = np.fft.fft(Moisture_mean_x[0])

Else something wrong happen, which you can see by the fact that the FFT result was not symetric, which should be the case for real input.

否则会发生一些错误,您可以通过 FFT 结果不对称的事实看出这一点,实际输入应该是这种情况。

result

结果

回答by Scott

Seems like @tillstenalready answered your question, but here is some additional confirmation. The first plot is your data (zero mean and I changed it to a csv). The second is the power spectral density and you can see a fat mass with a peak at ~0.3 Hz. I 'zoomed' in on the third plot to see if there was a second hidden frequency close to the main frequency.

似乎@tillsten已经回答了您的问题,但这里有一些额外的确认。第一个图是您的数据(零均值,我将其更改为 csv)。第二个是功率谱密度,您可以看到在 ~0.3 Hz 处具有峰值的脂肪量。我“放大”了第三个图,看看是否有第二个隐藏频率接近主频率。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

x = pd.read_csv("signal.csv")
x = np.array(x, dtype=float)[:,0]
x = x - np.mean(x)
fs = 1e2

f, Pxx = signal.welch(x, fs, nperseg=1024)
f_res, Pxx_res = signal.welch(x, fs, nperseg=2048)

plt.subplot(3,1,1)
plt.plot(x)

plt.subplot(3,1,2)
plt.plot(f, Pxx)
plt.xlim([0, 1])
plt.xlabel('frequency [Hz]')
plt.ylabel('PSD')

plt.subplot(3,1,3)
plt.plot(f_res, Pxx_res)
plt.xlim([0, 1])
plt.xlabel('frequency [Hz]')
plt.ylabel('PSD')

plt.show()

Hn = fft.fft(x)
freqs = fft.fftfreq(len(Hn), 1/fs)
idx = np.argmax(np.abs(Hn))
freq_in_hertz = freqs[idx]
print 'Main freq:', freq_in_hertz
print 'RMS amp:', np.sqrt(Pxx.max())

This prints:

这打印:

Main freq: 0.32012805122
RMS amp: 0.0556044913489

enter image description here

在此处输入图片说明

回答by hotpaw2

An FFT is a filter bank. Just look for the magnitude peak onlywithin the expected frequency range in the FFT result (instead of the entire result vector), and most of the other spectrum will essentially be filtered out.

FFT 是一个滤波器组。只要看看峰值幅度在FFT结果(而不是整个结果向量)预期的频率范围内,而其他大部分频谱基本上将被过滤掉。

回答by Mark Ransom

It isn't necessary to filter the signal beforehand, because the FFT isa filter. Just skip those parts of the FFT that correspond to frequencies you know to contain a lot of noise - zero them out, or otherwise exclude them.

没有必要预先对信号进行滤波,因为 FFT一个滤波器。只需跳过与您知道包含大量噪声的频率相对应的 FFT 部分 - 将它们归零,或以其他方式排除它们。

回答by Mark Ransom

I hope this may help you.

我希望这可以帮助你。

https://scipy-cookbook.readthedocs.io/items/ButterworthBandpass.html

https://scipy-cookbook.readthedocs.io/items/ButterworthBandpass.html

You should filter only the band around the expected frequency and improve the signal noise ratio before applying the FFT.

在应用 FFT 之前,您应该仅过滤预期频率附近的频带并提高信噪比。

Edit:

编辑:

Mark Ransom gave a smarter answer, if you have to do the FFT you can just cut off the noise after the transformation. It won't give a worse result than a filter would.

Mark Ransom 给出了一个更聪明的答案,如果你必须做 FFT,你可以在转换后切断噪音。它不会产生比过滤器更糟糕的结果。

回答by reptilicus

You should use a low pass filter, which should keep the larger periodic variations and smooth out some of the higher frequency stuff first. After that, then can do FFT to get the peaks. Here is a recipe for FIR filtertypically used for this exact sort of thing.

您应该使用低通滤波器,它应该保持较大的周期性变化并首先平滑一些较高频率的东西。之后,然后可以进行FFT以获得峰值。这是通常用于此类事情的FIR 滤波器配方