如何在python中使用scipy绘制fft并修改频率范围,使其显示中心的两个峰值频率?

pgky5nke  于 2022-12-13  发布在  Python
关注(0)|答案(2)|浏览(258)

下面的Python代码使用numpy生成正弦曲线图的频率图:

import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = scipy.fftpack.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)

fig, ax = plt.subplots()
ax.plot(xf, 2.0/N * np.abs(yf[:N//2]))
plt.show()

根据上面的代码,我们绘制了一个具有两个频率的正弦波,一个频率为50 Hz,另一个频率为80 Hz。您可以清楚地看到,傅里叶变换图显示了这两个频率的峰值。
我的问题:如何修改上述代码,使x轴的范围为0- 100 Hz?
如果我改变

xf = np.linspace(0.0, 1.0/(2.0*T), N//2)

xf = np.linspace(0.0, 100, N//2)

那么我的图表看起来像这样:

但是图形现在显示我的峰值在11和20赫兹左右,这是不正确的。当我改变我的轴时,峰值应该不会改变。
我做错了什么?

mfuanj7w

mfuanj7w1#

import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = scipy.fftpack.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)

fig, ax = plt.subplots()
ax.plot(xf, 2.0/N * np.abs(yf[:N//2]))
ax.set(
    xlim=(0, 100)
)
plt.show()

只需将xlim

q9rjltbz

q9rjltbz2#

另一种解决方案是绘制适当的值范围。
当执行FFT时,结果的频率步长,以及达到某个频率的bin数,取决于提交给FFT算法的样本数和采样率。因此,当选择要绘制的范围时,需要执行简单的计算,例如,以f为中心的bin的索引为:

idx = ceil(f * t.size / sr)

以下代码有效:

from numpy import arange, sin, pi, abs
from math import ceil
import matplotlib.pyplot as plt
from scipy.fft import rfft, rfftfreq

sr = 800 # Sampling rate = 800Hz
N = 600 # Number of samplepoints (duration = 0.75s)
t = arange(0, N/sr, 1/sr) # Sampling times

# Sampled values
s = sin(50 * 2*pi*t) + 0.5*sin(80 * 2*pi*t)

# FFT and bin centers
y = rfft(s)
f = rfftfreq(t.size, 1/sr)

# Index of 100Hz bin
f_hi = 100
idx_hi = ceil(f_hi * t.size / sr)

# Plot spectrum
fig, ax = plt.subplots()
ax.plot(f[:idx_hi], abs(y[:idx_hi]))
plt.show()

并产生:

由于您只处理真实的信号,因此可以使用rfft代替处理复值的fft来缩短计算时间。

相关问题