我目前正在为一篇课程做一些频谱分析,尽管我们还没有明确地教过傅里叶变换。我一直在玩scipy和numpy中的各种fft算法的一些数据,我知道答案应该是什么样的
在这种情况下,其顶部8kHz载波频率和1kHz调制正弦波的AM信号应该在fft上有3个清晰的峰值
在应用scipy.fftpack.rfft
和numpy.fft.rfft
时,我会分别得到以下图表:
SciPy的:
numpy的:
虽然2个FFT的形状与峰值之间的正确比率大致相同,但numpy
看起来更平滑,而scipy
的最大峰值略小,并且有很多更多的噪音。
我假设这很大程度上取决于离散傅里叶变换算法的不同应用,并且已经看到其他文章关于scipy
实现如何在运行时更快。但是我在徘徊是什么特别导致差异,哪一个实际上更准确?
编辑:用于生成图表的代码:
data = pd.read_csv("./Waveforms/AM waveform Sine.csv", sep = ',', dtype = float)
data = data.as_matrix()
time = data[:,0]
voltage = data[:,1]/data[:,1].max() # normalise the values
#scipy plot:
plt.figure()
magnitude = scipy.fftpack.rfft(voltage)
freq = scipy.fftpack.rfftfreq(len(time),np.diff(time)[0])
plt.figure()
plt.plot(freq, np.absolute(magnitude), lw = 1)
plt.ylim(0,2500)
plt.xlim(0,15)
#numpy plot
magnitude = np.fft.rfft(voltage)
freq = np.fft.rfftfreq(len(time),np.diff(time)[0])
plt.figure()
plt.plot(freq, np.absolute(magnitude), lw = 1)
plt.ylim(0,2500)
plt.xlim(0,15)
答案 0 :(得分:7)
来自NumPy的rfft文档:
返回:
out:复杂的ndarray
沿轴转换的截断或零填充输入 由轴指示,或者如果未指定轴,则指示最后一个。如果是 甚至,变换轴的长度是(n / 2)+1。如果n是奇数,那么 长度为(n + 1)/ 2。
它没有明确写出,但“转换后的数据”在这里很复杂。
来自SciPy的rfft
文档z:真正的ndarray
返回的实数组包含:
[y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2))] if n is even [y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2)),Im(y(n/2))] if n is odd
结论:存储不同。
对于首发,请查看magnitude
的长度,两种情况都会有所不同。为清晰起见,我在下面给出一个例子:
In [33]: data = np.random.random(size=8)
In [34]: np.fft.rfft(data)
Out[34]:
array([ 3.33822983+0.j , 0.15879369+0.48542266j,
0.00614876+0.03590621j, -0.67376592-0.69793372j, 1.51730861+0.j ])
In [35]: scipy.fftpack.rfft(data)
Out[35]:
array([ 3.33822983, 0.15879369, 0.48542266, 0.00614876, 0.03590621,
-0.67376592, -0.69793372, 1.51730861])
两种情况下的第一个元素是所谓的“DC分量”(信号的平均值)。
然后,您可以在SciPy版本中识别出NumPy版本的实部和虚部的连续性。