El periodograma está basado en una herramienta matemática denominada Transformada de Fourier, según la cual una serie, que cumpla determinados requisitos, puede descomponerse como una suma de un número finito o infinito de frecuencias. Del mismo modo, a partir de la represnetación frecuencial puede recuperarse la serie original a través de la Transformada Inversa de Fourier.
El periododgrama mide aportaciones de la varianza total de la serie de componentes periódicos de una frecuencia determinada (w). Si el periodograma presenta un "pico" en una frecuencia, indica que dicha frecuencia tiene mayor importancia en la serie que el resto.
Que se usa para encontrar los periodos en una señal.
Recuerde renombrar el archivo descargado como "datos_periodograma.csv"
In [7]: import pandas as pd
import numpy as np
In [3]: Datos2 = pd.read_csv('datos_periodograma.csv')
Datos2.head(2)
Out [3]:
Datos
0 -0.109606
1 -1.620408
In [5]: Datos2.plot(figsize=(16,4))
Out [5]: <AxesSubplot:>
In [30]: Datos2.describe()
Out [30]:
Datos
count 512.000000
mean 0.123904
std 5.156211
min -13.590559
25% -3.314705
50% 0.338391
75% 3.568908
max 13.154600
In [36]: Datos2.hist(figsize=(8,4))
Out [36]: array([[<AxesSubplot:title={'center':'Datos'}>]], dtype=object)
Se quiere ajustar un modelo lineal de la forma:
Como no se conoce el valor de la frecuencia \omegaω entonces vamos a usar un procedimiento que involucra la FFT la transformada de Fourier Discreta.
Aplicamos la transformada de Fourier a los datos originales
In [8]: Datos2['DataTrasn'] = np.fft.fft(Datos2['Datos'])
In [42]: Datos2.tail(3)
Out [42]:
Datos DataTrasn
509 -9.855796 38.077323-55.256842j
510 2.915284 47.212960-73.440956j
511 0.560807 -25.822076-51.628219j
Le tomamos el módulo a los datos transformados
Y esto es lo que se llama el dendograma !!
In [9]: Datos2['modulo'] = Datos2['DataTrasn'].apply( lambda x: np.absolute(x))
In [10]: Datos2.tail(4)
Out [10]:
Datos DataTrasn modulo
508 7.504165 19.358373-184.883867j 185.894569
509 -9.855796 38.077323-55.256842j 67.105895
510 2.915284 47.212960-73.440956j 87.307718
511 0.560807 -25.822076-51.628219j 57.725667
Se calculan los datos para el periodograma escalado:
In [11]: Datos2['periodograma'] = Datos2['modulo'] * 4 / len(Datos2['modulo'])
print (Datos2.head())
Out [11]:
Datos DataTrasn modulo periodograma
0 -0.109606 63.4391000+0.0000000j 63.439100 0.495618
1 -1.620408 -25.822076+51.628219j 57.725667 0.450982
2 3.457194 47.212960+73.440956j 87.307718 0.682092
3 -5.303519 38.077323+55.256842j 67.105895 0.524265
4 -2.908259 19.358373+184.883867j 185.894569 1.452301
In [49]: Datos2[['Datos','DataTrasn']].plot()
Out [49]: /ext/anaconda2021.11/lib/python3.9/site-packages/numpy/core/_asarray.py:102: ComplexWarning: Casting complex values to real discards the imaginary part return array(a, dtype, copy=False, order=order)
AxesSubplot:>
In [12]: import matplotlib.pyplot as plt
In [30]: fig, ax = plt.subplots(figsize=(15,6))
periodograma = Datos2['periodograma'].values
n = len(periodograma)/2
per = periodograma[0:50]
x = range(0, len(per))
ax.bar(x, per)
plt.title("periodograma escalado")
#plt.xlabel("Frecuencia", fontsize=13)
plt.ylabel("Valores del periodograma", fontsize=13)
Out [30]: Text(0, 0.5, 'Valores del periodograma')
In [56]: frecuencia = max(Datos2['periodograma'])
print (frecuencia)
Out [56]: 2.5246678388502013
La posición del valor máximo en la lista es:
In [57]: pos_frec = np.argmax(Datos2['periodograma'])
print (pos_frec)
Out [57]: 502
In [60]: pos_frec = float(pos_frec)
n = len(periodograma)
x = range(n)
Datos2['onda'] = [-1.15344*np.cos(2*np.pi*t*(pos_frec/n)) + (-0.51291)*np.sin(2*np.pi*t*(pos_frec/n)) for t in x]
print (Datos2.head())
Out [60]:
Datos DataTrasn modulo periodograma onda
0 -0.109606 63.4391000+0.0000000j 63.439100 0.495618 -1.153440
1 -1.620408 -25.822076+51.628219j 57.725667 0.450982 -1.081980
2 3.457194 47.212960+73.440956j 87.307718 0.682092 -0.994246
3 -5.303519 38.077323+55.256842j 67.105895 0.524265 -0.891557
4 -2.908259 19.358373+184.883867j 185.894569 1.452301 -0.775459
In [61]: fig, ax = plt.subplots(figsize=(15,6))
y_datos = Datos2['Datos'].values
ax.plot(x, y_datos)
y = Datos2['onda'].values
ax.plot(x, y, linewidth=2, color='red')
Out [61]: [<matplotlib.lines.Line2D at 0x7f22675c6160>]