Использование периодограммы для определения сезонности временных рядов

Я работаю над захватом сезонности временных рядов с использованием графика периодограммы, я хочу использовать десять верхних частотных компонентов для создания временного ряда сезонности, до сих пор я построил периодограмму:

data=elec_price[:48*365]
from scipy.signal import periodogram
f, Pxx_den = periodogram(data)

данные представляют собой подмножество цен за один год с 30-минутными интервалами и захватывают первые десять частотных компонентов из списка Fourier_coefficients после сортировки по амплитуде.

fourier_coefficients=Pxx_den.tolist()
fourier_coefficients=pd.DataFrame(fourier_coefficients,columns=['amplitude'])

верхние частоты с наивысшими амплитудами: 365,2,730,22,52,5,729,8, что мне нужно сделать дальше, это использовать эти верхние частотные компоненты, чтобы получить сезонность временных рядов, я сгенерировал синусоидальные волны каждой частотной составляющей, и сложил их вместе, чтобы построить временной ряд, хотя я не уверен, что это правильный путь, потому что я помню, что должна быть мнимая часть частотной составляющей, но я не могу найти ее по данным периодограммы, во-вторых, я только предполагая, что каждая из этих компонент является синусоидальной волной.

sin_waves=fourier_coefficients.drop(columns=['frequency coneficient','amplitude']).copy()
sin_waves[' sin_wave_1']=0
sin_waves[' sin_wave_2']=0
sin_waves[' sin_wave_3']=0
sin_waves[' sin_wave_4']=0
sin_waves[' sin_wave_5']=0
sin_waves[' sin_wave_6']=0
sin_waves[' sin_wave_7']=0
sin_waves[' sin_wave_8']=0
for i in range(8761):
    sin_waves[' sin_wave_1'][i]= fourier_coefficients['amplitude'][365]*math.sin(math.pi*i*365/8761)
    sin_waves[' sin_wave_2'][i]= fourier_coefficients['amplitude'][2]*math.sin(math.pi*i*2/8761)
    sin_waves[' sin_wave_3'][i]= fourier_coefficients['amplitude'][730]*math.sin(math.pi*i*730/8761)
    sin_waves[' sin_wave_4'][i]= fourier_coefficients['amplitude'][22]*math.sin(math.pi*i*22/8761)
    sin_waves[' sin_wave_5'][i]= fourier_coefficients['amplitude'][52]*math.sin(math.pi*i*52/8761)
    sin_waves[' sin_wave_6'][i]= fourier_coefficients['amplitude'][5]*math.sin(math.pi*i*5/8761)
    sin_waves[' sin_wave_7'][i]= fourier_coefficients['amplitude'][729]*math.sin(math.pi*i*729/8761)
    sin_waves[' sin_wave_8'][i]= fourier_coefficients['amplitude'][8]*math.sin(math.pi*i*8/8761)
sin_waves['accumulated_sin_wave']=(sin_waves[' sin_wave_1']+sin_waves[' sin_wave_2']
                + sin_waves[' sin_wave_3']+sin_waves[' sin_wave_4']+sin_waves[' sin_wave_5']+
                sin_waves[' sin_wave_6']+sin_waves[' sin_wave_7']+sin_waves[' sin_wave_8'])

8761 — это количество выборок в данных.
Затем я построил график sinaves['accumulated_sin_wave']

вот график для сезонных компонентов в первый год:

здесь

Итак, мне интересно, что мне делать вместо того, чтобы просто строить эти синусоидальные волны, чтобы захватить реальные компоненты вершины частоты.


person mohamed elhafiz    schedule 26.03.2019    source источник


Ответы (1)


Что ж, лучшим и более простым способом для меня было просто использовать модель БПФ-фильтрации-ОБПФ, она настолько проста, насколько кажется, сначала я построил БПФ для своих данных, используя:

one_year_values=48*365
data=elec_price[:one_year_values]
from numpy.fft import fft, fftfreq, ifft

n=len(data)
freqs=fftfreq(n)
mask = freqs>0


fft_values=fft(data)
fft_list=np.copy(fft_values).tolist()
fft_filtered=np.copy(fft_list).tolist() # copying from the original fft list in order to filter it

power= 2*(np.abs(fft_values/one_year_values))**2 # calculating the power make sit easy to compare between frequency components, because they are complex numbers, and the power of them gets the absolute values of them.
power=power.tolist()

после этого я отсортировал список мощности по амплитуде и использовал 10 верхних частот, которые для моих данных: данные, поэтому вы можете использовать их или нет, в зависимости от того, хотите ли вы смещение в своей сезонности или нет. Кроме того, обратите внимание, что каждая из этих частот является парой, что каждая пара является зеркалом друг друга и их, поскольку БПФ представляет собой график, на котором каждая частотная составляющая и ее отрицательная частота имеют одинаковую мощность. Выбрав 5 лучших частот, я отфильтровал список FFT_filtered:

tuple(fft_filtered)
for i in range(len(fft_filtered)):
    fft_filtered[i]=0
for i in (0
,365
,17155
,1
,17519
,11
,17509
,366
,17154
,2
,17518):
    fft_filtered[i]=fft_list[i]

Затем я изменил БПФ с помощью IFFT, чтобы получить график данных с использованием 5 верхних частот:

reverse=np.real(ifft(fft_filtered))
#%%
plt.plot(reverse)
plt.legend(loc='best')
plt.ylabel('seasonal factor')
plt.xlabel('time stamps')
plt.title('1st  year seasonality-top 5 freq')
plt.show(block=False)

а вот график обратного списка: сезонность за 1 год с использованием 5 лучших частот

person mohamed elhafiz    schedule 02.04.2019