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

时间:2015-05-01 17:48:54

标签: python numpy pandas fft

我有嘈杂的data我想要计算频率和幅度。每1/100秒收集样品。从趋势来看,我认为频率为~0.3

enter image description here

当我使用numpy fft模块时,我最终得到非常高的频率(36.32 /秒),这显然是不正确的。我尝试使用pandas rolling_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]

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

3 个答案:

答案 0 :(得分:3)

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

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())

打印:

Main freq: 0.32012805122
RMS amp: 0.0556044913489

enter image description here

答案 1 :(得分:0)

我希望这对你有所帮助。

http://wiki.scipy.org/Cookbook/ButterworthBandpass

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

编辑:

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

答案 2 :(得分:-1)

你应该使用一个低通滤波器,它应该保持较大的周期性变化并首先消除一些较高频率的东西。之后,然后可以进行FFT以获得峰值。这是一个recipe for FIR filter,通常用于这种确切的事情。