Python中的快速傅里叶变换

7
我是新手,对傅里叶理论不熟悉。我看过一些非常好的教程,教我如何将fft应用到信号中并绘制它,以便查看其中包含的频率。但这些教程都将正弦混合作为数据,我很难将其适应到我的实际问题中。
我有242个每小时观测值,具有日周期性,这意味着我的周期为24。因此,我期望在我的fft图上有一个峰值约为24。
我的data.csv样本在这里: https://pastebin.com/1srKFpJQ 数据绘制如下:

The Series

我的代码:

data = pd.read_csv('data.csv',index_col=0)
data.index = pd.to_datetime(data.index)
data = data['max_open_files'].astype(float).values

N = data.shape[0] #number of elements
t = np.linspace(0, N * 3600, N) #converting hours to seconds
s = data

fft = np.fft.fft(s)
T = t[1] - t[0]

f = np.linspace(0, 1 / T, N)
plt.ylabel("Amplitude")
plt.xlabel("Frequency [Hz]")
plt.bar(f[:N // 2], np.abs(fft)[:N // 2] * 1 / N, width=1.5)  # 1 / N is a normalization factor
plt.show()


这会输出一个非常奇怪的结果,似乎每个频率都得到了相同的值。

The result

我认为问题出在N、t和T的定义上,但我找不到任何在线帮助我清晰理解这个问题。请帮忙 :)
编辑1: 使用charles的答案提供的代码,我发现在0附近出现了一个非常奇怪的尖峰。为了避免太多的频率,我使用了rfft和rfftfreq。

frequencies

我读到这可能是由于序列的直流分量,因此在减去平均值后得到:

minusDCcomponentFrequencies

我在解释这个的时候遇到了困难,尖峰似乎周期性出现,但是Hz值不让我得到我的24值(总频率)。有人知道如何解释这个吗?我错过了什么吗?


1
每24小时发生一次事件的周期性意味着频率为1 /(24 * 3600)= 1.15E-5 Hz,因此在从0到0.5的范围内非常接近于零。 - manu190466
1个回答

7

你看到的问题是因为条形图太宽了,你只能看到一个条形。你需要将条形的宽度改为0.00001或更小才能看到它们显示出来。

不要使用条形图,使用fftfreq = np.fft.fftfreq(len(s))创建你的x轴,然后使用plot函数,plt.plot(fftfreq, fft)

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

data = pd.read_csv('data.csv',index_col=0)
data.index = pd.to_datetime(data.index)
data = data['max_open_files'].astype(float).values

N = data.shape[0] #number of elements
t = np.linspace(0, N * 3600, N) #converting hours to seconds
s = data

fft = np.fft.fft(s)
fftfreq = np.fft.fftfreq(len(s))

T = t[1] - t[0]

f = np.linspace(0, 1 / T, N)
plt.ylabel("Amplitude")
plt.xlabel("Frequency [Hz]")
plt.plot(fftfreq,fft)
plt.show()

1
谢谢Charles,我当时非常困惑,没有注意到宽度参数。现在我已经根据你提供的解决方案编辑了我的问题。 - rory
如果这回答解决了你的问题,请接受答案。否则,请告诉我你还需要什么。我认为这个答案加上@manu190466的评论(频率峰应该在一个很小的接近于零的数字)应该有助于解释你看到的情况并回答你的问题。 - charlesreid1
再说一点 - 在开始之前,您将时间值从小时缩放为秒,因此您可能会考虑将x值从Hz(1 /秒)缩放为1 /小时。 - charlesreid1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接