为什么你找不到1点的峰值
只是为了用我自己的方式重现可能的问题
import numpy as np
import matplotlib.pyplot as plt
# time with a 0.00006 second per sample
t=np.arange(0,12,0.00006)
# y is roughly sin(2π.f.t)⁴. But with some noise.
# Because of power 4, it is a 2f periodic signal. So I choose f
# around 0.5 to mimic the 1Hz signal. And I choose not exactly 0.5
# but a more specific 0.47, to verify my ability to find it back
y=(np.sin(2*np.pi*0.47*t)+np.random.normal(0,0.1,(len(t),)))**4
plt.plot(t,y)
plt.show()
不是相同的信号,但足够接近演示目的.
现在,你所做的是
freqs = np.fft.rfftfreq(len(y),0.0006)
sp = np.fft.rfft(y)
Which gives (once zoomed on the interesting part)
值较大时为0,因为信号平均不为0(这是常量项,或0 HZ)
另一个在0.1之前(我们推测是0.094).在0.2之前有一个小的(第一谐波).
然后,因为你确定1之前的任何东西都应该被忽略(但为什么?即使没有错误,如果FFT告诉你最大的峰值是0.1赫兹,那么为什么会这样呢?
,你放大了大的平面0区域.由于噪音,随着变焦,没有什么是真正平坦的.
你应该做的是
freqs = np.fft.rfftfreq(len(y),0.00006)
注意这对fft没有任何影响.fft
行甚至没有使用freqs
作为参数.只有在绘图时,它才改变x轴上的指示.同样的情节.只是x轴上的刻度不同.
(我没有花很多精力来进行完全相同的zoom ,因为我是用鼠标做的.但你可以看到,它是一样的,除了以前的0.1是现在的1)
更准确的估计
你可能已经注意到,我们所看到的是FFT中的峰值略低于1.可能是我的0.94.但很难说是0.94,0.96...
因为它在低频下的分辨率非常低.
(第一个频率是0.08333……那是一个12秒的周期,整个跨度.秒是它的两倍,所以时间是6秒.等.
在0.91666和1之间没有freqs
%的频率.很难从中准确地找到0.94%).
在这里,我觉得你更多地是在寻找一个重复周期,而不是一个频率(你可能会说,同样的事情.但在FFT中,重点是提供能够再现信号的周期函数的基.而不是映射所有频率.对于高频来说,这几乎是一样的,因为那里的分辨率很高.但对于低频率/高周期,情况并非如此).
所以我宁愿在这里找到最好的自相关.例如,简单地使用卷积
conv=np.convolve(y,y[::-1])
It gives you this
当然,有趣的是这里的山峰.
当信号与自身最匹配时,它们就会出现(想想打印在2个透明图形上的信号).你们互相推搡).
在这里,我们还没有为新的矢量基数固定基频.单位是"样本".
我大致看到的是第二个峰值的位置,在17760.
(中间的那个是当y与自身匹配时,根本没有移位.然后每个峰值都有1,2,3的位移,...或者-1,-2,-3...句号)
17760*0.06等于1.0596秒.
所以1/1.0596=0.94赫兹...