
Introducción a Xarray¶
Xarray
es una librería de Python diseñada para facilitar el análisis y manipulación de datos multidimensionales etiquetados (como los que provienen de modelos climáticos, observaciones satelitales o simulaciones numéricas).
Inspirado en la estructura de Pandas
, Xarray
extiende su funcionalidad a arreglos N-dimensionales, permitiendo trabajar de forma intuitiva con datos que tienen múltiples coordenadas como tiempo, latitud y longitud.
Xarray es especialmente popular en ciencias de la Tierra y del clima, donde los datos suelen venir en formatos como NetCDF, Zarr o GRIB.
📚 ¿Qué vas a aprender?¶
Al completar este cuadernillo serás capaz de:
- Comprender qué son
DataArray
yDataset
- Crear objetos Xarray desde arreglos de NumPy
- Asignar dimensiones y coordenadas
- Explorar y seleccionar datos usando coordenadas
- Calcular estadísticas y aplicar operaciones
- Visualizar datos con
.plot()
- Leer datos reales desde archivos NetCDF
✅ Requisitos previos¶
Concepto | Importancia | Notas |
---|---|---|
Introducción a NumPy | Necesario | Arreglos multidimensionales |
Fundamentos de Pandas | Necesario | Indexado y manipulación tabular |
Uso de JupyterLab | Útil | Navegación entre celdas |
⏱️ Tiempo estimado de aprendizaje: 20–25 minutos
✍️ Formato: interactivo, ejecuta y modifica el código a medida que avanzas
1. Primeros pasos con Xarray 🧪¶
La unidad básica en Xarray es el DataArray
, que extiende la funcionalidad de los ndarray
de NumPy. A diferencia de NumPy, Xarray permite asignar:
- Dimensiones con nombre (
time
,lat
,lon
, etc.) - Coordenadas con etiquetas asociadas
- Atributos descriptivos como unidades, nombre estándar, etc.
Esta herramienta es particularmente poderosa cuando se trabaja con datos atmosféricos, oceanográficos o climáticos provenientes de modelos numéricos o sensores remotos, donde las variables dependen del tiempo, la latitud, la longitud y a veces también de la altitud.
Importemos las librerias necesarias para este cuadernillo
import xarray as xr
import numpy as np
import pandas as pd
🎛️ 1.1. Crear un DataArray
desde NumPy¶
Para comenzar, creamos una matriz tridimensional con valores simulados de temperatura (en grados Kelvin). Esta matriz tendrá dimensiones que representan el tiempo, la latitud y la longitud:
data = 283 + 5 * np.random.randn(5, 3, 4) # 5 tiempos, 3 latitudes, 4 longitudes
data.shape
(5, 3, 4)
Podemos construir un DataArray
inicial directamente desde este arreglo de NumPy, aunque sin información adicional aún:
temp = xr.DataArray(data)
temp
⚠️ Como no definimos nombres para las dimensiones, Xarray usa nombres genéricos como dim_0
, dim_1
, dim_2
, lo cual puede dificultar la interpretación de los datos.
1.2 Asignar nombres de dimensiones 📀¶
Para mejorar la legibilidad, asignamos nombres explícitos a las dimensiones. Esto convierte un arreglo anónimo en un conjunto de datos más descriptivo y navegable:
temp = xr.DataArray(data, dims=["time", "lat", "lon"])
temp
Creamos un objeto con datos y dimensiones que gráficamente se podría representar de la siguiente manera:
Esto nos permite realizar operaciones sobre dimensiones por nombre, en lugar de índices numéricos.
1.3 Agregar coordenadas a las dimensiones 🗺️¶
Además de los nombres, podemos asociar coordenadas reales que representen valores geográficos o temporales. Esto permite, por ejemplo, ubicar espacialmente los datos o hacer filtrados temporales:
times = pd.date_range("2018-01-01", periods=5)
lats = np.linspace(25, 55, 3)
lons = np.linspace(-120, -90, 4)
Construimos nuevamente el DataArray
, esta vez incluyendo coordenadas:
temp = xr.DataArray(data, coords=[times, lats, lons], dims=["time", "lat", "lon"])
temp
Con esto obtenemos un objeto con visualización enriquecida: las dimensiones están etiquetadas y cada punto tiene una referencia espacial y temporal clara.
1.4 Agregar atributos descriptivos 🏷️¶
Finalmente, Xarray permite incluir metadatos como unidades físicas, nombres estándar de variables o descripciones adicionales. Esto es importante para la trazabilidad y para facilitar el trabajo colaborativo o la publicación de datos:
temp.attrs["units"] = "K"
temp.attrs["standard_name"] = "air_temperature"
Estos atributos no alteran los datos, pero se usan al exportar, graficar o convertir los objetos a otros formatos como netCDF. También ayudan a los usuarios a entender rápidamente qué representa el conjunto de datos.
2. Dataset: Contenedor multidimensional 🧳¶
Mientras que un DataArray
representa una sola variable con sus dimensiones y coordenadas, un Dataset
es un contenedor que puede almacenar múltiples DataArray
s, que posiblemente compartan dimensiones y coordenadas.
Esto es muy útil en ciencias ambientales, donde queremos trabajar simultáneamente con variables como temperatura, presión, humedad, etc., dentro de un mismo archivo o conjunto de datos.
2.1 Crear múltiples DataArrays 🌡️¶
Partimos de los DataArray
s que representan distintas variables físicas como temperatura del aire, presión atmosférica y humedad relativa:
# Temperatura
temp = xr.DataArray(
data=283 + 5 * np.random.randn(5, 3, 4),
coords={"time": times, "lat": lats, "lon": lons},
dims=["time", "lat", "lon"],
name="Temperature",
attrs={"units": "K", "standard_name": "air_temperature"}
)
# Presión
pressure = xr.DataArray(
data=1000 + 10 * np.random.randn(5, 3, 4),
coords={"time": times, "lat": lats, "lon": lons},
dims=["time", "lat", "lon"],
name="Pressure",
attrs={"units": "hPa", "standard_name": "air_pressure"}
)
# Humedad relativa
hr = xr.DataArray(
data=np.random.uniform(60, 100, size=5),
coords={"time": times},
dims=["time"],
name="RelativeHumidity",
attrs={"units": "%", "standard_name": "relative_humidity"}
)
2.2 Crear el Dataset 📦¶
Una vez definidos los DataArray
s, podemos crear un Dataset
pasando un diccionario con las variables:
ds = xr.Dataset(
data_vars={
"Temperature": temp,
"Pressure": pressure,
"RelativeHumidity": hr
}
)
En un entorno interactivo como JupyterLab, este Dataset
se mostrará como una menu desplegable que incluye:
- Dimensiones (
dims
) - Coordenadas (
coords
) - Variables (
data_vars
) - índices (
indexes
) - Atributos (
attrs
)
ds
La visualización del Dataset
mostrará las dimensiones compartidas, las coordenadas y un resumen de cada variable contenida como se muestra en la siguiente imagen tomada de la documentación de xarray
Esto permite acceder rápidamente a las dimensiones comunes y explorar todas las variables de forma estructurada.
3. Selección de datos y operaciones básicas 🧩¶
Una vez que tenemos nuestros datos organizados en DataArray
o Dataset
, Xarray nos permite acceder, filtrar y operar sobre ellos de forma muy intuitiva utilizando etiquetas en lugar de índices numéricos.
3.1 Acceder a variables en un Dataset 🔎¶
Cada variable contenida dentro de un Dataset
es un DataArray
, y se puede acceder de manera sencilla usando notacion por atributo ds.<atributo>
(acceso directo si el nombre es válido)
ds.Temperature
O Notación por clave de diccionario (más general y flexible)
ds["Pressure"]
Ambas formas retornan el DataArray
correspondiente. La primera es más compacta, útil en notebooks interactivos; la segunda es más robusta, especialmente si los nombres contienen espacios, guiones u otros caracteres especiales.
3.2 Seleccionar datos por coordenadas con .sel()
🧭¶
El método .sel()
permite seleccionar subconjuntos de datos utilizando los valores de las coordenadas en lugar de los índices posicionales. Esto hace que el código sea más legible y expresivo.
Por ejemplo, podemos seleccionar todos los datos para una fecha específica
ds.sel(time="2018-01-01")
O seleccionar una variable y una ubicación específica
ds.Temperature.sel(time="2018-01-01", lat=25, lon=-120)
✅ Muy útil y conveniente cuando trabajamos con fechas o ubicaciones reales.
3.3 Seleccionar datos por posición con .isel()
🔹¶
Si en cambio queremos seleccionar por posición (como con NumPy), usamos .isel()
. Esto es útil cuando no conocemos las coordenadas exactas o estamos en procesos de automatización.
# Seleccionar el primer tiempo (posición 0)
ds.isel(time=0)
Seleccionar temperatura para la primera posición de latitud y segunda longitud a lo largo del tiempo
ds.Temperature.isel(lat=0, lon=1)
🧠 .isel()
usa números de posición; .sel()
usa etiquetas de coordenadas.
3.4 Seleccionar rangos con slice()
🪄¶
Podemos seleccionar rangos utilizando slice()
, lo que facilita el trabajo con subconjuntos:
Por ejemplo seleccionemos el subconjunto de datos entre dos fechas
ds.sel(time=slice("2018-01-01", "2018-01-03"))
O subconjunto de latitudes
ds.sel(lat=slice(30, 50))
Esto es especialmente útil en análisis temporales o espaciales que requieren ventanas móviles.
4. Operaciones estadísticas y gráficas 📊¶
Una de las grandes ventajas de Xarray es que permite aplicar operaciones estadísticas y crear visualizaciones de forma muy similar a Pandas, pero extendidas a múltiples dimensiones.
4.1 Estadísticas sobre dimensiones 📐¶
Podemos calcular estadísticas como la media, desviación estándar, máximo o mínimo a lo largo de una o varias dimensiones.
# Media de temperatura a lo largo del tiempo
ds.Temperature.mean(dim="time")
# Mínimo de presión sobre latitudes
ds.Pressure.min(dim="lat")
# Desviación estándar de humedad relativa
ds.RelativeHumidity.std(dim="time")
✅ Estas funciones son muy útiles para obtener resúmenes climatológicos o patrones promedios.
4.2 Interpolación de datos 🌐
Cuando necesitas obtener valores en coordenadas que no existen exactamente en tus datos, puedes usar .interp()
para interpolar:
# Interpolación espacial
valor_interp = ds.Temperature.interp(lat=33.5, lon=-110)
valor_interp
📌 Puedes especificar el método de interpolación (como linear, nearest) y ajustar la tolerancia.
4.3 Visualizaciones rápidas con .plot()
🖼️¶
Xarray incluye integración con Matplotlib para hacer gráficos rápidos desde cualquier DataArray
:
Generemos una serie temporal de temperatura en una ubicación determinada
serie = ds.Temperature.sel(lat=40, lon=-100, method="nearest")
serie.plot()

O un mapa de temperatura para t=0
mapa = ds.Temperature.isel(time=0)
mapa.plot()

O un Mapa de temperatura promedio
prom_mapa = ds.Temperature.mean("time")
prom_mapa.plot()

🔍 Estas funciones detectan automáticamente si el resultado es 1D o 2D y generan una línea o un mapa respectivamente.
4.4 Aplicar máscaras y condiciones 🎭¶
Puedes aplicar filtros condicionales a los datos usando .where()
, muy útil para enmascarar regiones o aplicar umbrales:
# Mostrar datos para latitudes menores a 50 grados
ds.Temperature.where(ds.lat < 50).isel(time=0).plot()

# Filtrar valores de presión mayores a cierto umbral
ds.Pressure.where(ds.Pressure > 1000).isel(time=1).plot()

🧪 .where()
mantiene la forma del arreglo pero oculta los datos que no cumplen la condición.
5. 📂 Lectura de archivos netCDF con Xarray¶
Esta sección te introduciría a cómo cargar datos reales desde archivos científicos en formato netCDF, que es uno de los más comunes en ciencias de la atmósfera, océano y clima.
Los archivos NetCDF (Network Common Data Form) son ampliamente utilizados para almacenar datos multidimensionales del clima, el océano y la atmósfera. Xarray proporciona una forma sencilla y poderosa para leer y explorar este tipo de archivos.
5.1 Leer un archivo netCDF¶
Xarray facilita la lectura de estos archivos con la función xr.open_dataset()
.
En este ejemplo vamos a usar un archivo real llamado sst.mnmean.nc
, que contiene datos mensuales de la temperatura superficial del mar (SST) a nivel global durante varias décadas. Este tipo de dataset es comúnmente utilizado para analizar fenómenos como El Niño, anomalías de temperatura, o climatologías oceánicas.
path_ncfile = "../data/sst.mnmean.nc"
ds = xr.open_dataset(path_ncfile)
ds
5.2 Explorar estructura del archivo 🔎¶
Una vez abierto el Dataset, puedes inspeccionar las variables y dimensiones disponibles:
- Variables contenidas (por ejemplo,
sst
para temperatura superficial del mar) - Dimensiones como
time
,lat
, ylon
- Coordenadas disponibles y sus unidades
- Atributos globales (fuente, descripción, institución, etc.)
# Visualizar las dimensiones y coordenadas
print(ds.dims)
print(ds.coords)
FrozenMappingWarningOnValuesAccess({'lat': 89, 'lon': 180, 'time': 2037})
Coordinates:
* lat (lat) float32 356B 88.0 86.0 84.0 82.0 ... -82.0 -84.0 -86.0 -88.0
* lon (lon) float32 720B 0.0 2.0 4.0 6.0 8.0 ... 352.0 354.0 356.0 358.0
* time (time) datetime64[ns] 16kB 1854-01-01 1854-02-01 ... 2023-09-01
También puedes ver los atributos generales del archivo:
ds.attrs
{'climatology': 'Climatology is based on 1971-2000 SST, Xue, Y., T. M. Smith, and R. W. Reynolds, 2003: Interdecadal changes of 30-yr SST normals during 1871.2000. Journal of Climate, 16, 1601-1612.',
'description': 'In situ data: ICOADS2.5 before 2007 and NCEP in situ data from 2008 to present. Ice data: HadISST ice before 2010 and NCEP ice after 2010.',
'keywords_vocabulary': 'NASA Global Change Master Directory (GCMD) Science Keywords',
'keywords': 'Earth Science > Oceans > Ocean Temperature > Sea Surface Temperature >',
'instrument': 'Conventional thermometers',
'source_comment': 'SSTs were observed by conventional thermometers in Buckets (insulated or un-insulated canvas and wooded buckets) or Engine Room Intaker',
'geospatial_lon_min': np.float32(-1.0),
'geospatial_lon_max': np.float32(359.0),
'geospatial_laty_max': np.float32(89.0),
'geospatial_laty_min': np.float32(-89.0),
'geospatial_lat_max': np.float32(89.0),
'geospatial_lat_min': np.float32(-89.0),
'geospatial_lat_units': 'degrees_north',
'geospatial_lon_units': 'degrees_east',
'cdm_data_type': 'Grid',
'project': 'NOAA Extended Reconstructed Sea Surface Temperature (ERSST)',
'original_publisher_url': 'http://www.ncdc.noaa.gov',
'References': 'https://www.ncdc.noaa.gov/data-access/marineocean-data/extended-reconstructed-sea-surface-temperature-ersst-v5 at NCEI and http://www.esrl.noaa.gov/psd/data/gridded/data.noaa.ersst.v5.html',
'source': 'In situ data: ICOADS R3.0 before 2015, NCEP in situ GTS from 2016 to present, and Argo SST from 1999 to present. Ice data: HadISST2 ice before 2015, and NCEP ice after 2015',
'title': 'NOAA ERSSTv5 (in situ only)',
'history': "created 07/2017 by PSD data using NCEI's ERSST V5 NetCDF values",
'institution': 'This version written at NOAA/ESRL PSD: obtained from NOAA/NESDIS/National Centers for Environmental Information and time aggregated. Original Full Source: NOAA/NESDIS/NCEI/CCOG',
'citation': 'Huang et al, 2017: Extended Reconstructed Sea Surface Temperatures Version 5 (ERSSTv5): Upgrades, Validations, and Intercomparisons. Journal of Climate, https://doi.org/10.1175/JCLI-D-16-0836.1',
'platform': 'Ship and Buoy SSTs from ICOADS R3.0 and NCEP GTS',
'standard_name_vocabulary': 'CF Standard Name Table (v40, 25 January 2017)',
'processing_level': 'NOAA Level 4',
'Conventions': 'CF-1.6, ACDD-1.3',
'metadata_link': ':metadata_link = https://doi.org/10.7289/V5T72FNM (original format)',
'creator_name': 'Boyin Huang (original)',
'date_created': '2017-06-30T12:18:00Z (original)',
'product_version': 'Version 5',
'creator_url_original': 'https://www.ncei.noaa.gov',
'license': 'No constraints on data access or use',
'comment': 'SSTs were observed by conventional thermometers in Buckets (insulated or un-insulated canvas and wooded buckets), Engine Room Intakers, or floats and drifters',
'summary': 'ERSST.v5 is developed based on v4 after revisions of 8 parameters using updated data sets and advanced knowledge of ERSST analysis',
'dataset_title': 'NOAA Extended Reconstructed SST V5',
'data_modified': '2023-10-03'}
5.3 Acceder a variables específicas 🧬¶
Cada variable contenida en el archivo se puede acceder directamente como un DataArray
.
# Seleccionar la variable de temperatura superficial del mar (sst)
sst = ds['sst']
sst
Esto mostrará la forma, dimensiones y atributos asociados a la variable.
5.4 Visualización básica 🌍¶
Vamos a generar un mapa de la temperatura para el primer valor temporal del archivo.
# Graficar la primera capa temporal
sst.isel(time=0).plot(cmap="coolwarm")

🧭 Esto te muestra un mapa global de temperatura superficial del mar para el primer mes disponible en el conjunto de datos.
✅ Puedes cambiar el índice o usar .sel(time=...)
para seleccionar fechas específicas si el tiempo está en formato calendario.
5.5 Operaciones comunes ⚙️¶
Ya que tenemos un DataArray
, podemos aplicar operaciones estadísticas o espaciales directamente:
# Temperatura promedio global (promedio espacial)
sst.mean(dim=["lon", "lat"]).plot()

5.6 Aplicar máscaras o filtros 🎭¶
Filtrar solo los valores en el hemisferio sur o para latitudes específicas:
sst.where(sst.lat < 0).isel(time=0).plot(cmap="viridis")

5.7 Guardar resultados en nuevo archivo 💾¶
Podemos guardar los datos procesados a un nuevo archivo Zarr:
sst_mean = sst.mean(dim="time")
sst_mean.to_zarr("sst_media.zarr")
<xarray.backends.zarr.ZarrStore at 0x7fceaae91a80>
! ls sst_media.zarr
lat lon sst zarr.json
🎉 ¡Con esto completamos nuestra introducción al uso de Xarray con datos reales en formato netCDF!
✅ Conclusiones¶
En este cuadernillo aprendiste los fundamentos del manejo de datos multidimensionales con Xarray, una herramienta esencial en la ciencia del clima, meteorología y disciplinas relacionadas con datos ambientales.
🔑 Lo más destacado:
- Comprendiste la diferencia entre
DataArray
yDataset
, dos estructuras clave para manejar datos con múltiples dimensiones y coordenadas. - Aprendiste a etiquetar tus datos con dimensiones y coordenadas que hacen tu análisis más claro y reproducible.
- Aplicaste operaciones estadísticas como
mean()
,std()
osum()
a lo largo de diferentes dimensiones. - Usaste
.sel()
y.isel()
para extraer datos fácilmente con etiquetas o índices. - Generaste visualizaciones rápidas usando
.plot()
para explorar tendencias temporales y mapas espaciales. - Accediste y exploraste datos reales en formato
netCDF
, el estándar para datos climáticos y atmosféricos.
📦 Con este conocimiento ya puedes comenzar a trabajar con grandes volúmenes de datos científicos como modelos climáticos, observaciones satelitales o reanálisis atmosféricos.
📚 Recursos recomendados¶
- Documentación oficial de Xarray
- Pythia Foundations: Introducción a Xarray
- Earth & Environmental Data Science
🎓 ¡Felicitaciones! Estás listo para abordar análisis más complejos con datos multidimensionales usando Xarray.
Fuentes y Referencias¶
- Rose, B. E. J., Kent, J., Tyle, K., Clyne, J., Banihirwe, A., Camron, D., May, R., Grover, M., Ford, R. R., Paul, K., Morley, J., Eroglu, O., Kailyn, L., & Zacharias, A. (2023). Pythia Foundations (Version v2023.05.01) Rose et al. (2023)
- Rose, B., Kent, J., Tyle, K., Clyne, Banihirwe, A., Camron, D., Ford, R., Morley, J., Grover, M., Eroglu, O., Paul, K., May, R., Lkailynncar, Irving, D., Uieda, L., Ojaybee, Blain, P., & Moon, Z. (2023). ProjectPythia/pythia-foundations: v2023.05.01. Zenodo. 10.5281/ZENODO.7884572