1

I am working on capturing seasonality of time series using periodogram plot, I want to use the top ten frequency components to create the seasonality time series, so far, I plotted the periodogram:

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

data is a one year subset of prices with 30 minutes intervals , and captured the top ten frequency components from the fourier_coefficients list after sorting it by the amplitude

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

top frequencies with highest amplitudes are : 365,2,730,22,52,5,729,8 , what I need to do next is to use these top frequency components to get the seasonality of time series, I generated the sinusoidal waves of each frequency component, and added them together to plot the time series, thought I am not sure if this is the right way, because I remember that there should be an imaginary part of the frequency component but I cant find it from the periodogram data, secondly I am only assuming that each of these components is a sin wave.

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

the 8761 is the number of samples in the data.
I then plotted sinaves['accumulated_sin_wave']

here is a plot for the seasonal components in the first year:

here

So, I am wondering what should I do instead of just plotting these sin waves to capture the real components of the top frequencies.

1 Answers1

1

Well, a better and easier way for me was just to use an FFT-filtering-IFFT model, it is as simple as it looks, first I plotted the FFt for my data using:

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()

after this I sorted the power list by amplitudes, and used the top 10 frequencies, which for my data are: 0,365,17155,1,17519,11,17509,366,17154,2,17518 notice that 0 is the DC component in the data, so you can use it or not depending whether you want offset in your seasonality or not. Also, notice that each of these frequencies are couples, that each couples are mirrors of each other and their since the FFT is a plot where each frequency component and its negative frequency have the same power. After chosing my top 5 frequencies, I filtered the FFT_filtered list:

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]

Then I reveresed the FFt using IFFT to get the plot of the data using top 5 frequencies:

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)

and here is the plot of the reverse list: 1 year seasonality using top 5 frequencies