Saltar al contenido

decompose () para series de tiempo: ValueError: debe especificar un período ox debe ser un objeto pandas con un DatetimeIndex con una frecuencia no establecida en None

Luego de de esta extensa selección de datos hemos podido solucionar este enigma que presentan ciertos de nuestros lectores. Te ofrecemos la respuesta y deseamos servirte de gran ayuda.

Solución:

Tener el mismo ValueError, esto es solo el resultado de algunas pruebas y poca investigación por mi cuenta, sin la pretensión de ser completo o profesional al respecto. Por favor comente o responda a quien encuentre algo mal.

Por supuesto, sus datos deben estar en el orden correcto de los valores del índice, lo que aseguraría con df.sort_index(inplace=True), como lo indica en su respuesta. Esto no es incorrecto como tal, aunque el mensaje de error no es sobre el orden de clasificación, y he comprobado esto: el error no desaparece en mi caso cuando clasifico el índice de un enorme conjunto de datos que tengo a mano. Está true, También tengo que ordenar el df.index, pero el decompose () también puede manejar datos sin clasificar donde los elementos saltan aquí y allá en el tiempo: luego simplemente obtienes muchas líneas azules de izquierda a derecha y viceversa, hasta que todo el gráfico está lleno de eso. Además, por lo general, la clasificación ya está en el orden correcto de todos modos. En mi caso, ordenar no ayuda a corregir el error. Por lo tanto, también dudo que la clasificación de índices haya solucionado el error en su caso, porque: ¿qué dice realmente el error?

ValueError: debe especificar:

  1. [either] un período
  2. o x debe ser un objeto pandas con un DatetimeIndex con una frecuencia no establecida en None

Antes que nada, en caso de que tengas un columna de lista para que su serie de tiempo esté anidada hasta ahora, consulte Convertir pandas df con datos en una “columna de lista” en una serie de tiempo en formato largo. Utilice tres columnas: [list of data] + [timestamp] + [duration] para obtener detalles sobre cómo desanidar un columna de lista. Esto sería necesario tanto para 1.) como para 2.).

Detalles de 1 .:

Definición de período

“período, int, opcional” de https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.seasonal_decompose.html:

Periodo de la serie. Debe usarse si x no es un objeto pandas o si el índice de x no tiene frecuencia. Anula la periodicidad predeterminada de x si x es un objeto pandas con un índice de serie temporal.

El parámetro de período que se establece con un número entero significa el número de ciclos que espera que estén en los datos. Si tiene un df con 1000 filas con un columna de lista en él (llámelo df_nested), y cada lista con, por ejemplo, 100 elementos, entonces tendrá 100 elementos por ciclo. Probablemente sea inteligente tomar period = len(df_nested) (= número de ciclos) para obtener la mejor división de estacionalidad y tendencia. Si sus elementos por ciclo varían con el tiempo, otros valores pueden ser mejores.

El parámetro “período” de la opción 1.) tiene una gran ventaja sobre la opción 2.). Aunque utiliza el índice de tiempo (DatetimeIndex) para su eje x, no requiere que un elemento alcance la frecuencia exactamente, a diferencia de la opción 2.). En cambio, simplemente une lo que está en una fila, con la ventaja de que no necesita llenar ningún espacio: el último valor del evento anterior simplemente se une con el siguiente valor del siguiente evento, si ya está en el siguiente segundo o al día siguiente.

¿Cuál es el valor máximo posible de “período”? En caso de que tenga un columna de lista (llame al df “df_nested” nuevamente), primero debe desanimar los columna de lista a un columna normal. El período máximo es len(df_unnested)/2.

Ejemplo 1: 20 elementos en x (x es la cantidad de todos los elementos de df_unnested) pueden tener como máximo un period = 10.

Ejemplo 2: Tener los 20 elementos y tomar period=20 en cambio, esto arroja el siguiente error:

ValueError: x debe tener 2 ciclos completos y requiere 40 observaciones. x solo tiene 20 observación (es)

Otra nota al margen: para deshacerse del error en cuestión, period = 1 ya debería eliminarlo, pero para el análisis de series de tiempo, “= 1” no revela nada nuevo, cada ciclo es solo 1 elemento, la tendencia es la misma que los datos originales, la estacionalidad es 0 y los residuos son siempre 0.

####

Ejemplo tomado de Convertir pandas df con datos en una “columna de lista” en una serie de tiempo en formato largo. Utilice tres columnas: [list of data] + [timestamp] + [duration]

df_test = pd.DataFrame('timestamp': [1462352000000000000, 1462352100000000000, 1462352200000000000, 1462352300000000000],
                'listData': [[1,2,1,9], [2,2,3,0], [1,3,3,0], [1,1,3,9]],
                'duration_sec': [3.0, 3.0, 3.0, 3.0])
tdi = pd.DatetimeIndex(df_test.timestamp)
df_test.set_index(tdi, inplace=True)
df_test.drop(columns='timestamp', inplace=True)
df_test.index.name = 'datetimeindex'

df_test = df_test.explode('listData') 
sizes = df_test.groupby(level=0)['listData'].transform('size').sub(1)
duration = df_test['duration_sec'].div(sizes)
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount() * duration, unit='s') 

El df_test resultante[‘listData’] tiene el siguiente aspecto:

2016-05-04 08:53:20    1
2016-05-04 08:53:21    2
2016-05-04 08:53:22    1
2016-05-04 08:53:23    9
2016-05-04 08:55:00    2
2016-05-04 08:55:01    2
2016-05-04 08:55:02    3
2016-05-04 08:55:03    0
2016-05-04 08:56:40    1
2016-05-04 08:56:41    3
2016-05-04 08:56:42    3
2016-05-04 08:56:43    0
2016-05-04 08:58:20    1
2016-05-04 08:58:21    1
2016-05-04 08:58:22    3
2016-05-04 08:58:23    9

Ahora eche un vistazo a los valores enteros de diferentes períodos.

period = 1:

result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=1)
plt.rcParams.update('figure.figsize': (5,5))
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

ingrese la descripción de la imagen aquí

period = 2:

result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=2)
plt.rcParams.update('figure.figsize': (5,5))
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

ingrese la descripción de la imagen aquí

Si toma una cuarta parte de todos los elementos como un ciclo, que es 4 (de 16 elementos) aquí.

period = 4:

result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/4))
plt.rcParams.update('figure.figsize': (5,5))
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

ingrese la descripción de la imagen aquí

O si toma el tamaño máximo posible de un ciclo que es 8 (de 16 artículos) aquí.

period = 8:

result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/2))
plt.rcParams.update('figure.figsize': (5,5))
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

ingrese la descripción de la imagen aquí

Observe cómo los ejes y cambian su escala.

####

Aumentarás el número entero del período según tus necesidades. El máximo en su caso de la pregunta:

sm.tsa.seasonal_decompose(df, model = 'additive', period = int(len(df)/2))

Detalles de 2 .:

Para que x sea un DatetimeIndex con una frecuencia no establecida en None, debe asignar la frecuencia del DatetimeIndex usando .asfreq (‘?’) Con? siendo su elección entre una amplia gama de alias de compensación de https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases.

En su caso, esta opción 2. es la más adecuada, ya que parece tener una lista sin espacios. Sus datos mensuales probablemente deberían introducirse como “frecuencia de inicio del mes” -> “MS” como alias de compensación:

sm.tsa.seasonal_decompose(df.asfreq('MS'), model = 'additive')

Consulte ¿Cómo establecer la frecuencia con pd.to_datetime ()? para obtener más detalles, también sobre cómo manejaría las brechas.

Si tiene datos muy dispersos en el tiempo, por lo que tiene demasiados huecos que llenar o si los huecos en el tiempo no son nada importantes, la opción 1 de utilizar “punto” es probablemente la mejor opción.

En mi caso de ejemplo de df_test, la opción 2. no es buena. Los datos están totalmente dispersos en el tiempo, y si tomo un minuto como frecuencia, obtienes esto:

Salida de df_test.asfreq('s') (= frecuencia en segundos):

2016-05-04 08:53:20      1
2016-05-04 08:53:21      2
2016-05-04 08:53:22      1
2016-05-04 08:53:23      9
2016-05-04 08:53:24    NaN
                      ...
2016-05-04 08:58:19    NaN
2016-05-04 08:58:20      1
2016-05-04 08:58:21      1
2016-05-04 08:58:22      3
2016-05-04 08:58:23      9
Freq: S, Name: listData, Length: 304, dtype: object

Aquí puede ver que aunque mis datos son solo 16 filas, la introducción de una frecuencia en segundos obliga a que el df sea de 304 filas solo para llegar desde “08:53:20” hasta “08:58:23”, aquí se producen 288 espacios. . Es más, aquí tienes que marcar la hora exacta. Si tiene 0.1 o incluso 0.12314 segundos como su frecuencia real, no alcanzará la mayoría de los elementos con su índice.

Aquí un ejemplo con min como el alias de compensación, df_test.asfreq('min'):

2016-05-04 08:53:20      1
2016-05-04 08:54:20    NaN
2016-05-04 08:55:20    NaN
2016-05-04 08:56:20    NaN
2016-05-04 08:57:20    NaN
2016-05-04 08:58:20      1

Vemos que solo el primer y el último minuto se llenan en absoluto, el resto no se golpea.

Tomando el día como alias de compensación, df_test.asfreq('d'):

2016-05-04 08:53:20    1

Vemos que obtiene solo la primera fila como el gl resultante, ya que solo hay un día cubierto. Le dará el primer elemento encontrado, el resto se descarta.

El fin de todo:

Juntando todo esto, en su caso, elija la opción 2., mientras que en mi caso de ejemplo de df_test, se necesita la opción 1.

Tuve el mismo problema y finalmente resultó (en mi caso, al menos) ser un problema de puntos de datos faltantes en mi conjunto de datos. En el ejemplo, tengo datos por hora durante un cierto período de tiempo y allí faltan 2 puntos de datos por hora separados (en el medio del conjunto de datos). Entonces obtuve el mismo error. Al probar en un conjunto de datos diferente sin puntos de datos faltantes, funcionó sin ningún mensaje de error. Espero que esto ayude. No es exactamente una solución.

Te mostramos las reseñas y valoraciones de los usuarios

Nos puedes apoyar nuestra investigación ejecutando un comentario o dejando una puntuación te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *