簡體   English   中英

Python:使用 SciPy 文檔對 .csv 值執行 FFT

[英]Python: Performing FFT on .csv values using SciPy documentation

我想對數據系列執行快速傅立葉變換。 該系列包含在 407 天內一致采樣的每日地震振幅值。 我想搜索這個數據集的任何周期性周期。

我在此處使用 SciPy 文檔進行了初步嘗試: https ://docs.scipy.org/doc/scipy/reference/tutorial/fftpack.html。 與這個問題( 鏈接)類似,然后我將 y 的參數從人工正弦函數更改為我的數據集。

但是,我收到以下錯誤:

ValueError: x and y must have same first dimension, but have shapes (203,) and (407, 1)

我很感激幫助理解我為什么會收到這個錯誤,以及我如何解決它。

我也很感激有關 FFT 處理我的數據集所需的正確頻率和采樣輸入值的幫助。 我的數據集中有 407 個值,每個值代表一天。 因此,我定義了 N(樣本點數)= 407,T(樣本間距)= 1 / 84600(1 / 一天中的秒數)。 那是正確的嗎?

這是我的完整代碼:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft, ifft
import pandas as pd

# Import csv file
df = pd.read_csv('rsam_2016-17_fft_test.csv', index_col=['DateTime'], parse_dates=['DateTime'])
print(df.head())

#plot data
plt.figure(figsize=(12,4))
df.plot(linestyle = '', marker = '*', color='r')
plt.show()

#FFT
#number of sample points
N = 407
#frequency of signal
T = 1 / 84600
#create x-axis for time length of signal
x = np.linspace(0, N*T, N)
#create array that corresponds to values in signal
y = df
#perform FFT on signal
yf = fft(y)
#create new x-axis: frequency from signal
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)
#plot results
plt.plot(xf, yf)
plt.grid()
plt.show()

非常感謝您的幫助!


編輯:完整的錯誤如下:

Traceback (most recent call last):

File "<ipython-input-40-c090e0039ba9>", line 1, in <module>
runfile('/Users/an16975/Desktop/PhD/Code/FFT/fft_test.py', wdir='/Users/an16975/Desktop/PhD/Code/FFT')

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 710, in runfile
execfile(filename, namespace)

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 101, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "/Users/an16975/Desktop/PhD/Code/FFT/fft_test.py", line 36, in <module>
plt.plot(xf, yf)

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/pyplot.py", line 3317, in plot
ret = ax.plot(*args, **kwargs)

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/__init__.py", line 1898, in inner
return func(ax, *args, **kwargs)

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_axes.py", line 1406, in plot
for line in self._get_lines(*args, **kwargs):

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py", line 407, in _grab_next_args
for seg in self._plot_args(remaining, kwargs):

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py", line 385, in _plot_args
x, y = self._xy_from_xy(x, y)

File "/Users/an16975/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py", line 244, in _xy_from_xy
"have shapes {} and {}".format(x.shape, y.shape))

ValueError: x and y must have same first dimension, but have shapes (203,) and (407, 1)

第二次編輯:

SleuthEye 的回答使我能夠生成我正在尋找的圖。 對於任何感興趣的人,情節如下。

未過濾的數據系列 -

2016 - 2017 年期間的每日地震振幅值

下面是對上述數據系列執行 FFT 生成的圖 -

日地震振幅數據集的快速傅立葉變換

我希望這是正確的輸出,並且我已經正確標記了軸/理解第二個圖代表什么。 我也想知道為什么傅里葉頻譜的上半部分是多余的。

作為參考,我的完整(更正)代碼如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft, ifft
import pandas as pd

# Import csv file
df = pd.read_csv('rsam_2016-17_fft_test.csv', index_col=['DateTime'], parse_dates=['DateTime'])
print(df.head())

#plot data
plt.figure(figsize=(12,4))
df.plot(linestyle = '', marker = '*', color='r')
plt.savefig('rsam_2016_2017_snippetforfft.jpg')
plt.show()

#FFT
#number of sample points
N = 407
#frequency of signal (in days)
T = 1
#create x-axis for time length of signal
x = np.linspace(0, N*T, N)
#create array that corresponds to values in signal
y = df
#perform FFT on signal
yf = fft(y)
#create new x-axis: frequency from signal
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)
#plot results
plt.plot(xf, yf[0:N//2], label = 'signal')
plt.grid()
plt.xlabel('Frequency (days)')
plt.ylabel(r'Spectral Amplitude')
plt.legend(loc=1)
plt.savefig('rsam_2016_2017_snippet_fft_firstresult.jpg')
plt.show()

fft函數返回完整的N點頻譜(對於實值輸入,它包括頻譜的冗余上半部分),而您的頻率軸xf被構建為僅覆蓋頻譜的下半部分,只有N//2個點。 您的錯誤與這些xfyf數組大小之間的不匹配有關。 由於冗余,您可以使用yf[0:N//2]排除yf頻譜的上半部分。

另請注意,數組yf包含復數。 要顯示頻譜圖輸出,您應該取絕對值:

plt.plot(xf, abs(yf[0:N//2]))

最后,就采樣周期而言,如果您打算使用秒作為采樣周期,使用赫茲作為頻率,您應該使用T = 86400 (因為您每 1 天或 86400 秒有一個數據點)。 您也可以選擇使用天數作為采樣周期,使用天數-1 (或周期/天)作為頻率,在這種情況下,您將使用T = 1

import pandas as pd
import numpy as np
from numpy.fft import rfft, rfftfreq
import matplotlib.pyplot as plt

t=pd.read_csv('C:\\Users\\trial\\Desktop\\EW.csv',usecols=[0])
a=pd.read_csv('C:\\Users\\trial\\Desktop\\EW.csv',usecols=[1])
n=len(a)
dt=0.02 #time increment in each data

acc=a.values.flatten() #to convert DataFrame to 1D array
#acc value must be in numpy array format for half way mirror calculation

fft=rfft(acc)*dt
freq=rfftfreq(n,d=dt)

FFT=abs(fft)

plt.plot(freq,FFT)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM