Использование периодограммы для определения сезонности временных рядов - PullRequest
0 голосов
/ 26 марта 2019

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

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']

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

here

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

1 Ответ

0 голосов
/ 02 апреля 2019

Что ж, лучше и проще для меня было просто использовать модель FFT-filtering-IFFT, это так просто, как кажется, сначала я построил FFt для своих данных, используя:

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 верхних частот, которые для моих данных: 0,365,17155,1,17519,11,17509,366,17154,2,17518 обратите внимание, что 0 является компонентом постоянного токав данных, так что вы можете использовать его или нет, в зависимости от того, хотите ли вы смещения в сезонности или нет.Также обратите внимание, что каждая из этих частот является парами, что каждая пара является зеркалами друг друга, и их так как FFT представляет собой график, где каждый частотный компонент и его отрицательная частота имеют одинаковую мощность.После выбора 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]

Затем я почитал FFt, используя 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 лучших частот

...