Análisis de la Contaminación por PM10 y su Relación con el Turismo en Monterrey

La contaminación del aire en Monterrey y su zona metropolitana se ha convertido en un tema de creciente visibilidad y preocupación social en los últimos meses. A medida que la ciudad continúa expandiéndose e industrializándose, los niveles de contaminación han aumentado de forma alarmante, lo que ha derivado en una crisis ambiental que impacta directamente en la calidad del aire que respiramos.

Este problema no solo afecta nuestra salud, sino que también repercute en otros aspectos fundamentales de la vida urbana, como la economía, la movilidad y, en particular, el turismo. Con base en esta preocupación, se decidió realizar un análisis que explorara la correlación entre los niveles mensuales promedio de partículas PM10 y la cantidad de habitaciones disponibles para hospedaje en la región.

Para ello, se desarrollaron dos indicadores clave que permiten monitorear la evolución de los niveles de PM10 a lo largo del tiempo. Además, se llevaron a cabo pruebas estadísticas para evaluar cómo la calidad del aire podría estar influyendo en la dinámica turística del estado de Nuevo León. Este análisis busca aportar evidencia relevante para la toma de decisiones en políticas públicas y estrategias de desarrollo sostenible en la región.

Metodología de investigación

  1. Extracción de datos para crear una base de datos para obtener los niveles de PM10 del 2022 al 2025.
  2. Análisis exploratorio de datos
  3. Diseño para KPI
  4. Investigación de valores de treshold
  5. Creación de KPI
  6. Limitantes del análisis
  7. Recomendaciones a futuro para mejorar la metodología
  8. Conclusiones

Importamos las bases de datos

library(readxl)
contaminacion <- read_excel("/Users/pedrovillanueva/Downloads/PM10_Monterrey_Ene_Abr_2025.xlsx")
contaminacion_mensual <- read_excel("/Users/pedrovillanueva/Downloads/PM10_Monterrey_Mensual_2022_2025.xlsx")

Transformación de datos

# Asegurar formato de fecha
contaminacion$Fecha <- as.Date(contaminacion$Fecha)

Indicador de Evolución diaria de PM10 en la Zona Metropolitana

names(contaminacion)[names(contaminacion) == "PM10 (µg/m³)"] <- "PM10"

fecha_min <- min(contaminacion$Fecha)
fecha_max <- max(contaminacion$Fecha)

zonas <- data.frame(
  ymin = c(0, 41, 76, 151),
  ymax = c(40, 75, 150, max(contaminacion$PM10, na.rm = TRUE) + 10),
  Calidad = c("Excelente", "Regular", "Malo", "Muy Malo"),
  Color = c("green", "yellow", "orange", "red")
)

library(ggplot2)
library(geometries)
ggplot() +
  geom_rect(
    data = zonas,
    aes(xmin = fecha_min, xmax = fecha_max, ymin = ymin, ymax = ymax, fill = Calidad),
    alpha = 0.2
  ) +
  geom_line(
    data = contaminacion,
    aes(x = Fecha, y = PM10),
    color = "black", size = 1
  ) +
  scale_fill_manual(values = setNames(zonas$Color, zonas$Calidad)) +
  labs(
    title = "Evolución diaria de PM10 en Monterrey",
    x = "Fecha",
    y = "PM10 (µg/m³)",
    fill = "Calidad del aire"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.title = element_text(hjust = 0.5)
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Tabla de PM10 Claves

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(gt)
## Warning: Can't find generic `as.gtable` in package gtable to register S3 method.
## ℹ This message is only shown to developers using devtools.
## ℹ Do you need to update gtable to the latest version?
# Asegúrate de que la columna se llame "PM10"
names(contaminacion)[names(contaminacion) == "PM10 (µg/m³)"] <- "PM10"

matriz_10_dias <- contaminacion %>%
  mutate(
    Calidad = case_when(
      PM10 <= 40 ~ "Excelente",
      PM10 <= 75 ~ "Regular",
      PM10 <= 150 ~ "Malo",
      PM10 <= 250 ~ "Muy Malo",
      PM10 > 250 ~ "Extremo"
    )
  ) %>%
  arrange(desc(Fecha)) %>%
  select(Fecha, PM10, Calidad) %>%
  slice(1:10) %>%
  arrange(Fecha)

matriz_10_dias %>%
  gt() %>%
  data_color(
    columns = Calidad,
    colors = scales::col_factor(
      palette = c(
        "Excelente" = "lightgreen",
        "Regular" = "khaki",
        "Malo" = "orange",
        "Muy Malo" = "red",
        "Extremo" = "purple"
      ),
      domain = c("Excelente", "Regular", "Malo", "Muy Malo", "Extremo")
    )
  ) %>%
  tab_header(
    title = "🟢 KPI: Calidad del aire por PM10 (últimos 10 días)"
  ) %>%
  tab_style(
    style = cell_text(weight = "bold", color = "white"),
    locations = cells_body(
      columns = Calidad,
      rows = Calidad %in% c("Muy Malo", "Extremo")
    )
  ) %>%
  tab_footnote(
    footnote = "⚠️ ¡Alerta! Calidad del aire en nivel crítico.",
    locations = cells_body(
      columns = Calidad,
      rows = Calidad %in% c("Muy Malo", "Extremo")
    )
  )
## Warning: Since gt v0.9.0, the `colors` argument has been deprecated.
## • Please use the `fn` argument instead.
## This warning is displayed once every 8 hours.
🟢 KPI: Calidad del aire por PM10 (últimos 10 días)
Fecha PM10 Calidad
2025-04-21 57 Regular
2025-04-22 49 Regular
2025-04-23 77 Malo
2025-04-24 63 Regular
2025-04-25 70 Regular
2025-04-26 47 Regular
2025-04-27 66 Regular
2025-04-28 93 Malo
2025-04-29 62 Regular
2025-04-30 76 Malo

Matriz de correlación PM10 y Número de Hospedajes Alquilados

# Instalar y cargar el paquete si es necesario
# install.packages("corrplot")
library(corrplot)
## corrplot 0.95 loaded
contaminacion_mensual$Cuartos <- as.numeric(as.character(contaminacion_mensual$Cuartos))

datos_cor <- contaminacion_mensual[, c("PM10", "Cuartos")]
matriz_cor <- cor(datos_cor, use = "complete.obs", method = "pearson")

print(matriz_cor)
##              PM10   Cuartos
## PM10    1.0000000 0.5895703
## Cuartos 0.5895703 1.0000000
corrplot(matriz_cor, method = "color", type = "upper",
         tl.col = "black", tl.srt = 45, addCoef.col = "black",
         col = colorRampPalette(c("blue", "white", "red"))(200),
         title = "Matriz de Correlación", mar = c(0, 0, 1, 0))

Matriz de correlación PM10 y Número de Hospedajes Alquilados (LAG T -1)

contaminacion_mensual <- contaminacion_mensual %>%
  arrange(Mes) %>%
  mutate(
    Cuartos = as.numeric(as.character(Cuartos)),
    Cuartos_Lag1 = lag(Cuartos, 1)
  )

datos_cor <- contaminacion_mensual %>%
  filter(!is.na(PM10), !is.na(Cuartos_Lag1)) %>%
  select(PM10, Cuartos_Lag1)

matriz_cor <- cor(datos_cor, use = "complete.obs", method = "pearson")

print(matriz_cor)
##                   PM10 Cuartos_Lag1
## PM10         1.0000000    0.0619034
## Cuartos_Lag1 0.0619034    1.0000000
corrplot(matriz_cor, method = "color", type = "upper",
         tl.col = "black", tl.srt = 45, addCoef.col = "black",
         col = colorRampPalette(c("blue", "white", "red"))(200),
         title = "Matriz de Correlación: PM10 vs Cuartos (Lag 1)", mar = c(0, 0, 1, 0))

# Conclucioens sobre el análisis de correlación - Limitaciones del análisis: Existen importantes limitaciones al momento de realizar este análisis. La principal es que, aunque se cuenta con información sobre los niveles de contaminación desde el año 2022, los datos sobre el número de cuartos ocupados solo abarcan algunos meses incompletos de 2022 y 2023. Esto impide realizar un análisis de estacionalidad confiable, ya que hay huecos de hasta cinco meses en la serie temporal. Por lo tanto, no es posible construir una serie de tiempo robusta para fines estadísticos.