Qries eduard-martinez.github.io

Qries @emartigo

Qries eduard-martinez

Qries efmartinez@icesi.edu.co

[1.] Motivación

1.1. Night lights and Covid-19

El análisis de imágenes de luminosidad nocturna se ha consolidado como una herramienta valiosa para aproximar la actividad económica, especialmente durante la pandemia de COVID-19. Diversos estudios han empleado esta fuente de datos para evaluar los efectos económicos de las medidas de confinamiento, así como los patrones de recuperación en diferentes contextos geográficos.

👉 Puede acceder al documento aquí: COVID19 y actividad económica: demanda de energía y luminosidad ante la emergencia

Adicionalmente, se ha documentado el uso combinado de datos satelitales de luminosidad con variables de consumo energético para estimar el impacto económico de la pandemia. Un caso representativo es el estudio aplicado a India, que integra ambos indicadores para observar dinámicas económicas diarias durante el confinamiento:

👉 Puede acceder al documento aquí: Examining the economic impact of COVID-19 in India through daily electricity consumption and nighttime light intensity

1.2. Measuring the size and growth of cities using nighttime light

La intensidad lumínica registrada por sensores satelitales también ha sido utilizada como proxy para estimar el tamaño y la expansión de las áreas urbanas. Esta metodología ha permitido identificar patrones de crecimiento urbano en ausencia de datos administrativos consistentes.

👉 El estudio puede consultarse en el siguiente enlace: Measuring the size and growth of cities using nighttime light

1.3. Housing Vacancy Rate (VHR) y Luces Nocturnas

La información de luminosidad nocturna también ha sido empleada para estimar la tasa de vacancia habitacional (VHR), integrando imágenes satelitales con datos geoespaciales abiertos como OpenStreetMap. Esta aproximación permite inferir dinámicas del mercado inmobiliario y ocupación urbana con mayor granularidad espacial.

👉 El artículo completo está disponible en: An estimation of housing vacancy rate using NPP-VIIRS night-time light data and OpenStreetMap data

1.4. Causes Of Sprawl: A Portrait From Space

El uso de datos satelitales también ha permitido documentar los determinantes de la expansión urbana (urban sprawl). En el caso de Estados Unidos, un estudio seminal analiza cómo factores institucionales y de planificación territorial se reflejan en la distribución de tierras urbanas, utilizando imágenes nocturnas para representar el crecimiento espacial de ciudades como Miami, Florida.

Tomado de: Causes Of Sprawl: A Portrait From Space
Tomado de: Causes Of Sprawl: A Portrait From Space

👉 Puede acceder al documento aquí: Causes Of Sprawl: A Portrait From Space

1.5. Aplicaciones en el sector agrícola e industrial

La integración de imágenes satelitales con algoritmos de inteligencia artificial ha abierto nuevas posibilidades para el monitoreo agrícola y la gestión de riesgos financieros. Bancos y aseguradoras utilizan estas herramientas para evaluar la salud de los cultivos, anticipar pérdidas y definir condiciones crediticias más precisas.

👉 Más información: EOS Crop Monitoring - El País – Revolución tecnológica del campo

[2.] Introducción a Datos Raster

2.1. ¿Qué es un raster?

Un raster es una estructura de datos espaciales que representa el territorio como una matriz regular de celdas (píxeles), cada una asociada a un valor numérico. Este valor puede corresponder a una variable continua (como temperatura, altitud o intensidad lumínica) o categórica (como tipo de uso del suelo). Los datos raster son particularmente útiles para representar fenómenos que varían de manera continua en el espacio.

2.2. Resolución

La resolución espacial de un raster se refiere al tamaño del área terrestre que representa cada píxel. A mayor resolución (es decir, menor tamaño del píxel), mayor detalle espacial contiene la imagen. Este concepto es clave para interpretar adecuadamente los análisis, ya que la escala de los fenómenos observados debe estar alineada con la resolución del dato satelital utilizado.

2.3. Bandas de un raster

Muchos productos raster, como las imágenes satelitales, están compuestos por múltiples bandas espectrales, que capturan información en distintas longitudes de onda (por ejemplo, rojo, verde, azul o infrarrojo cercano). Estas bandas pueden combinarse para generar visualizaciones (como imágenes RGB) o para calcular índices espectrales, como el NDVI en agricultura.

2.4. Formatos comunes de datos raster

Los datos raster pueden almacenarse en distintos formatos, dependiendo de su origen, nivel de compresión, metadatos asociados y compatibilidad con software geoespacial. Algunos de los formatos más utilizados en aplicaciones con R y SIG (Sistemas de Información Geográfica) son:

  • GeoTIFF (.tif / .tiff): Es el formato más común y ampliamente soportado. Permite almacenar información georreferenciada junto con múltiples bandas y metadatos espaciales. Es ideal para análisis con terra en R.

  • NetCDF (.nc): Utilizado frecuentemente para datos climáticos o multitemporales. Permite almacenar series de tiempo, variables múltiples y dimensiones espaciales complejas.

  • IMG (.img): Formato utilizado por el software ERDAS Imagine, común en sensores remotos. Puede contener múltiples bandas y datos categóricos o continuos.

  • HDF (.hdf / .h5): Formato jerárquico utilizado por agencias como la NASA para distribuir productos satelitales complejos (e.g., MODIS). Requiere herramientas específicas para su apertura y conversión.

  • ASCII Raster (.asc): Representa los valores de las celdas como texto plano, acompañado de una cabecera con metadatos espaciales. Útil para interoperabilidad y edición manual, aunque menos eficiente en términos de almacenamiento.

La elección del formato depende del tipo de análisis, el volumen de datos y el software utilizado. En general, GeoTIFF es el formato recomendado para la mayoría de tareas de análisis raster en R.

2.5. Fuentes:

2.5.1. Night lights

Una de las fuentes más utilizadas para el análisis de actividad económica y urbana es el producto satelital VIIRS (Visible Infrared Imaging Radiometer Suite), disponible desde el año 2012. Este sensor captura la intensidad de la luz visible durante la noche, lo que permite generar indicadores geoespaciales de actividad humana con alta resolución temporal y espacial.

Los datos de VIIRS están disponibles en diferentes frecuencias de agregación:

👉 Sitio principal del proyecto VIIRS Nighttime Lights: https://eogdata.mines.edu/products/vnl/

👉 Datos mensuales (VNL V.1): https://eogdata.mines.edu/nighttime_light/monthly/v10/

👉 Datos diarios (NOAA - sueltos por mosaico): https://ngdc.noaa.gov/eog/viirs/download_ut_mos.html

Estos archivos suelen estar en formato raster (GeoTIFF) y permiten realizar análisis comparativos en el tiempo, como la detección de apagones, patrones de expansión urbana o impactos económicos de eventos disruptivos.

También se encuentran disponibles productos históricos de luminosidad nocturna provenientes del sensor DMSP-OLS, que cubren el periodo 1992–2013, útiles para análisis de largo plazo: Datos anuales (DMSP-OLS, 1992–2013)

Para facilitar la comparación temporal, se ha desarrollado un producto que armoniza las series de DMSP-OLS y VIIRS, permitiendo construir análisis consistentes desde 1992 hasta 2018: Datos armonizados y publicación científica

2.5.2. Imágenes satelitales de alta resolución – Planet Labs

Planet Labs ofrece acceso gratuito a imágenes satelitales de alta resolución para investigadores y docentes a través de su programa educativo. Esta plataforma proporciona datos casi diarios de observación de la Tierra, útiles para estudios en agricultura, medio ambiente, desarrollo urbano y cambio climático. Los productos incluyen imágenes RGB, infrarrojas y multiespectrales con resoluciones de hasta 3 metros.

Investigadores afiliados a instituciones académicas pueden solicitar acceso a través del siguiente enlace: 👉 Programa educativo y de investigación de Planet Labs

2.5.3. Datos climáticos y ambientales – NASA GES DISC

El portal GES DISC (Goddard Earth Sciences Data and Information Services Center) de la NASA proporciona acceso a una amplia variedad de datos climáticos y ambientales derivados de sensores satelitales. Entre los productos disponibles se encuentran variables como precipitación, temperatura, calidad del aire, concentración de aerosoles, velocidad del viento y humedad del suelo, con cobertura global y distintas resoluciones temporales (diaria, mensual, estacional).

Estos datos son especialmente útiles para investigaciones en cambio climático, agricultura, salud pública, y gestión de desastres.

👉 Acceso al portal: https://disc.gsfc.nasa.gov.

[3.] Ecosistema de Datos Raster en R

El análisis de datos raster en R se apoya en un conjunto de paquetes que permiten la lectura, visualización, transformación y análisis de este tipo de estructuras espaciales. A continuación, se presenta un resumen del ecosistema actual más relevante para el trabajo con datos raster:

Paquetes base y principales:

terra: Paquete principal para el manejo de datos raster y vectoriales. Es el sucesor moderno de raster, con mejor rendimiento y compatibilidad con estándares geoespaciales actuales.

raster: Aún ampliamente usado en muchos tutoriales y scripts antiguos, aunque ya en desuso activo. Su funcionalidad está siendo reemplazada por terra.

stars: Alternativa a terra, con estructura orientada a arrays multidimensionales. Útil para análisis con cubos de datos espaciales-temporales.

Lectura y escritura de formatos raster:

rgdal (obsoleto desde 2023): Fue el paquete de referencia para la lectura y escritura de datos espaciales con soporte de GDAL. Su funcionalidad ha sido absorbida por terra y sf.

sf: Aunque está orientado a datos vectoriales, puede ser complementario para análisis que integren capas vector y raster.

Visualización:

tmap: Permite la creación de mapas temáticos estáticos y dinámicos. Compatible con objetos SpatRaster de terra.

mapview, leaflet: Herramientas para visualización interactiva de mapas. Especialmente útiles en aplicaciones exploratorias o web.

Acceso a datos raster externos:

geodata: Descarga datos raster (e.g., altitud, clima, uso del suelo) desde repositorios globales como WorldClim, SRTM, MODIS, etc.

MODIStsp: Acceso automatizado a productos MODIS, con preprocesamiento.

nasapower, rnoaa: Interfaces para acceder a datos climáticos y meteorológicos.

[4.] Aplicación en R

Esta sección muestra cómo recortar un raster de intensidad lumínica nocturna para la ciudad de Cali y preparar los datos vectoriales de manzanas censales para análisis espacial.

4.1. Acerca de la replicación

👉 Para replicar las secciones de esta clase, debe descargar el siguiente script de R.

4.2 Configuración inicial

Instalar/llamar las librerías de la clase

Este bloque utiliza el paquete pacman, que permite instalar (si es necesario) y cargar múltiples librerías en una sola línea mediante la función p_load(). Las librerías incluidas cumplen funciones clave en el análisis espacial:

## Instalar/llamar las librerías de la clase
require(pacman) 
p_load(tidyverse,
       sf,
       osmdata,
       terra,
       mapview)
  • tidyverse: Colección de paquetes para manipulación, transformación y visualización de datos (como dplyr, ggplot2, readr).

  • sf: Manejo de datos espaciales vectoriales bajo el estándar Simple Features.

  • osmdata: Acceso a datos abiertos de OpenStreetMap.

  • terra: Paquetes para trabajar con datos raster; terra es el sucesor de raster.

  • mapview: Visualización interactiva de objetos espaciales en mapas dinámicos.

4.3 Leer un archivo raster

A continuación se muestra cómo importar un archivo raster directamente desde una URL utilizando el paquete terra. La función rast() crea un objeto de clase SpatRaster, que representa una o varias capas raster. Esta función permite leer archivos locales o remotos (por ejemplo, alojados en GitHub o servidores de datos satelitales).

nl_r <- rast("https://eduard-martinez.github.io/blog/intro_raster_in_r/data/night_light_202301.tif")

Puedes inspeccionar el objeto, imprimiendolo sobre la consola:

dimensions: número de filas, columnas y capas (bandas).

resolution: tamaño de cada píxel en grados (latitud y longitud).

extent: cobertura espacial (coordenadas mínimas y máximas).

coord. ref.: sistema de referencia espacial (en este caso, WGS84).

min/max value: valores mínimo y máximo de la capa raster (aquí, intensidad lumínica nocturna).

nl_r          # Información general
## class       : SpatRaster 
## dimensions  : 2990, 2919, 1  (nrow, ncol, nlyr)
## resolution  : 0.004166667, 0.004166667  (x, y)
## extent      : -79.01042, -66.84792, 0.002082733, 12.46042  (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326) 
## source      : night_light_202301.tif 
## name        : night_light_202301 
## min value   :              -0.64 
## max value   :            2208.49

Al ejecutar plot(nl_r) en un objeto SpatRaster, se obtiene una representación rápida del contenido del raster.

Esta visualización es útil como primer paso exploratorio, aunque limitada en personalización. Para mapas más elaborados se recomienda utilizar tmap, ggplot2 (vía as.data.frame()) o mapview para vistas interactivas.

plot(nl_r)    # Visualización

4.4. Luminosidad por manzanas en Cali

Primero, se obtienen los límites administrativos de la ciudad de Cali directamente desde OpenStreetMap utilizando la función getbb() del paquete osmdata. Esta función permite extraer geometrías espaciales abiertas con base en un nombre de lugar, especificando el tipo de límite requerido. En este caso, se solicita el límite de tipo “administrative” en formato sf (Simple Features).

Como resultado, se obtiene un objeto que puede contener múltiples polígonos (por ejemplo, límites departamentales y municipales). Se selecciona la segunda geometría (cali[2, ]), que típicamente corresponde al municipio de Cali como unidad administrativa. Finalmente, se visualiza la geometría seleccionada en un mapa interactivo con mapview() para verificar su correcta descarga y forma geográfica.

# Obtener los límites administrativos de Cali desde OpenStreetMap
cali <- getbb(place_name = "Cali, Colombia", 
              featuretype = "boundary:administrative", 
              format_out = "sf_polygon")

# Seleccionar la segunda geometría
cali <- cali[2, ]

# Visualizar la geometría de Cali sobre un mapa interactivo
mapview(cali)

Ahora se realiza el recorte espacial del raster de luminosidad nocturna (nl_r) utilizando el polígono de la ciudad de Cali obtenido previamente. Para ello se emplea la función crop() del paquete terra, que recorta el raster en función de los límites del polígono proporcionado.

El argumento mask = TRUE asegura que los valores fuera del límite de Cali sean descartados, es decir, se enmascaran y se asigna NA a las celdas externas. Esto permite conservar exclusivamente los píxeles de interés dentro del área urbana o administrativa de Cali. Finalmente, el resultado (cali_r) se visualiza con mapview() como un mapa interactivo:

# Recortar el raster original (nl_r) usando el polígono de Cali
cali_r <- crop(nl_r, cali, mask = TRUE)

# Visualizar el raster recortado de Cali
mapview(cali_r)

Ahora se guarda el raster recortado de luminosidad nocturna (cali_r) como un archivo GeoTIFF en el disco local. Se utiliza la función writeRaster() del paquete terra, que permite exportar objetos SpatRaster en formatos estándar geoespaciales. El argumento overwrite = TRUE asegura que, si el archivo ya existe, se sobrescriba sin generar errores.

# Guardar el raster recortado como archivo GeoTIFF en el disco
writeRaster(cali_r, "cali_recorte.tif", overwrite = TRUE)

Para explorar visualmente el contenido del raster recortado (cali_r), se puede convertir en una tabla (data.frame) utilizando la función as.data.frame() del paquete terra. Al especificar el argumento xy = TRUE, se incluyen en el resultado las coordenadas espaciales (x, y) correspondientes al centro de cada celda del raster. De esta forma, también se puede convertir el resultado en un objeto sf con los centroides del raster.

# Convertir el raster recortado en un data.frame, incluyendo las coordenadas (x, y)
df <- as.data.frame(cali_r, xy = TRUE)

En este paso se carga un archivo en formato .rds que contiene los polígonos correspondientes a las manzanas censales de la ciudad de Cali. Estos datos provienen del Marco Geoestadístico Nacional (MGN) publicado por el DANE (Departamento Administrativo Nacional de Estadística de Colombia), que define las unidades espaciales utilizadas oficialmente para el levantamiento y agregación de información estadística.

Para su lectura se utiliza la función read_rds() y posteriormente se convierte el objeto resultante a formato espacial sf mediante `st_as_sf()```, lo que permite operar sobre estas geometrías con funciones del ecosistema espacial de R.

# Leer archivo RDS que contiene los polígonos de manzanas censales de Cali
mnz <- read_rds("https://eduard-martinez.github.io/blog/intro_raster_in_r/data/manzanas_cali.rds") %>% 
  st_as_sf()

# Visualizar las primeras filas del objeto de manzanas
head(mnz)
## Simple feature collection with 6 features and 2 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -76.57632 ymin: 3.453265 xmax: -76.57056 ymax: 3.455849
## Geodetic CRS:  MAGNA-SIRGAS
##                 cod_dane personas                       geometry
## 1 7600110000000001010101      246 MULTIPOLYGON (((-76.5736 3....
## 2 7600110000000001010102       90 MULTIPOLYGON (((-76.57208 3...
## 3 7600110000000001010104        0 MULTIPOLYGON (((-76.57437 3...
## 4 7600110000000001010111      189 MULTIPOLYGON (((-76.5747 3....
## 5 7600110000000001010112      257 MULTIPOLYGON (((-76.57574 3...
## 6 7600110000000001010113      230 MULTIPOLYGON (((-76.57596 3...

Una vez cargadas las manzanas censales de Cali, se procede a vincular a cada polígono su correspondiente valor de luminosidad nocturna.

Primero, el raster recortado (cali_r) se convierte en una colección de polígonos, donde cada celda del raster se representa como un polígono individual con su valor asociado. Esta operación se realiza mediante as.polygons() del paquete terra, seguido de la conversión a objeto sf con st_as_sf().

## raster to sf
cali_sf <- as.polygons(cali_r) %>% st_as_sf()
st_crs(cali_sf) == st_crs(mnz)
## [1] FALSE

Dado que ambos conjuntos deben compartir el mismo sistema de referencia espacial, se transforma cali_sf al CRS de las manzanas con st_transform().

## transformar el CRS
cali_sf <- st_transform(cali_sf , st_crs(mnz))

Finalmente, se realiza una unión espacial (st_join()) entre las manzanas (mnz) y el raster convertido a polígonos (cali_sf). Esto permite asignar a cada manzana el valor de luminosidad del polígono con el que intersecta, generando un nuevo objeto (mnz_nl) que contiene tanto las geometrías censales como los valores de intensidad lumínica.

## unir los 
mnz_nl <- st_join(x=mnz , y=cali_sf)

# Visualizar resultado
mapview(mnz_nl, zcol = "night_light_202301")

Una vez integrados los valores de luminosidad nocturna a cada manzana censal, se transforma el objeto espacial (sf) en un data.frame convencional con as.data.frame(), excluyendo la geometría (geometry = NULL) para facilitar el análisis estadístico.

# Convertir el objeto sf en un data.frame plano
df_nl <- as.data.frame(mnz_nl, geometry = NULL)
head(df_nl)
##                   cod_dane personas night_light_202301
## 1   7600110000000001010101      246                 18
## 1.1 7600110000000001010101      246                 22
## 2   7600110000000001010102       90                 22
## 3   7600110000000001010104        0                 18
## 4   7600110000000001010111      189                 18
## 5   7600110000000001010112      257                 18
##                           geometry
## 1   MULTIPOLYGON (((-76.5736 3....
## 1.1 MULTIPOLYGON (((-76.5736 3....
## 2   MULTIPOLYGON (((-76.57208 3...
## 3   MULTIPOLYGON (((-76.57437 3...
## 4   MULTIPOLYGON (((-76.5747 3....
## 5   MULTIPOLYGON (((-76.57574 3...

Puede chuequear la relación entre el número de personas por manzana y la intensidad de la luz nocturna satelital utilizando un gráfico de dispersión con ambas variables transformadas mediante logaritmo natural. Esta transformación permite reducir la asimetría de la distribución y capturar mejor las relaciones no lineales entre magnitudes de orden diferente.

# Graficar relación entre población y luminosidad
ggplot(data = df_nl, 
       aes(x = log(personas), y = log(night_light_202301))) +
geom_point() +
geom_smooth(method="lm", se =T , color = "blue") +
theme_bw()
## Warning: Removed 3460 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 707 rows containing missing values or values outside the scale range
## (`geom_point()`).

O puede estimar un modelo lineal entre logaritmo de la luminosidad y logaritmo de la población:

lm(asinh(night_light_202301) ~ asinh(personas), data = df_nl)
## 
## Call:
## lm(formula = asinh(night_light_202301) ~ asinh(personas), data = df_nl)
## 
## Coefficients:
##     (Intercept)  asinh(personas)  
##        4.633519         0.009274

Referencias

  • Introduction to Geospatial Raster and Vector Data with R. [Ver aquí]