lección 2
Descomponer una serie: tendencia, estacionalidad y ruido
Separar una serie en sus tres piezas con seasonal_decompose, elegir entre aditivo y multiplicativo, y revelar la tendencia con la media móvil.
⏱ 50 min
¿Cómo sabes si tu negocio está creciendo cuando cada diciembre vendes el triple y cada agosto la mitad? El dato en bruto no te lo dice: sube y baja tanto por el calendario que la señal que de verdad importa —si el nivel de fondo mejora o empeora— queda enterrada bajo el vaivén estacional. La respuesta es un procedimiento con casi un siglo de historia: separar la serie en las piezas que la componen, mirarlas una a una, y responder la pregunta de dirección sobre la pieza que la contiene y solo sobre esa. A ese procedimiento se le llama descomposición, y es la primera cosa que un profesional hace cuando le ponen delante una serie temporal.
La idea de que una serie es la suma de piezas con significados distintos no es nueva: cuando los economistas aprendieron a quitarle a las series oficiales su latido estacional, lo que hacían por detrás era exactamente esto. El trabajo con series temporales empezó precisamente ahí, en separar el patrón que se repite del movimiento que no. Lo que vamos a hacer ahora es poner números y gráficos a esa separación: tomar una serie real, pedirle a la máquina que la parta en tendencia, estacionalidad y ruido, y ver las tres piezas dibujadas. Cuando las tengas separadas, cada una responde a una pregunta que la serie entera no sabía contestar.
## El modelo mental: la serie es la suma (o el producto) de sus piezas
Descomponer una serie parte de una hipótesis sencilla: el valor que observas cada día es el resultado de combinar tres cosas. Un nivel de fondo que cambia despacio (la tendencia), un patrón que se repite con el calendario (la estacionalidad), y lo que queda cuando quitas los dos anteriores (el ruido). La pregunta es cómo se combinan, y hay dos respuestas posibles que no son intercambiables: o se suman, o se multiplican. Elegir mal entre las dos es el error típico de esta técnica, así que vale la pena entenderlo antes de tocar código.
En el modelo aditivo, la serie es tendencia más estacionalidad más ruido. La estacionalidad suma o resta una cantidad fija, en las mismas unidades que la serie: si cada diciembre vendes 2.000 euros más que el nivel de fondo, ese "+2.000" es el mismo tanto si tu nivel de fondo son 10.000 como si son 50.000. El pico de diciembre tiene siempre la misma altura en euros, no importa lo grande que sea el negocio. Visualmente, la amplitud de las olas estacionales es constante: suben y bajan lo mismo todos los años.
En el modelo multiplicativo, la serie es tendencia por estacionalidad por ruido. La estacionalidad es un factor, un porcentaje: cada diciembre vendes un 30% más que el nivel de fondo. Y un 30% de 10.000 son 3.000, pero un 30% de 50.000 son 15.000. Así que a medida que el negocio crece, los picos de diciembre crecen con él: las olas estacionales son cada vez más grandes. Esta es la pista visual que decide entre los dos modelos: si al mirar la serie las oscilaciones estacionales se agrandan según sube la tendencia, es multiplicativo; si se mantienen igual de altas aunque el nivel suba, es aditivo.
La regla práctica para elegir: mira el dibujo de la serie. ¿Las subidas y bajadas estacionales son del mismo tamaño a lo largo de todo el gráfico, o se van haciendo más grandes a medida que la serie sube? Si son constantes, aditivo. Si crecen con el nivel, multiplicativo. Y un atajo que casi siempre acierta: la mayoría de las series de negocio (ventas, ingresos, usuarios) son multiplicativas, porque los patrones estacionales suelen ser porcentuales —"diciembre vende un 40% más"— y no cantidades fijas. Las series de magnitudes físicas acotadas (temperatura, por ejemplo) tienden a ser aditivas, porque el pico de verano sube los mismos grados cada año, no un porcentaje.
## La media móvil: cómo se extrae la tendencia
Antes de usar la herramienta automática conviene entender qué hace por dentro, porque el ingrediente principal es algo que ya has visto: promediar cada punto con sus vecinos. Esa operación se llama media móvil, y es la forma más sencilla y más usada de extraer la tendencia de una serie. La idea: para cada día, en vez de quedarte con su valor, calculas la media de ese día y los que tiene alrededor dentro de una ventana. Si la ventana es de siete días, cada punto pasa a ser el promedio de la semana centrada en él. El vaivén diario —el ruido y la estacionalidad corta— se cancela, porque unos días están por encima y otros por debajo, y lo que sobrevive es el nivel de fondo.
El tamaño de la ventana es la decisión clave, y tiene una lógica preciosa cuando hay estacionalidad: la ventana debe medir exactamente un periodo estacional completo. Si tus datos son diarios y la estacionalidad es semanal, usa una ventana de siete días; así cada media móvil contiene exactamente un lunes, un martes... un domingo, y el patrón semanal se promedia hasta desaparecer, dejando solo la tendencia. Si usaras una ventana de tres días, quedarían restos del patrón semanal dentro. Y si la haces demasiado larga, la media móvil se vuelve tan suave que empieza a aplanar también la tendencia real. La ventana del tamaño de un periodo es el punto justo: borra la estacionalidad sin matar la tendencia.
En pandas, la media móvil se calcula con rolling, que crea una ventana deslizante sobre la serie, y encima se pide la operación: rolling(7).mean() da la media de cada ventana de siete valores. Lo único que hay que recordar es que los primeros valores salen vacíos: para calcular la media de siete días centrada en el día 1 harían falta tres días antes del primero, que no existen. Por eso una media móvil siempre tiene huecos en los extremos, y por eso una descomposición pierde un poco de serie al principio y al final.
1import numpy as np2import pandas as pd34# Ventas diarias de tres semanas: ruido fuerte sobre una tendencia creciente5np.random.seed(42)6dias = pd.date_range("2026-01-01", periods=21, freq="D")7tendencia = np.linspace(100, 160, 21) # sube de 100 a 1608ruido = np.random.normal(0, 12, 21) # vaiven diario9ventas = pd.Series(tendencia + ruido, index=dias)1011# Media movil de 7 dias: borra el vaiven semanal y revela la tendencia12media_movil = ventas.rolling(window=7, center=True).mean()1314primera = media_movil.dropna().iloc[0]15ultima = media_movil.dropna().iloc[-1]16print(f"La tendencia suavizada sube: {ultima > primera}")17print(f"Puntos sin dato por los bordes: {media_movil.isna().sum()}")
rolling(7).mean() promedia cada día con su semana: el ruido se cancela y queda la tendencia
## seasonal_decompose: las tres piezas de una vez
Hacer la descomposición a mano —media móvil para la tendencia, restar para quedarte con la estacionalidad, promediar por periodo para estabilizarla y restar otra vez para el ruido— es instructivo pero tedioso. La herramienta estándar que lo hace de golpe se llama seasonal_decompose, y vive en el módulo de series temporales de statsmodels, una de las librerías de estadística más veteranas de Python. Le das la serie, le dices cuál es el periodo estacional y si el modelo es aditivo o multiplicativo, y te devuelve las tres piezas por separado, listas para dibujar o para analizar.
El parámetro que no puedes equivocar es el periodo. Es cuántas observaciones hay en un ciclo estacional completo: 12 si tienes datos mensuales con estacionalidad anual, 7 si tienes datos diarios con estacionalidad semanal, 24 si tienes datos horarios con estacionalidad diaria. Si le dices un periodo que no es el real, la herramienta separa mal: mete parte de la estacionalidad en la tendencia o al revés, y las tres piezas salen contaminadas. Saber el periodo no es adivinar: es conocer tus datos y saber cada cuánto se repite el patrón que ves.
1import numpy as np2import pandas as pd3from statsmodels.tsa.seasonal import seasonal_decompose45# Dos anios de ventas mensuales con tendencia + estacionalidad anual (periodo 12)6np.random.seed(42)7meses = pd.date_range("2025-01-01", periods=24, freq="MS")8tendencia = np.linspace(1000, 1600, 24)9# patron anual: pico en diciembre (indice 11 y 23), valle en agosto10estacional = np.array([0, -40, 20, 60, 80, 40, -60, -120, -30, 50, 120, 260] * 2)11ruido = np.random.normal(0, 15, 24)12ventas = pd.Series(tendencia + estacional + ruido, index=meses)1314resultado = seasonal_decompose(ventas, model="additive", period=12)1516# El pico estacional cae en diciembre y el valle en agosto?17estac = resultado.seasonal18pico_diciembre = estac.iloc[11] == estac.max()19valle_agosto = estac.iloc[7] == estac.min()20print(f"Pico estacional en diciembre: {pico_diciembre}")21print(f"Valle estacional en agosto: {valle_agosto}")22print(f"La tendencia extraida crece: {resultado.trend.dropna().iloc[-1] > resultado.trend.dropna().iloc[0]}")
seasonal_decompose separa la serie en tendencia, estacionalidad y ruido; se comprueba la forma, no los valores crudos
## El residuo es el chivato de si la descomposición salió bien
De las tres piezas que devuelve la descomposición, la que más se ignora y más información da es el residuo, el ruido que queda al final. La tentación es mirar la tendencia (que es la que interesa) y la estacionalidad (que es vistosa) y dar por buena la separación. Pero el residuo es el control de calidad: si la descomposición ha hecho bien su trabajo, el residuo tiene que parecerse a ruido puro —vaivén aleatorio alrededor de cero, sin ninguna forma reconocible—. Esa es la señal de que has exprimido toda la señal de la serie y lo único que queda es lo impredecible, que es exactamente lo que debe quedar.
Y al revés: si al dibujar el residuo todavía ves estructura —una ondita que sube y baja con regularidad, un tramo donde el residuo es sistemáticamente positivo y otro donde es negativo—, la descomposición se ha dejado señal sin separar y hay que sospechar. Un residuo con olas regulares significa que la estacionalidad que estimaste no coincide con la real: o te equivocaste de periodo, o la estacionalidad cambia con el tiempo y el modelo de patrón fijo no la captura. Un residuo que tiene su propia pendiente significa que la media móvil no capturó toda la tendencia. Leer el residuo es, en la práctica, la forma de distinguir una descomposición que ha entendido la serie de una que ha repartido los números de cualquier manera.
## Para qué sirve de verdad: desestacionalizar
La aplicación más útil de la descomposición es la que abrió esta historia: quitarle a la serie su estacionalidad para poder leer la tendencia sin que el calendario la tape. A eso se le llama desestacionalizar, y es lo que hacen los institutos de estadística con el paro, la inflación o las ventas minoristas. El procedimiento es directo una vez que tienes las piezas: a la serie observada le restas la componente estacional (si el modelo es aditivo) o la divides por ella (si es multiplicativo), y lo que queda es la serie limpia del patrón repetido. Sobre esa serie desestacionalizada ya puedes comparar meses consecutivos con honestidad: si enero desestacionalizado es más bajo que diciembre desestacionalizado, el negocio ha ido realmente a peor, no es solo que enero siempre sea flojo.
La segunda aplicación, menos obvia pero igual de valiosa, es detectar anomalías. Cuando le has quitado a una serie su tendencia y su estacionalidad, el residuo debería ser pequeño y aleatorio; así que un residuo enorme en una fecha concreta es exactamente eso: algo que no encaja con ningún patrón conocido, una anomalía que merece una explicación. Esta es la base de muchos sistemas de alerta automática. En vez de poner un umbral fijo sobre la serie cruda —que saltaría todos los diciembres por el pico normal de Navidad y nunca saltaría en un agosto flojo aunque fuera anormalmente flojo—, se descompone la serie y se vigila el residuo. Un pico en el residuo en pleno diciembre significa "este diciembre ha sido raro incluso para ser diciembre", que es la alerta que de verdad importa. Separar lo esperado de lo inesperado es, de nuevo, el trabajo entero.
Vale la pena situar esta técnica en su contexto, porque explica por qué sigue siendo el primer paso después de casi un siglo. La descomposición nació como una herramienta puramente descriptiva: separar las piezas para entender y comunicar, no para predecir. Los métodos de predicción potentes vinieron mucho después y, en gran medida, incorporaron por dentro esta misma idea de separar tendencia y estacionalidad. Pero el hábito de descomponer primero, a mano y mirando los gráficos, no ha desaparecido, y no por nostalgia: es que ningún modelo automático te va a avisar de que elegiste mal el periodo o de que tu estacionalidad cambia con los años. Esos problemas se ven con el ojo, en los paneles de la descomposición, antes de que ningún modelo los herede sin que te enteres. Descomponer es cómo entiendes la serie; modelar es lo que haces después, cuando ya sabes qué tienes delante.
Esto resuelve el problema del responsable que dice "este agosto hemos vendido menos que en julio". Con la serie desestacionalizada, la comparación tiene sentido: le has quitado a los dos meses su factor estacional, así que si agosto desestacionalizado sigue siendo más bajo, hay un problema real; y si una vez desestacionalizado agosto está al nivel de julio o por encima, la caída que veía era puro calendario y no hay nada que arreglar. Es la diferencia entre asustarse por una caída que ocurre todos los años y detectar una caída que no debería estar ahí.
Consejo de senior: cuando presentes una serie desestacionalizada a alguien de negocio, enséñale las dos líneas superpuestas: la original con sus dientes de sierra y la desestacionalizada suave. El contraste visual hace el argumento solo. "Esta de abajo, con los picos, es lo que vendemos; esta de aquí, lisa, es cómo vamos de verdad quitando el efecto Navidad." En un segundo entiende por qué la caída de enero que le preocupaba no era nada, y por qué la bajada lenta de la línea lisa sí debería preocuparle. Separar el ruido estacional de la señal real es, muchas veces, el análisis entero.
La descomposición clásica tiene un punto ciego: supone que el patrón estacional es idéntico en todos los periodos. Si tu estacionalidad va cambiando con el tiempo —porque el negocio cambia, porque la gente cambia de hábitos—, seasonal_decompose la promedia en un único patrón fijo y pierde esa evolución. Para la mayoría de los casos vale de sobra, pero si al mirar el panel de ruido ves que todavía queda estructura estacional (olas regulares donde debería haber solo vaivén aleatorio), es la señal de que la estacionalidad no era tan constante como el modelo asume.
## Lo que te llevas
Separar una serie en sus piezas convierte una pregunta imposible —"¿vamos bien?" sobre una serie llena de dientes de sierra— en tres preguntas que sí se pueden responder: ¿cómo va el nivel de fondo (tendencia)?, ¿cuánto pesa el calendario (estacionalidad)?, ¿cuánto de lo que veo es irrepetible (ruido)? La media móvil extrae la tendencia promediando una ventana del tamaño de un periodo; seasonal_decompose hace las tres piezas de golpe; y la elección entre aditivo y multiplicativo la decide una sola mirada al dibujo: ¿crecen las olas o no?
Hay una condición escondida en todo esto que todavía no hemos nombrado. Para que un modelo pueda predecir una serie, muchas veces necesita que la serie tenga un comportamiento estable en el tiempo: que su nivel y su variabilidad no se vayan de las manos. Una serie con una tendencia fuerte no cumple eso, y la descomposición es justo la herramienta que te deja quitarle la tendencia para dejarla en una forma que un modelo pueda tratar. Qué significa exactamente ese comportamiento estable, por qué los modelos lo exigen y cómo se consigue y se comprueba es lo siguiente que necesitas.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...
Regístrate para guardar tu progreso.