import datetime
import shlex
import numpy as np
from scipy.fftpack import rfft, irfft, fftfreq
strWeatherFile = "data/weather.dat"
signal = []
with open(strWeatherFile, 'rt') as f:
for line in f:
arrDat = shlex.split(line)
d = float(arrDat[3])
if d < -30: # if it's dummy data
d = signal[len(signal) - 1]
signal.append(d)
size = len(signal)
time = np.linspace(1,size,size)
f_signal = rfft(signal)
import pylab as plt
plt.subplot(221)
plt.plot(time,signal)
plt.subplot(222)
plt.plot(time,f_signal)
plt.xlim(0,size)
plt.show()
这是天气数据,因此它应该显示频率为365的峰值。但结果并不像预期的那样。 代码有什么问题吗?
数据来自以下链接: http://academic.udayton.edu/kissock/http/Weather/gsod95-current/CALOSANG.txt
答案 0 :(得分:2)
你的FFT应该根据频率而不是时间来绘制。
import shlex
import pylab as plt
import numpy as np
from scipy.fftpack import rfft, rfftfreq
strWeatherFile = "data/weather.dat"
signal = []
with open(strWeatherFile, 'rt') as f:
for line in f:
arrDat = shlex.split(line)
d = float(arrDat[3])
if d < -30: # if it's dummy data
d = signal[len(signal) - 1]
signal.append(d)
size = len(signal)
time = np.arange(1,size+1)
f_signal = rfft(signal)
freq = rfftfreq(size, d=1.)
plt.ion()
plt.close("all")
plt.figure()
plt.plot(time,signal)
plt.figure()
plt.plot(freq,abs(f_signal))
plt.show()
你不会期望看到365的飙升,因为这是时间价值。对于周期为365的信号的相应频率将是1/365或.00274
答案 1 :(得分:2)
数据文件包含14个错误样本,值为-99。我使用最近的好样本用线性插值替换坏样本。文件中的样本总数为7006.该数据用于未知的每日天气参数。
正如Ben所说,频率单位是1 /天而不是天,所以你不会看到365频率单位的峰值(假设数据是周期性的365天)。
下图显示了输入FFT的数据。使用线性插值程序删除了不良样本。右端的零值由FFT自动添加,以便将输入样本的数量填充到下一个更高的2的幂。
下图显示了输入到FFT的数据,并删除了DC偏移(62.3127)。
下图显示了满量程的FFT输出。 FFT输入包括DC偏移。
下图放大了FFT输出的低频端。在图的左侧附近可以看到峰值。该峰值对应于您要查找的频率。 FFT输入包括DC偏移。
下图显示了感兴趣的频率峰值。峰值频率单位为0.0026855(22/8192),对应的时间值为372天(1 / 0.0026855)。 FFT输入包括DC偏移。
下图显示了使用Blackman-Harris 92 dB高分辨率窗口输入数据后的FFT。感兴趣的频率峰值比周围背景高18 dB。在这种情况下,窗口显着减少了光谱泄漏。窗口化后,峰值保持在0.0026855(22/8192)频率单位,这对应于372天的时间值(1 / 0.0026855)。 FFT输入包括DC偏移。
下图显示了从输入数据中删除DC偏移(62.3127)后的FFT,并且没有应用于输入数据的窗口。
下图显示了从输入数据中移除DC偏移(62.3127)并应用Blackman-Harris 92 dB高分辨率窗口后的FFT。
完成FFT和图表
答案 2 :(得分:0)
我不一定在这里有一个好的答案,但我想让你的代码很容易为其他人复制,所以他们不必动手下载和文件:
import datetime
import urllib2
import numpy as np
from scipy.fftpack import rfft, irfft, fftfreq
url = 'http://academic.udayton.edu/kissock/http/Weather/gsod95-current/CALOSANG.txt'
response = urllib2.urlopen(url)
html = response.read()
rows = [[float(c) if '.' in c else int(c)
for c in row.split()]
for row in html.splitlines()]
signal = []
for line in rows:
d = float(line[3])
if d < -30: # if it's dummy data
d = signal[len(signal) - 1]
signal.append(d)
size = len(signal)
time = np.linspace(1,size,size)
f_signal = rfft(signal)
import pylab as plt
plt.subplot(221)
plt.plot(time,signal)
plt.subplot(222)
plt.plot(time,f_signal)
plt.xlim(0,size)
plt.show()