Análisis de series de tiempo – medidas espaciadas de manera desigual – pandas + statsmodels

Tengo dos arrays numpy light_points y time_points y me gustaría usar algunos métodos de análisis de series de tiempo en esos datos.

Entonces intenté esto:

import statsmodels.api as sm import pandas as pd tdf = pd.DataFrame({'time':time_points[:]}) rdf = pd.DataFrame({'light':light_points[:]}) rdf.index = pd.DatetimeIndex(freq='w',start=0,periods=len(rdf.light)) #rdf.index = pd.DatetimeIndex(tdf['time']) 

Esto funciona pero no está haciendo lo correcto. De hecho, las mediciones no están espaciadas uniformemente en el tiempo y, si solo declaro el time_points pandas DataFrame como el índice de mi marco, obtengo un error:

 rdf.index = pd.DatetimeIndex(tdf['time']) decomp = sm.tsa.seasonal_decompose(rdf) elif freq is None: raise ValueError("You must specify a freq or x must be a pandas object with a timeseries index") ValueError: You must specify a freq or x must be a pandas object with a timeseries index 

No sé cómo corregir esto. Además, parece que los pandas ‘ TimeSeries están en desuso.

Intenté esto:

     rdf = pd.Series({'light':light_points[:]}) rdf.index = pd.DatetimeIndex(tdf['time']) 

    Pero me da un desajuste de longitud:

     ValueError: Length mismatch: Expected axis has 1 elements, new values have 122 elements 

    Sin embargo, no entiendo de dónde viene, ya que rdf [‘light’] y tdf [‘time’] son ​​de la misma longitud …

    Finalmente, lo intenté definiendo mi rdf como una serie de pandas:

     rdf = pd.Series(light_points[:],index=pd.DatetimeIndex(time_points[:])) 

    Y entiendo esto:

     ValueError: You must specify a freq or x must be a pandas object with a timeseries index 

    Entonces, traté de reemplazar el índice por

      pd.TimeSeries(time_points[:]) 

    Y me da un error en la línea de método season_decompose:

     AttributeError: 'Float64Index' object has no attribute 'inferred_freq' 

    ¿Cómo puedo trabajar con datos espaciados de forma desigual? Estaba pensando en crear una matriz de tiempo aproximadamente espaciada agregando muchos valores desconocidos entre los valores existentes y utilizando la interpolación para “evaluar” esos puntos, pero creo que podría haber una solución más limpia y más fácil.

    seasonal_decompose() requiere una freq que se proporciona como parte de la metainformación DateTimeIndex , puede ser inferida por pandas.Index.inferred_freq o bien por el usuario como un integer que proporciona el número de períodos por ciclo. por ejemplo, 12 para mensual (de docstring for seasonal_mean ):

     def seasonal_decompose(x, model="additive", filt=None, freq=None): """ Parameters ---------- x : array-like Time series model : str {"additive", "multiplicative"} Type of seasonal component. Abbreviations are accepted. filt : array-like The filter coefficients for filtering out the seasonal component. The default is a symmetric moving average. freq : int, optional Frequency of the series. Must be used if x is not a pandas object with a timeseries index. 

    Para ilustrar – usando datos de muestra al azar:

     length = 400 x = np.sin(np.arange(length)) * 10 + np.random.randn(length) df = pd.DataFrame(data=x, index=pd.date_range(start=datetime(2015, 1, 1), periods=length, freq='w'), columns=['value'])  DatetimeIndex: 400 entries, 2015-01-04 to 2022-08-28 Freq: W-SUN decomp = sm.tsa.seasonal_decompose(df) data = pd.concat([df, decomp.trend, decomp.seasonal, decomp.resid], axis=1) data.columns = ['series', 'trend', 'seasonal', 'resid'] Data columns (total 4 columns): series 400 non-null float64 trend 348 non-null float64 seasonal 400 non-null float64 resid 348 non-null float64 dtypes: float64(4) memory usage: 15.6 KB 

    Hasta ahora, todo bien: ahora se eliminan aleatoriamente elementos de DateTimeIndex para crear datos de espacio de forma desigual:

     df = df.iloc[np.unique(np.random.randint(low=0, high=length, size=length * .8))]  DatetimeIndex: 222 entries, 2015-01-11 to 2022-08-21 Data columns (total 1 columns): value 222 non-null float64 dtypes: float64(1) memory usage: 3.5 KB df.index.freq None df.index.inferred_freq None 

    Ejecutando el valor seasonal_decomp en estos datos ‘funciona’:

     decomp = sm.tsa.seasonal_decompose(df, freq=52) data = pd.concat([df, decomp.trend, decomp.seasonal, decomp.resid], axis=1) data.columns = ['series', 'trend', 'seasonal', 'resid'] DatetimeIndex: 224 entries, 2015-01-04 to 2022-08-07 Data columns (total 4 columns): series 224 non-null float64 trend 172 non-null float64 seasonal 224 non-null float64 resid 172 non-null float64 dtypes: float64(4) memory usage: 8.8 KB 

    La pregunta es: ¿cuán útil es el resultado? Incluso sin espacios en los datos que complican la inferencia de patrones estacionales (ver ejemplo de uso de .interpolate() en las notas de la versión , statsmodels califica este procedimiento de la siguiente manera:

     Notes ----- This is a naive decomposition. More sophisticated methods should be preferred. The additive model is Y[t] = T[t] + S[t] + e[t] The multiplicative model is Y[t] = T[t] * S[t] * e[t] The seasonal component is first removed by applying a convolution filter to the data. The average of this smoothed series for each period is the returned seasonal component.