Python, xarray, pandas y el proyecto ENSO–Baja
2026-09-01
Marina recibió tres tipos de datos:
Hoy quiere pasar de:
¿Cómo han variado la SST frente a Baja California, la precipitación en Ensenada y ENSO durante los últimos 30 años?
Hoy no buscamos una respuesta final.
Buscamos dejar listo un flujo de trabajo para explorar la pregunta.
Queremos tener:
Entramos al proyecto:
Activamos el ambiente:
Abrimos JupyterLab:
Desde la terminal:
ls data
ls data/*.csv
ls data/*.nc
head data/oni_mensual.csv
head data/precipitacion_ensenada_mensual.csvPregunta:
¿Qué tipo de archivo parece cada uno?
¿Podemos leerlos todos de la misma forma?
En notebooks/, crea:
Primera celda:
Un notebook científico debe combinar:
No queremos sólo una lista de celdas ejecutadas.
Queremos que alguien pueda seguir la historia.
En los datos dummy el nombre puede ser:
Al abrir ds, buscar:
Preguntas:
En xarray:
Una variable típica sería:
En parejas:
sst?Pistas:
Pregunta:
¿Qué estamos viendo: un valor absoluto o una anomalía?
Podemos seleccionar por posición:
O por coordenada:
Si la fecha exacta no existe:
Para obtener una serie mensual promedio frente a Baja California:
Graficamos:
Miren la figura.
Pregunta:
¿Qué variabilidad salta primero a la vista?
Normalmente veremos un ciclo estacional fuerte.
Eso puede ocultar variabilidad interanual.
Calculamos el promedio para cada mes del año:
Graficamos:
Restamos la climatología de cada mes:
Graficamos:
La anomalía nos ayuda a comparar enero con enero, julio con julio, etc.
Haz una figura de la anomalía de SST y guárdala en figures/.
fig, ax = plt.subplots()
ssta_bc.plot(ax=ax)
ax.axhline(0, color="k", linewidth=0.8)
ax.set_title("Anomalía de SST frente a Baja California")
ax.set_ylabel("SSTA")
fig.savefig("../figures/ssta_baja_timeseries.png", dpi=150, bbox_inches="tight")Verifica desde la terminal:
Preguntas:
Idealmente queremos una columna de tiempo entendida como fecha:
oni = pd.read_csv("../data/oni_mensual.csv", parse_dates=["time"])
oni = oni.set_index("time")
oni.head()Si la columna se llama distinto, hay que adaptar el código.
oni["oni"].plot()
plt.axhline(0, color="k", linewidth=0.8)
plt.title("Índice ONI")
plt.ylabel("ONI")Pregunta:
¿Cuándo aparecen eventos positivos y negativos?
Usando la gráfica de ONI:
No necesitamos responder todavía.
Sólo estamos formulando una pregunta.
rain = pd.read_csv("../data/precipitacion_ensenada_mensual.csv", parse_dates=["time"])
rain = rain.set_index("time")
rain.head()Preguntas:
rain["precip_mm"].plot()
plt.title("Precipitación mensual en Ensenada")
plt.ylabel("Precipitación [mm]")Pregunta:
¿Conviene comparar precipitación mensual directamente con ONI mensual?
Para precipitación quizá nos interesen acumulados invernales.
Ejemplo simple:
Hasta ahora tenemos:
Cada una responde a una pregunta distinta.
El proyecto final consistirá en decidir:
¿qué comparación vale la pena mostrar?
Ejemplo: SSTA regional y ONI.
fig, ax = plt.subplots()
ssta_bc.plot(ax=ax, label="SSTA Baja California")
ax.set_title("SSTA regional")
ax.set_ylabel("SSTA")
ax.legend()Para comparar con ONI puede ser necesario alinear fechas y unidades.
Dos series que se parecen no prueban causalidad.
Preguntas importantes:
El notebook sirve muy bien para explorar.
Un script sirve para repetir una tarea.
Por ejemplo:
import matplotlib.pyplot as plt
import xarray as xr
# Leer datos
ds = xr.open_dataset("data/sst_baja_mensual_1994_2024.nc")
sst = ds["sst"]
# Calcular anomalía regional
sst_bc = sst.mean(dim=("lat", "lon"))
clim = sst_bc.groupby("time.month").mean("time")
ssta_bc = sst_bc.groupby("time.month") - clim
# Figura
fig, ax = plt.subplots()
ssta_bc.plot(ax=ax)
ax.axhline(0, color="k", linewidth=0.8)
ax.set_title("Anomalía de SST frente a Baja California")
ax.set_ylabel("SSTA")
fig.savefig("figures/ssta_baja_timeseries.png", dpi=150, bbox_inches="tight")Desde el directorio principal del proyecto:
Verificar:
También empezamos a entender:
Marina ya tiene código, figuras y decisiones.
Pero mañana puede cambiar algo y arrepentirse.
Pregunta final:
¿Cómo guardamos la historia del proyecto sin llenar la carpeta de versiones finales?
Mañana: Git y GitHub.
Introducción a programación científica · DOF · Sesión 2