如何在 matplotlib 中将正弦波的 FFT 居中?

How to center the FFT of sine wave in matplotlib?

我想使用 matplotlib 绘制正弦波的 FFT,我想在正弦波所属的频率上绘制一条直线。

这是我的代码

import numpy as np
import matplotlib.pyplot as plt


f = 3
t = np.arange(-np.pi, np.pi, 0.01)
y = np.sin(2*np.pi*f*t)


plt.subplot(2, 1, 1)
plt.plot(t, y)


ft = np.fft.fft(y)

plt.subplot(2, 1, 2)
plt.plot(ft.real)

plt.show()

并且,这是上面代码的输出。

我想将 FFT 绘制成一条直线,这条直线将在给定的正弦波频率处直线上升。假设,如果我将两个 20Hz 和 40Hz 的正弦波加在一起,如 sine(2*pi*20*t) + sine(2*pi*40*t) 那么它们的 FFT 应该在 20Hz 和 30Hz 处有两条直线。

如何修改我的代码以获得我想要的?我在 Whosebug 上看到很多问题,但我不明白。任何帮助将不胜感激。

这里有一些东西要打开。

对真实信号使用np.fft.rfft

由于您的信号是 real-valued(即没有复数),所以您的 fft 的后半部分没有包含任何信息。您应该使用 rfft 代替真实信号。

请参阅 numpy 文档的 this 部分。

使用abs得到振幅

您似乎对每个频率分量的幅度感兴趣。幅值取fft的绝对值得到:

ft = np.fft.rfft(y)
amplitude = abs(ft)

有关详细信息,请参阅 numpy 文档的 this 部分。

正确缩放频率

您可以使用 np.fft.rfftfreq 获取每个分量的频率,但是这些频率将按 1 / number of points 缩放。

要缩放频率以使其与您的 f 参数相匹配,您需要知道系列中各点之间的时间差:

delta_t = 0.01
t = np.arange(-np.pi, np.pi, delta_t)
freq = np.fft.rfftfreq(len(t)) / delta_t

综合起来

import numpy as np
import matplotlib.pyplot as plt

# Extract delta_t to rescale the frequencies later
delta_t = 0.01
t = np.arange(-np.pi, np.pi, delta_t)

# Signal is a mixture of 2 frequencies
f0 = 3
f1 = 8
y = np.sin(2*np.pi*f0*t) + 0.5 * np.sin(2*np.pi*f1*t)

plt.subplot(2, 1, 1)
plt.plot(t, y)

ft = np.fft.rfft(y)

# Frequency of each component, scaled like f0 and f1
freq = np.fft.rfftfreq(len(t)) / delta_t

# Amplitude of each frequency is given by the absolute value
amplitude = abs(ft)

plt.subplot(2, 1, 2)
plt.plot(freq, amplitude)
plt.xlabel('frequency')
plt.ylabel('amplitude')

plt.show()