Skip to article frontmatterSkip to article content

Introducción a Xarray

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 y Dataset
  • 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

ConceptoImportanciaNotas
Introducción a NumPyNecesarioArreglos multidimensionales
Fundamentos de PandasNecesarioIndexado y manipulación tabular
Uso de JupyterLabÚtilNavegació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
Loading...

⚠️ 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
Loading...

Creamos un objeto con datos y dimensiones que gráficamente se podría representar de la siguiente manera:

Datarray

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
Loading...

Con esto obtenemos un objeto con visualización enriquecida: las dimensiones están etiquetadas y cada punto tiene una referencia espacial y temporal clara.

Datarray_Coords

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 DataArrays, 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 DataArrays 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 DataArrays, 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
Loading...

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

Dataset

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
Loading...

O Notación por clave de diccionario (más general y flexible)

ds["Pressure"]
Loading...

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")
Loading...

O seleccionar una variable y una ubicación específica

ds.Temperature.sel(time="2018-01-01", lat=25, lon=-120)
Loading...

✅ 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)
Loading...

Seleccionar temperatura para la primera posición de latitud y segunda longitud a lo largo del tiempo

ds.Temperature.isel(lat=0, lon=1)
Loading...

🧠 .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"))
Loading...

O subconjunto de latitudes

ds.sel(lat=slice(30, 50))
Loading...

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")
Loading...
# Mínimo de presión sobre latitudes
ds.Pressure.min(dim="lat")
Loading...
# Desviación estándar de humedad relativa
ds.RelativeHumidity.std(dim="time")
Loading...

✅ 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
Loading...

📌 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()
<Figure size 640x480 with 1 Axes>

O un mapa de temperatura para t=0

mapa = ds.Temperature.isel(time=0)
mapa.plot()
<Figure size 640x480 with 2 Axes>

O un Mapa de temperatura promedio

prom_mapa = ds.Temperature.mean("time")
prom_mapa.plot()
<Figure size 640x480 with 2 Axes>

🔍 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()
<Figure size 640x480 with 2 Axes>
# Filtrar valores de presión mayores a cierto umbral
ds.Pressure.where(ds.Pressure > 1000).isel(time=1).plot()
<Figure size 640x480 with 2 Axes>

🧪 .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
Loading...

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, y lon
  • 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
Loading...

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")
<Figure size 640x480 with 2 Axes>

🧭 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()
<Figure size 640x480 with 1 Axes>

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")
<Figure size 640x480 with 2 Axes>

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 y Dataset, 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() o sum() 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


🎓 ¡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)
References
  1. 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