Periodogram to find the season of a time series

40 Views Asked by At

I have a time series that is detecting a toggle system which has a repetitive pattern of length k, where (k-1) consecutive values are 0 and one is equal to 1. I want to use periodogram to find the length k of this system. How can I do so?

Currently I have this code:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import periodogram

def find_repetitive_pattern_length(time_series):
    f, Pxx = periodogram(time_series)
    max_power_index = np.argmax(Pxx)
    dominant_frequency = f[max_power_index]
    period_length = int(1 / dominant_frequency)

    
    plt.figure(figsize=(10, 6))
    plt.plot(f, Pxx, label='Periodogram')
    plt.scatter(f[max_power_index], Pxx[max_power_index], color='red', label=f'Dominant Frequency: {dominant_frequency:.2f} Hz')
    plt.title('Periodogram with Dominant Frequency')
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Power/Frequency Density')
    plt.legend()
    plt.show()

    return period_length


time_series4 = np.array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1])
time_series7 = np.array([0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1])
period_length = find_repetitive_pattern_length(time_series4)
print(f"The length of the first repetitive pattern is: {period_length}")
period_length = find_repetitive_pattern_length(time_series7)
print(f"The length of the second repetitive pattern is: {period_length}")

But I get:

The length of the first repetitive pattern is: 4 (correct)

The length of the second repetitive pattern is: 3 (incorrect)

What am I doing wrong and how can I solve?

1

There are 1 best solutions below

0
Michael Hodel On

Here is a solution that I believe solves your problem that however does not use a periodogram. The function get_season takes a numpy array arr and returns the mode of the distances between the ones in arr.

import numpy as np

time_series4 = np.array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1])
time_series7 = np.array([0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1])

def get_season(arr):
    """
    returns the most common difference between indices of adjacent non-zero values in arr
    """
    return np.argmax(np.bincount(np.diff(np.where(arr)[0])))

assert get_season(time_series4) == 4
assert get_season(time_series7) == 7