Skip to contents

Introducción

Las islas de calor urbano (UHI) son un problema ambiental crítico en las ciudades, donde las áreas urbanas experimentan temperaturas más altas que sus alrededores rurales. Este estudio de caso demuestra cómo analizar los UHI utilizando datos de temperatura del aire (Tair) de crowdsourcing de Citizen Weather Stations (CWS) y el paquete LCZ4r en R. Nos centramos en los datos horarios de Tair de mayo de 2023, recopilados por Netatmo CWS en Berlín, Alemania, y disponibles a través de Paquete CrowdQCplus en R.

# Instalar y cargar los paquetes necesarios
if (!require("pacman")) install.packages("pacman")
install.packages("sf", type = "binary")
pacman::p_load(remotes, dplyr, tmap, ggplot2, devtools, data.table)

library(dplyr)   # Para la manipulación de datos
library(sf)      # Para la manipulación de datos vectoriales
library(tmap)    # Para visualización interactiva de mapas
library(ggplot2) # Para la visualización de datos
library(data.table)

# Instale CrowdQCplus para el control de calidad de los datos de CWS
if (!require("CrowdQCplus")) {
  remotes::install_github("dafenner/CrowdQCplus")
}
library(CrowdQCplus)

¿Por qué utilizar datos de crowdsourcing?

Las estaciones meteorológicas colaborativas ofrecen una cobertura espacial sin precedentes de datos de temperatura urbana: - Alta densidad: Cientos o miles de estaciones en toda la ciudad - Datos en tiempo real: mediciones horarias o subhorarias - Rentable: Utiliza la infraestructura ciudadana existente - Complementario: llena los vacíos en las redes oficiales de monitoreo

Sin embargo, un control de calidad cuidadoso es esencial para garantizar la confiabilidad de los datos.

Preparación del conjunto de datos

Cargar mapa LCZ para Berlín

# Obtenga el mapa LCZ de Berlín utilizando la plataforma generadora de LCZ
lcz_map <- LCZ4r::lcz_get_map_generator(ID = "8576bde60bfe774e335190f2e8fdd125dd9f4299")

# Visualice el mapa de LCZ
LCZ4r::lcz_plot_map(lcz_map)
Mapa LCZ de Berlín que muestra la distribución espacial de las Zonas Climáticas Locales

Mapa LCZ de Berlín que muestra la distribución espacial de las zonas climáticas locales. Este mapa sirve como marco espacial para analizar datos de temperatura de origen colaborativo.

Cargar y explorar datos de CWS

# Cargar datos de muestra de CWS para Berlín desde el paquete CrowdQCplus
data(cqcp_cws_data)

# Visualice la estructura del conjunto de datos
head(cqcp_cws_data)

# Estadísticas descriptivas
summary(cqcp_cws_data)

Visualice la distribución de estaciones CWS

# Convertir las estaciones CWS a un objeto sf para análisis espacial
shp_stations <- cqcp_cws_data %>%
  distinct(lon, lat, .keep_all = TRUE) %>%
  st_as_sf(coords = c("lon", "lat"), crs = 4326)

# Visualice las estaciones CWS en un mapa interactivo
tmap_mode("view")
qtm(shp_stations, dots.col = "blue", dots.size = 0.3,
    title = "Citizen Weather Stations in Berlin")

Control de calidad de los datos de CWS

Para garantizar la confiabilidad de los datos, aplicamos el método de control de calidad (QC) desarrollado por Fenner et al. (2021) utilizando el paquete CrowdQCplus. Este proceso filtra lecturas estadísticamente inverosímiles, mejorando la precisión de los datos.

Pasos del proceso de control de calidad:

  1. Relleno de datos: garantiza series temporales consistentes
  2. Validación de entrada: Comprueba la estructura de datos
  3. Control de calidad: Aplica filtros estadísticos para identificar valores atípicos
  4. Estadísticas de salida: Resume los resultados de control de calidad.
# Realizar el relleno de datos y las comprobaciones de entrada
data_crows <- cqcp_padding(cqcp_cws_data)
data_check <- cqcp_check_input(data_crows)

# Aplicar control de calidad
if (data_check) {
  data_qc <- cqcp_qcCWS(data_crows)  # QC process
}

# Ver resultados de control de calidad
head(data_qc)

# Mostrar estadísticas de salida de control de calidad
n_data_qc <- cqcp_output_statistics(data_qc)
print(n_data_qc)

Comprensión del resultado de control de calidad:

Después de aplicar el control de calidad, se generan varias columnas: - ta_int: Valores de temperatura que pasaron todos los pasos de control de calidad - qc_flag: indicadores de control de calidad que indican el estado de calidad de los datos - qa_flag: indicadores de control de calidad para validación adicional

Para la interpolación de la temperatura del aire, utilizamos el ta_int columna, que representa las estimaciones de temperatura más confiables.

Análisis del ciclo diurno por LCZ

Examinamos el ciclo diurno de la temperatura del aire para un día específico (1 de mayo de 2023) en diferentes LCZ para comprender cómo la forma urbana afecta los patrones de temperatura diarios.

# Analizar el ciclo de temperatura diurna en las distintas clases de LCZ
cws_ts <- lcz_ts(lcz_map, 
                 data_frame = data_qc,
                 var = "ta_int", 
                 station_id = "p_id",
                 time.freq = "hour",
                 extract.method = "two.step",
                 year = 2023, month = 5, day = 1,
                 by = "daylight")

# Mostrar el gráfico de la serie temporal
cws_ts
Diurnal temperature cycle across different LCZ classes in Berlin

Ciclo de temperatura diurno en diferentes clases de LCZ en Berlín el 1 de mayo de 2023. Observe cómo las áreas construidas compactas mantienen temperaturas más altas durante todo el día en comparación con las áreas abiertas y con vegetación.

Análisis de islas de calor urbanas

Serie temporal de intensidad UHI

Calculamos las intensidades UHI horarias para mayo de 2023 utilizando el método LCZ, que selecciona automáticamente las temperaturas urbanas y rurales según las clases LCZ.

# Calcular la intensidad del efecto isla de calor urbano para mayo de 2023
cws_uhi <- lcz_uhi_intensity(lcz_map, 
                             data_frame = data_qc,
                             var = "ta_int", 
                             station_id = "p_id",
                             time.freq = "hour",
                             extract.method = "two.step",
                             year = 2023, month = 5,
                             method = "LCZ")

# Visualización de la serie temporal de intensidad de UHI
cws_uhi
UHI intensity time series for Berlin in May 2023

Serie temporal de intensidad UHI para Berlín en mayo de 2023. La intensidad UHI más alta observada fue de 3,7 °C el 13 de mayo a las 16:00, lo que demuestra el importante efecto de calentamiento urbano.

Mapeo espacial UHI

Modelamos el UHI para el 13 de mayo de 2023, a las 16:00 (el momento de máxima intensidad), utilizando interpolación espacial basada en LCZ.

Mapa de temperatura

# Mapa de temperaturas del aire para el evento de isla de calor urbana de máxima intensidad
my_interp_map <- lcz_interp_map(
  lcz_map,
  data_frame = data_qc,
  var = "ta_int",
  station_id = "p_id",
  sp.res = 100,
  tp.res = "hour",
  year = 2023, month = 5, day = 13, hour = 16
)

# Personaliza la trama con títulos y etiquetas
lcz_plot_interp(
  my_interp_map,
  title = "Thermal Field - CWS Data",
  subtitle = "Berlin - May 13, 2023 at 16:00",
  caption = "Source: LCZ4r, 2024",
  fill = "Temperature [°C]"
)
Spatial distribution of air temperature during peak UHI event

Distribución espacial de la temperatura del aire durante el evento pico UHI el 13 de mayo de 2023 a las 16:00. El mapa revela distintos patrones térmicos con temperaturas más cálidas en áreas urbanas compactas y temperaturas más frías en zonas con vegetación y periféricas.

Mapa de anomalías térmicas

# Generar mapa de anomalías térmicas para el mismo evento
my_anomaly_map <- lcz_anomaly_map(
  lcz_map,
  data_frame = data_qc,
  var = "ta_int",
  station_id = "p_id",
  sp.res = 100,
  tp.res = "hour",
  year = 2023, month = 5, day = 13, hour = 16
)

# Personaliza el gráfico de anomalías
lcz_plot_interp(
  my_anomaly_map,
  title = "Thermal Anomaly Field - CWS Data",
  subtitle = "Berlin - May 13, 2023 at 16:00",
  caption = "Source: LCZ4r, 2024",
  fill = "Temperature Anomaly [°C]", 
  palette = "bl_yl_rd"
)
Mapa de anomalías térmicas que muestra las desviaciones respecto al promedio urbano

Mapa de anomalías térmicas que muestra las desviaciones de la media urbana. Las áreas rojas indican temperaturas por encima del promedio (puntos calientes), mientras que las áreas azules indican temperaturas por debajo del promedio (puntos fríos).

Evaluación de la precisión del mapa UHI

Evaluamos la precisión de la interpolación mediante la validación cruzada Leave-One-Out (LOOCV) y calculamos métricas como RMSE, MAE y sMAPE.

Validación cruzada

# Evaluar la precisión de la interpolación
df_eval <- lcz_interp_eval(
  lcz_map,
  data_frame = data_qc,
  var = "ta_int",
  station_id = "p_id",
  year = 2023, month = 5, day = 13, 
  LOOCV = TRUE,
  extract.method = "two.step",
  sp.res = 500,
  tp.res = "hour",
  vg.model = "Sph",
  LCZinterp = TRUE
)

Métricas de evaluación por clase LCZ

# Calcular las métricas de evaluación por clase LCZ
df_eval_metrics <- df_eval %>%
  group_by(lcz) %>%
  summarise(
    n_obs = n(),                                      # Number of observations
    rmse = sqrt(mean((observed - predicted)^2)),      # RMSE
    mae = mean(abs(observed - predicted)),            # MAE
    smape = mean(2 * abs(observed - predicted) / 
                (abs(observed) + abs(predicted)) * 100) # sMAPE
  ) %>%
  arrange(rmse)

# Mostrar las métricas
df_eval_metrics

Análisis de correlación

# Gráfico de correlación con ecuación de regresión y R²
p1 <- ggplot(df_eval, aes(x = observed, y = predicted)) +
  geom_point(alpha = 0.3, color = "#1D9E75", size = 1) +
  geom_smooth(method = "lm", color = "red", se = FALSE, linewidth = 1) +
  stat_density2d(aes(fill = after_stat(level)), geom = "polygon", alpha = 0.3) +
  scale_fill_viridis_c(option = "viridis", name = "Density") +
  stat_poly_eq(
    aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~")),
    formula = y ~ x,
    parse = TRUE,
    label.x.npc = "left",
    label.y.npc = "top",
    size = 4
  ) +
  labs(
    title = "Observed vs. Predicted Temperatures",
    x = "Observed Temperature [°C]",
    y = "Predicted Temperature [°C]"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
    axis.title = element_text(face = "bold")
  )

# Agregar histogramas marginales
p1_with_marginals <- ggMarginal(p1, 
                                 type = "histogram", 
                                 fill = "#1D9E75", 
                                 bins = 30,
                                 alpha = 0.6)

# Imprimir el gráfico
p1_with_marginals
Correlation between observed and predicted temperatures from CWS data

Correlación entre las temperaturas observadas y previstas a partir de datos de colaboración colectiva. El alto valor de R² indica un buen rendimiento del modelo, lo que demuestra la confiabilidad de los datos de crowdsourcing después del control de calidad.

Análisis residual por clase LCZ

# Gráfico de residuos por clase LCZ
p2 <- ggplot(df_eval, aes(x = observed, y = residual)) +
  geom_point(alpha = 0.3, color = "darkgreen", size = 1) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red", linewidth = 0.8) +
  geom_smooth(method = "loess", color = "blue", se = FALSE, linewidth = 1) +
  stat_density2d(aes(fill = after_stat(level)), geom = "polygon", alpha = 0.3) +
  scale_fill_viridis_c(option = "plasma", direction = -1, name = "Density") +
  facet_wrap(~ lcz, scales = "free", ncol = 3) +
  labs(
    title = "Residuos por clase LCZ",
    x = "Temperatura observada [°C]",
    y = "Derechos residuales de autor [°C]"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
    axis.title = element_text(face = "bold"),
    strip.text = element_text(size = 12, face = "bold"),
    legend.position = "right",
    panel.grid.major = element_line(color = "gray90", linetype = "dotted"),
    panel.grid.minor = element_blank()
  )

# Imprimir el gráfico
p2
Residual analysis by LCZ class for crowdsourced data

Residuos por clase LCZ para la evaluación de datos de colaboración abierta. La dispersión aleatoria alrededor de cero indica un buen desempeño del modelo en diferentes formas urbanas.

Hallazgos clave y discusión

Resumen de resultados

Métrica Valor Interpretación
Intensidad máxima de UHI 3,7°C Importante efecto de calentamiento urbano
RMSE general ~0,8-1,2°C Buena precisión de predicción
LCZ con mejor rendimiento Abierto de poca altura Bien representado en los datos de entrenamiento
LCZ desafiante Compacto de media altura Mayor variabilidad espacial

Ventajas de los datos de colaboración colectiva

  1. Alta resolución espacial: Cientos de estaciones proporcionan patrones térmicos urbanos detallados
  2. Monitoreo en tiempo real: Captura cambios rápidos de temperatura
  3. Rentable: aprovecha la infraestructura ciudadana existente
  4. Complementario: llena los vacíos en las redes oficiales de monitoreo

Beneficios del control de calidad

El proceso de control de calidad de CrowdQCplus con éxito: - Lecturas estadísticamente improbables identificadas y eliminadas - Ruido reducido en la señal de temperatura. - Correlación mejorada entre los valores observados y predichos. - Detección de patrones espaciales mejorada

Aplicaciones prácticas

  1. Alerta temprana de olas de calor: Identifique las áreas de mayor riesgo durante eventos de calor extremo
  2. Planificación Urbana: Informar la ubicación de infraestructura verde en función de patrones térmicos
  3. Adaptación climática: Evaluar la efectividad de las estrategias de mitigación
  4. Salud pública: intervenciones dirigidas a zonas vulnerables al calor

Guardar resultados

# Guardar las métricas de evaluación en formato CSV
write.csv(df_eval_metrics, 
          file = "cws_uhi_metrics_may2023.csv", 
          row.names = FALSE)

# Guardar el marco de datos de evaluación completo
write.csv(df_eval, 
          file = "cws_uhi_evaluation_may2023.csv", 
          row.names = FALSE)

# Guardar parcelas
ggsave("cws_correlation_plot.png", p1_with_marginals, width = 10, height = 8, dpi = 300)
ggsave("cws_residuals_by_lcz.png", p2, width = 12, height = 10, dpi = 300)

¿Tiene comentarios o sugerencias?

¿Tiene una idea para mejorar o detectó un error? ¡Nos encantaría saber de usted! Haga clic en el botón a continuación para crear una nueva edición (GitHub) y compartir sus comentarios o sugerencias directamente con nosotros.

Abrir incidencia en GitHub