Pandas Análisis de series temporales

El análisis de series temporales es una parte importante del análisis de datos. Pandas proporciona funciones ricas para procesar y analizar datos de series temporales, incluyendo remuestreo, cálculo móvil, medias móviles, etc.


Operaciones básicas de series temporales

Crear series temporales

Ejemplo

import pandas as pd
import numpy as np

# Crear datos de series temporales
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=100, freq="D")

ts = pd.Series(
    np.random.randn(100).cumsum() + 100,
    index=dates
)

print("Datos de series temporales (primeros 10):")
print(ts.head(10))
print()

# Ver información
print(f"Tipo de índice: {type(ts.index)}")
print(f"Hora de inicio: {ts.index.min()}")
print(f"Hora de fin: {ts.index.max()}")
print(f"Duración: {ts.index.max() - ts.index.min()}")

Establecer la fecha como índice

Ejemplo

import pandas as pd
import numpy as np

# Crear un DataFrame y establecer el índice de fecha
df = pd.DataFrame({
    "Fecha": pd.date_range("2024-01-01", periods=30, freq="D"),
    "Ventas": np.random.randint(100, 500, 30),
    "Visitantes": np.random.randint(50, 200, 30)
})

print("Antes de establecer:")
print(df.head())
print()

# Establecer la fecha como índice
df = df.set_index("Fecha")
print("Después de establecer:")
print(df.head())
print()

# Usar loc para consultar por fecha
print("Consultar de 2024-01-05 a 2024-01-10:")
print(df.loc["2024-01-05":"2024-01-10"])

Remuestreo

El remuestreo (Resampling) es el proceso de convertir datos de series temporales de una frecuencia a otra, lo que incluye el remuestreo ascendente (aumentar puntos de datos) y el remuestreo descendente (reducir puntos de datos).

Remuestreo descendente (Downsampling)

Ejemplo

import pandas as pd
import numpy as np

# Crear datos a nivel diario
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=90, freq="D")
ts = pd.Series(np.random.randint(100, 500, 90), index=dates)

print("Datos a nivel diario (primeros 10):")
print(ts.head(10))
print()

# Remuestrear por mes (suma)
monthly = ts.resample("M").sum()
print("Suma mensual:")
print(monthly)
print()

# Remuestrear por mes (promedio)
monthly_mean = ts.resample("M").mean()
print("Promedio mensual:")
print(monthly_mean)

Remuestreo ascendente (Upsampling)

Ejemplo

import pandas as pd

# Crear datos de baja frecuencia
dates = pd.date_range("2024-01-01", periods=3, freq="M")
ts = pd.Series([100, 200, 150], index=dates)

print("Datos a nivel mensual:")
print(ts)
print()

# Remuestrear a nivel diario (se necesita método de relleno)
ts_daily = ts.resample("D").ffill()
print("Remuestreo ascendente a nivel diario (primeros 10):")
print(ts_daily.head(10))

Métodos de remuestreo comunes

Método Descripción
sum() Suma
mean() Promedio
max() / min() Máximo/Mínimo
first() / last() Primer/último valor
count() Número de valores no nulos
ohlc() Apertura, máximo, mínimo, cierre (OHLC)

Cálculo móvil (Rolling)

El cálculo móvil (Rolling) consiste en realizar cálculos con una ventana deslizante sobre los datos de la serie temporal. Se utiliza frecuentemente para calcular medias móviles, desviaciones estándar móviles, etc.

Media móvil

Ejemplo

import pandas as pd
import numpy as np

# Crear datos
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=30, freq="D")
ts = pd.Series(np.random.randint(100, 200, 30), index=dates)

# Calcular media móvil de 7 días
rolling_mean = ts.rolling(window=7).mean()
print("Media móvil de 7 días (primeros 10):")
print(rolling_mean.head(10))
print()

# Calcular desviación estándar móvil de 7 días
rolling_std = ts.rolling(window=7).std()
print("Desviación estándar móvil de 7 días:")
print(rolling_std.head(10))

Aplicación de funciones personalizadas con Rolling

Ejemplo

import pandas as pd
import numpy as np

ts = pd.Series(range(1, 11))

print("Datos originales:")
print(ts)
print()

# Suma móvil
print("Suma móvil de 3:")
print(ts.rolling(3).sum())
print()

# Máximo móvil
print("Máximo móvil de 3:")
print(ts.rolling(3).max())
print()

# Usar apply
print("Función personalizada de rolling 3 (rango):")
print(ts.rolling(3).apply(lambda x: x.max() - x.min()))

Visualización de datos de series temporales

Ejemplo

import pandas as pd
import numpy as np

# Crear datos de ejemplo
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=100, freq="D")
ts = pd.Series(
    np.random.randn(100).cumsum() + 100,
    index=dates
)

# Calcular media móvil
ma_7 = ts.rolling(7).mean()
ma_30 = ts.rolling(30).mean()

# Mostrar datos
print("Serie temporal + media móvil:")
print(f"Datos originales (primeros 5): {ts.head().tolist()}")
print(f"Media móvil de 7 días (primeros 10): {ma_7.dropna().head().tolist()}")
print(f"Media móvil de 30 días (últimos 5): {ma_30.dropna().tail().tolist()}")

Extracción de características de series temporales

Ejemplo

import pandas as pd

# Crear serie temporal
ts = pd.Series(
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    index=pd.date_range("2024-01-01", periods=10, freq="D")
)

# Diferencia
diff = ts.diff()
print("Diferencia de primer orden:")
print(diff)
print()

# Cambio porcentual
pct = ts.pct_change()
print("Cambio porcentual:")
print(pct)
print()

# Desplazamiento
shifted = ts.shift(1)
print("Desplazamiento hacia atrás de 1:")
print(shifted)

Práctica: Análisis de datos de acciones

Ejemplo

import pandas as pd
import numpy as np

# Simular datos de acciones
np.random.seed(42)
n_days = 60

df = pd.DataFrame({
    "Fecha": pd.date_range("2024-01-01", periods=n_days, freq="D"),
    "Precio de apertura": 100 + np.random.randn(n_days).cumsum(),
    "Precio de cierre": 100 + np.random.randn(n_days).cumsum(),
    "Volumen de negociación": np.random.randint(1000000, 10000000, n_days)
})
df = df.set_index("Fecha")

# Calcular rendimiento diario
df["Rendimiento"] = df["Precio de cierre"].pct_change()

# Calcular la volatilidad (desviación estándar móvil de 7 días)
df["Volatilidad"] = df["Rendimiento"].rolling(7).std() * np.sqrt(252)  # Anualizar

# Calcular líneas de media móvil
df["MA5"] = df["Precio de cierre"].rolling(5).mean()
df["MA20"] = df["Precio de cierre"].rolling(20).mean()

# Generar señales de trading (cruce dorado / cruce de muerte)
df["Señal"] = 0
df.loc[df["MA5"] > df["MA20"], "Señal"] = 1
df.loc[df["MA5"] < df["MA20"], "Señal"] = -1

print("Resultado del análisis de datos de acciones:")
print(df.tail(10))

Preguntas frecuentes

1. Fechas no continuas

Algunas series temporales no tienen datos todos los días (festivos, etc.), es necesario utilizarasfreqoreindexpara procesarlo.

2. Problema de zona horaria

Al procesar datos de múltiples zonas horarias, utilicetz_localizeytz_convertpara configurar y convertir la zona horaria.

3. Impacto de los valores faltantes

El cálculo móvil omite los valores faltantes por defecto, pero puede afectar la continuidad de los resultados.

El análisis de series temporales es una habilidad fundamental en campos como finanzas, meteorología e IoT. Pandas proporciona un conjunto completo de herramientas para procesar este tipo de datos.

Otras extensiones