En las últimas décadas, el crecimiento acelerado de las áreas urbanas ha generado cambios significativos en los patrones climáticos locales, dando lugar a la formación de microclimas urbanos. Estos microclimas se caracterizan por variaciones en la temperatura, humedad, velocidad del viento y otros factores meteorológicos, que difieren de las condiciones climáticas de las áreas rurales circundantes. Comprender y clasificar estos microclimas es crucial para la planificación urbana, la gestión de recursos energéticos y la mejora de la calidad de vida de los habitantes.
Además, en un contexto global de transición hacia fuentes de energía renovable, la energía solar se ha posicionado como una de las alternativas más prometedoras. Sin embargo, la eficiencia de los sistemas de captación de energía solar depende en gran medida de las condiciones meteorológicas locales, como la radiación solar, la nubosidad y la temperatura. Por lo tanto, predecir con precisión el potencial de energía solar en diferentes áreas urbanas es fundamental para optimizar la instalación de paneles solares y maximizar su rendimiento.
Paquetes y librerias necesarias
Code
# Carga de paquetes necesarios# 📊 Manejo y visualización de datoslibrary(tidyverse) # Incluye ggplot2, dplyr, tidyr, readr, tibble, stringr, forcats, purrrlibrary(ggpubr) # Gráficos mejorados con ggplot2library(patchwork) # Para combinar múltiples gráficoslibrary(ggcorrplot) # Para gráficos de correlaciónlibrary(ggplot2) # (ya incluido en tidyverse, pero puedes mantenerlo si usas versiones específicas)library(viridis) # Mejor paleta de colores para gráficos# 📋 Manejo de datos y transformaciónlibrary(Hmisc) # Funciones avanzadas de estadísticalibrary(knitr) # Para formatear tablas en R Markdownlibrary(DT) # Para tablas interactivaslibrary(pander) # Para formateo de reporteslibrary(reshape2) # Para manipulación de datos en formato largo/ancho# 📈 Estadística y análisis de datoslibrary(nortest) # Pruebas de normalidadlibrary(naniar) # Visualización y manejo de datos faltanteslibrary(EnvStats) # Métodos avanzados de análisis ambiental# 📦 Utilidades adicionaleslibrary(gridExtra) # Para organizar gráficos en cuadrículas
Representa la tasa de precipitación (lluvia, nieve) ajustada según correcciones satelitales.
WS10M: MERRA-2 Velocidad del Viento a 10 Metros (m/s).
Velocidad del viento medida a una altura de 10 metros sobre la superficie.
WD10M: MERRA-2 Dirección del Viento a 10 Metros (Grados).
Indica la dirección desde la que sopla el viento, en grados (0° = Norte, 90° = Este, etc.).
PS: MERRA-2 Presión Superficial (kPa).
Mide la presión atmosférica en la superficie terrestre.
Variables Relacionadas con la Energía Solar
ALLSKY_SFC_UV_INDEX: CERES SYN1deg Índice UV en Superficie Bajo Cielo Total (W m⁻² × 40).
Mide la intensidad de la radiación ultravioleta en la superficie terrestre.
ALLSKY_SFC_SW_DIFF: CERES SYN1deg Irradiancia Difusa de Onda Corta en Superficie Bajo Cielo Total (Wh/m²).
Cantidad de energía solar dispersada en la atmósfera que llega a la superficie terrestre.
ALLSKY_SRF_ALB: CERES SYN1deg Albedo Superficial Bajo Cielo Total (adimensional).
Fracción de la radiación solar reflejada por la superficie terrestre respecto a la radiación recibida.
ALLSKY_KT: CERES SYN1deg Índice de Claridad de Insolación Bajo Cielo Total (adimensional).
Relación entre la irradiancia solar real y la irradiancia solar máxima teórica en ausencia de atmósfera.
Variables Adicionales
T2MDEW: MERRA-2 Punto de Rocío/Escarcha a 2 Metros (°C).
Temperatura a la cual el aire debe enfriarse para que el vapor de agua se condense en forma de rocío.
T2MWET: MERRA-2 Temperatura de Bulbo Húmedo a 2 Metros (°C).
Mide la temperatura mínima alcanzable por evaporación de agua en condiciones de enfriamiento adiabático.
WS50M: MERRA-2 Velocidad del Viento a 50 Metros (m/s).
Velocidad del viento medida a 50 metros de altura, relevante para el aprovechamiento eólico.
Variables Geográficas
Loacality: Localidad donde se tomaron los datos.
NHBD: Neighborhood, barrio donde se registraron las mediciones.
Este glosario permite una mejor comprensión de los datos utilizados en el análisis de microclimas y potencial de energía solar. ### Objetivos:
Impacto en la planificación urbana: La clasificación de microclimas permite identificar áreas con condiciones climáticas extremas (como islas de calor urbanas) y proponer medidas de mitigación, como la creación de espacios verdes o la implementación de techos reflectantes.
Optimización de energía renovable: La predicción de energía solar potencial es esencial para diseñar sistemas de energía solar más eficientes y reducir la dependencia de combustibles fósiles.
Contribución científica: Este proyecto utiliza datos de alta resolución de fuentes como MERRA-2 y CERES SYN1deg, lo que permite un análisis detallado y preciso de las variables meteorológicas. Los resultados están pensados para ser publicados y servir como base para futuras investigaciones. ## Datos
Code
# Vista de los datosdatatable( dataclimabq[1:100, ],caption ="Data Frame: dataclimabq",options =list(scrollX =TRUE,scrollY ="450px" ))
# Contar la cantidad de valores -999 en cada columnacount_neg_999 <-colSums(dataclimabq ==-999)# Imprimir resultadoscat("\nCount of -999 values in each column:\n")
En el análisis de datos tipo meteorológicos y climáticos, es común encontrar valores faltantes que no pueden ser calculados o que están fuera del rango de disponibilidad de las fuentes. Estos valores en este caso han sido representados con un código específico, como -999, para indicar su ausencia. En este contexto, se trabajó con un conjunto de (1)Variables. Estos mismos, provenientes de fuentes como MERRA-2 y CERES SYN1deg, son fundamentales para estudios climáticos, pero requieren un manejo cuidadoso de los valores faltantes para garantizar la precisión y confiabilidad de los análisis.
Limpieza de datos
Code
# Seleccionar solo las columnas numéricasnumeric_cols <-sapply(dataclimabq, is.numeric)# Crear una copia del dataframe originaldataclimabq_cleaned <- dataclimabq# Reemplazar -999.0 por NA solo en columnas numéricasdataclimabq_cleaned[numeric_cols] <-lapply(dataclimabq_cleaned[numeric_cols], function(x) replace(x, x ==-999.0, NA))# Calcular el porcentaje de datos faltantes por columnamissing_per_col <-colSums(is.na(dataclimabq_cleaned)) /nrow(dataclimabq_cleaned) *100# Calcular el porcentaje total de datos faltantestotal_missing <-sum(is.na(dataclimabq_cleaned))total_values <-prod(dim(dataclimabq_cleaned))missing_percentage <- (total_missing / total_values) *100
Code
suppressWarnings(require(Amelia))missmap(dataclimabq_cleaned, col =c("#fde725","#440154" ))
Code
gg_miss_var(dataclimabq_cleaned, show_pct =TRUE) +geom_hline(yintercept =50, linetype ="dashed", color ="black") +labs(title ="Cantidad de NA por columna") +theme_minimal()
Code
# Imprimir resultadoscat("Porcentaje de datos faltantes por variable:\n")
cat("\nPorcentaje total de datos faltantes:", round(missing_percentage, 2), "%\n")
Porcentaje total de datos faltantes: 6.48 %
Pero este porcentaje varía considerablemente entre las variables. Las variables con mayor porcentaje de datos faltantes son:
Variable Porcentaje de Datos Faltantes - ALLSKY_SFC_UV_INDEX 8.49% - ALLSKY_SRF_ALB 23.77% - ALLSKY_SFC_SW_DIFF 37.73% - ALLSKY_KT 53.03% Estos valores faltantes están representados con el valor -999, que indica que los datos no pudieron calcularse o están fuera del rango de disponibilidad de las fuentes.
Los porcentajes anteriormente mostrados se pueden visualizar de una mejor manera en las graficas anteriores:
Análisis de Correlación
Code
numeric_data <- dataclimabq_cleaned[sapply(dataclimabq_cleaned, is.numeric)]# Calcular la matriz de correlacióncorr_matrix <-cor(numeric_data, use ="pairwise.complete.obs")# Crear el heatmap sin números en las celdas y sin coord_fixed()ggcorrplot(corr_matrix, method ="square", type ="lower", # Mostrar solo la mitad inferiorlab =FALSE, # Eliminar los números dentro de las celdascolors =c("blue", "white", "red"), title ="Matriz de Correlación de Variables Numéricas",ggtheme =theme_minimal()) +theme(axis.text.x =element_text(angle =45, hjust =1, size =10), # Rotar etiquetas para mejor legibilidadaxis.text.y =element_text(size =10))
Análisis de Correlación entre Variables Climáticas
Este análisis busca entender las relaciones entre distintas variables climáticas para apoyar la planificación urbana y la optimización de energía renovable.
Puntos clave del análisis de correlación:
1️. Temperatura y Radiación Solar
T2M (Temperatura a 2m) y ALLSKY_SFC_SW_DIFF (Irradiancia de onda corta difusa) tienen una fuerte correlación positiva (~0.73).
Esto indica que temperaturas más altas suelen estar asociadas con una mayor irradiancia solar difusa, lo que es clave para modelos de energía solar.
2️. Humedad y Precipitación
RH2M (Humedad relativa a 2m) y PRECTOTCORR (Precipitación corregida) presentan una correlación negativa moderada (~ -0.76).
A mayor precipitación, la humedad relativa disminuye, lo cual puede indicar cambios abruptos en el clima urbano.
3️. Viento y Altura
WS10M (Viento a 10m) y WS50M (Viento a 50m) tienen una correlación de casi 0.99.
Esto sugiere que la velocidad del viento a distintas alturas está altamente relacionada, lo que es útil para evaluar viabilidad de proyectos eólicos.
4️. Presión Superficial y Radiación Solar
ALLSKY_SFC_UV_INDEX (Índice UV) y PS (Presión superficial) tienen correlación negativa (~ -0.25).
Puede indicar que a mayor presión, la radiación UV en la superficie tiende a disminuir, lo que podría afectar la eficiencia de paneles solares, no obstante la relación entre ambas variables es bastante debil.
Distribución de Variables
Code
dataclimabq_long <-melt(dataclimabq_cleaned)dataclimabq_long <-na.omit(dataclimabq_long)# Crear boxplotggplot(dataclimabq_long, aes(x =factor(1), y = value, fill = variable)) +geom_boxplot(outlier.colour ="red", outlier.shape =8, outlier.size =3) +facet_wrap(~ variable, scales ="free_y") +labs(x ="Variables", y ="Valores", title ="Distribución de Variables en dataclimabq") +theme_minimal() +theme(axis.text.x =element_blank(), strip.text =element_text(size =12), axis.text.y =element_text(size =10), legend.position ="none") +scale_fill_viridis_d(option ="plasma") # Paleta de colores para más de 12 variables
Code
pander(summary(dataclimabq_cleaned))
Table continues below
YEAR
MO
DY
HR
T2M
Min. :2020
Min. : 1.000
Min. : 1.00
Min. : 0.0
Min. :22.88
1st Qu.:2021
1st Qu.: 4.000
1st Qu.: 8.00
1st Qu.: 6.0
1st Qu.:26.91
Median :2022
Median : 7.000
Median :16.00
Median :12.0
Median :27.93
Mean :2022
Mean : 6.518
Mean :15.73
Mean :11.5
Mean :28.21
3rd Qu.:2023
3rd Qu.:10.000
3rd Qu.:23.00
3rd Qu.:17.5
3rd Qu.:29.46
Max. :2025
Max. :12.000
Max. :31.00
Max. :23.0
Max. :35.36
NA
NA
NA
NA
NA
Table continues below
PRECTOTCORR
RH2M
WS10M
WD10M
Min. : 0.00
Min. : 0.00
Min. : 0.040
Min. : 0.00
1st Qu.: 2.60
1st Qu.: 0.09
1st Qu.: 3.560
1st Qu.: 30.30
Median : 71.73
Median : 3.13
Median : 5.410
Median : 42.00
Mean : 53.68
Mean : 29.63
Mean : 5.292
Mean : 66.46
3rd Qu.: 86.14
3rd Qu.: 73.71
3rd Qu.: 6.970
3rd Qu.: 57.20
Max. :684.23
Max. :684.23
Max. :11.720
Max. :359.80
NA
NA
NA
NA
Table continues below
PS
ALLSKY_SFC_UV_INDEX
ALLSKY_SRF_ALB
ALLSKY_SFC_SW_DIFF
Min. : 99.97
Min. : 0.00
Min. : 0.0
Min. : 0.0
1st Qu.:100.43
1st Qu.: 0.00
1st Qu.: 0.0
1st Qu.: 0.0
Median :100.54
Median : 0.00
Median : 0.1
Median : 0.1
Mean :100.55
Mean : 2.38
Mean : 72.1
Mean : 45.0
3rd Qu.:100.66
3rd Qu.: 3.95
3rd Qu.:139.2
3rd Qu.: 11.1
Max. :101.27
Max. :17.52
Max. :585.1
Max. :525.3
NA
NA’s :130425
NA’s :365040
NA’s :579409
Table continues below
T2MDEW
T2MWET
WS50M
ALLSKY_KT
Min. :17.85
Min. :22.05
Min. : 0.040
Min. :0.0
1st Qu.:23.19
1st Qu.:25.44
1st Qu.: 4.440
1st Qu.:0.4
Median :24.43
Median :26.33
Median : 6.730
Median :0.6
Mean :24.25
Mean :26.23
Mean : 6.639
Mean :0.5
3rd Qu.:25.43
3rd Qu.:27.08
3rd Qu.: 8.790
3rd Qu.:0.7
Max. :27.97
Max. :29.61
Max. :15.150
Max. :0.8
NA
NA
NA
NA’s :814249
LOCALITY
NBHD
Length:1535519
Length:1535519
Class :character
Class :character
Mode :character
Mode :character
NA
NA
NA
NA
NA
NA
NA
NA
##Se detectan datos NA’S teniendo en cuenta el rango lógico de valores en los que deberían estar las variables numéricas
Code
# Crear una copia del dataframe limpio anteriordataclimabq_limits <- dataclimabq_cleaned# Definir los límites lógicos para cada variable en una listalimits <-list(YEAR =c(2020, 2025),MO =c(1, 12),DY =c(1, 31),HR =c(0, 23),T2M =c(-90, 60),RH2M =c(0, 100),PRECTOTCORR =c(0, 300),WS10M =c(0, 80),WD10M =c(0, 360),PS =c(50, 110),ALLSKY_SFC_UV_INDEX =c(0, 15),ALLSKY_SFC_SW_DIFF =c(0, 1500),ALLSKY_SRF_ALB =c(0, 1),T2MDEW =c(-45, 35),T2MWET =c(-35, 35),WS50M =c(0, 75),ALLSKY_KT =c(0, 1))# Reemplazar valores fuera de los límites por NAfor (col innames(limits)) { min_val <- limits[[col]][1] max_val <- limits[[col]][2] dataclimabq_limits[[col]] <-ifelse(dataclimabq_limits[[col]] < min_val | dataclimabq_limits[[col]] > max_val, NA, dataclimabq_limits[[col]])}
Code
pander(summary(dataclimabq_limits))
Table continues below
YEAR
MO
DY
HR
T2M
Min. :2020
Min. : 1.000
Min. : 1.00
Min. : 0.0
Min. :22.88
1st Qu.:2021
1st Qu.: 4.000
1st Qu.: 8.00
1st Qu.: 6.0
1st Qu.:26.91
Median :2022
Median : 7.000
Median :16.00
Median :12.0
Median :27.93
Mean :2022
Mean : 6.518
Mean :15.73
Mean :11.5
Mean :28.21
3rd Qu.:2023
3rd Qu.:10.000
3rd Qu.:23.00
3rd Qu.:17.5
3rd Qu.:29.46
Max. :2025
Max. :12.000
Max. :31.00
Max. :23.0
Max. :35.36
NA
NA
NA
NA
NA
Table continues below
PRECTOTCORR
RH2M
WS10M
WD10M
Min. : 0.00
Min. : 0.00
Min. : 0.040
Min. : 0.00
1st Qu.: 2.60
1st Qu.: 0.09
1st Qu.: 3.560
1st Qu.: 30.30
Median : 71.73
Median : 3.12
Median : 5.410
Median : 42.00
Mean : 53.65
Mean :29.41
Mean : 5.292
Mean : 66.46
3rd Qu.: 86.14
3rd Qu.:73.53
3rd Qu.: 6.970
3rd Qu.: 57.20
Max. :295.23
Max. :99.91
Max. :11.720
Max. :359.80
NA’s :132
NA’s :2231
NA
NA
Table continues below
PS
ALLSKY_SFC_UV_INDEX
ALLSKY_SRF_ALB
ALLSKY_SFC_SW_DIFF
Min. : 99.97
Min. : 0.00
Min. :0.0
Min. : 0.0
1st Qu.:100.43
1st Qu.: 0.00
1st Qu.:0.0
1st Qu.: 0.0
Median :100.54
Median : 0.00
Median :0.0
Median : 0.1
Mean :100.55
Mean : 2.35
Mean :0.1
Mean : 45.0
3rd Qu.:100.66
3rd Qu.: 3.88
3rd Qu.:0.1
3rd Qu.: 11.1
Max. :101.27
Max. :15.00
Max. :1.0
Max. :525.3
NA
NA’s :133770
NA’s :838981
NA’s :579409
Table continues below
T2MDEW
T2MWET
WS50M
ALLSKY_KT
Min. :17.85
Min. :22.05
Min. : 0.040
Min. :0.0
1st Qu.:23.19
1st Qu.:25.44
1st Qu.: 4.440
1st Qu.:0.4
Median :24.43
Median :26.33
Median : 6.730
Median :0.6
Mean :24.25
Mean :26.23
Mean : 6.639
Mean :0.5
3rd Qu.:25.43
3rd Qu.:27.08
3rd Qu.: 8.790
3rd Qu.:0.7
Max. :27.97
Max. :29.61
Max. :15.150
Max. :0.8
NA
NA
NA
NA’s :814249
LOCALITY
NBHD
Length:1535519
Length:1535519
Class :character
Class :character
Mode :character
Mode :character
NA
NA
NA
NA
NA
NA
NA
NA
Code
# Obtener las localidades únicaslocalidades <-unique(dataclimabq_cleaned$LOCALITY)# Imprimir resultadoscat("Localidades únicas:\n")
Localidades únicas:
Code
print(localidades)
[1] "Centro" "Sur" "Occidente" "Oriente" "Norte"
Code
dataclimabq_long <-melt(dataclimabq_limits)dataclimabq_long <-na.omit(dataclimabq_long)# Crear boxplotggplot(dataclimabq_long, aes(x =factor(1), y = value, fill = variable)) +geom_boxplot(outlier.colour ="red", outlier.shape =8, outlier.size =3) +facet_wrap(~ variable, scales ="free_y") +labs(x ="Variables", y ="Valores", title ="Distribución de Variables en dataclimabq_limit") +theme_minimal() +theme(axis.text.x =element_blank(), strip.text =element_text(size =12), axis.text.y =element_text(size =10), legend.position ="none") +scale_fill_viridis_d(option ="plasma") # Paleta de colores para más de 12 variables
Debido a que la falta de datos en las variables ALLSKY_SRF_ALB y ALLSKY_KT procederemos a analizar la correlación entre los datos y ver alternativas para el tratamiento de los datos faltantes más allá de los comunes, como lo son el reemplazo por la media, la mediana o el descarte completo de los datos.
Code
library(ggplot2)library(ggpubr) library(dplyr)# Definir número máximo de variables a graficar por iteraciónmax_plots <-6# Ajusta este valor según tu necesidad# Variables numéricasnumeric_cols <-names(select_if(dataclimabq_limits, is.numeric))# Graficar histogramas y QQ plots por localidadfor (localidad inunique(dataclimabq_limits$LOCALITY)[1:3]) { # Limita a las primeras 3 localidades para evitar demoras df_localidad <-filter(dataclimabq_limits, LOCALITY == localidad)# Seleccionar un subconjunto de variables si hay demasiadas vars_to_plot <-head(numeric_cols, max_plots) p1 <-ggplot(df_localidad %>%select(all_of(vars_to_plot)) %>%pivot_longer(cols =everything(), names_to ="Variable", values_to ="Valor"), aes(x = Valor)) +geom_histogram(aes(y = ..density..), bins =30, fill ="blue", alpha =0.5) +geom_density(color ="red", size =1) +facet_wrap(~Variable, scales ="free_x") +labs(title =paste("Histogramas en", localidad)) +theme_minimal() p2 <-ggplot(df_localidad %>%select(all_of(vars_to_plot)) %>%pivot_longer(cols =everything(), names_to ="Variable", values_to ="Valor"), aes(sample = Valor)) +stat_qq() +stat_qq_line(color ="red") +facet_wrap(~Variable, scales ="free") +labs(title =paste("QQ Plots en", localidad)) +theme_minimal()print(p1)print(p2)}
Code
# Variables categóricascategorical_cols <-names(select_if(dataclimabq_limits, is.character))for (localidad inunique(dataclimabq_limits$LOCALITY)[1:3]) { # Solo primeras 3 localidades para evitar demora df_localidad <-filter(dataclimabq_limits, LOCALITY == localidad) p_cat <-ggplot(df_localidad %>%pivot_longer(cols =all_of(categorical_cols), names_to ="Variable", values_to ="Valor"),aes(x = Valor)) +geom_bar(fill ="skyblue") +facet_wrap(~Variable, scales ="free_x") +labs(title =paste("Histogramas de variables categóricas en", localidad), x ="Categoría", y ="Frecuencia") +theme_minimal() +theme(axis.text.x =element_text(angle =45, hjust =1))print(p_cat)}
Code
# Test de Shapiro-Wilk (con muestreo si hay más de 5000 datos)numeric_cols <-names(select_if(dataclimabq_limits, is.numeric))normality_results <-data.frame(Variable =character(), Statistic =numeric(), P_value =numeric())for (col in numeric_cols) { data <-na.omit(dataclimabq_limits[[col]])if (length(data) >5000) { data <-sample(data, 5000) # Tomar solo 5000 valores aleatorios }if (length(data) >=3) { # Verificar que haya suficientes datos shapiro_test <-shapiro.test(data) normality_results <-rbind(normality_results, data.frame(Variable = col, Statistic = shapiro_test$statistic, P_value = shapiro_test$p.value)) }}print(normality_results)
Análisis de Normalidad y Distribución de Variables
El test de normalidad proporciona un valor estadístico y un p-valor. Si el p-valor es menor a 0.05, significa que rechazamos la hipótesis nula de que la variable sigue una distribución normal.
Resultados Clave:
Variables con mejor ajuste a la normalidad (mayores estadísticas y p-valores más altos, pero aún no completamente normales):
T2M (Temperatura a 2 metros): $ p = 7.63 ^{-107} $
T2MDEW (Punto de rocío a 2 metros): $ p = 6.92 ^{-107} $
T2MWET (Temperatura húmeda a 2 metros): $ p = 1.67 ^{-90} $
WS10M (Viento a 10 metros): $ p = 4.65 ^{-97} $
WS50M (Viento a 50 metros): $ p = 1.74 ^{-94} $
Estas variables están relativamente cerca de una normalidad aceptable, aunque siguen mostrando desviaciones.
Variables que NO siguen una distribución normal (p-valores extremadamente pequeños, estadística baja):
WD10M (Dirección del viento a 10m): $ p = 8.73 ^{-211} $ (muy no normal)
ALLSKY_SFC_SW_DIFF (Radiación solar difusa): $ p = 1.65 ^{-222} $
ALLSKY_SRF_ALB (Albedo superficial): $ p = 3.45 ^{-220} $
RH2M (Humedad relativa a 2m): $ p = 5.41 ^{-197} $
PRECTOTCORR (Precipitación corregida): $ p = 5.14 ^{-188} $
ALLSKY_SFC_UV_INDEX (Índice UV): $ p = 2.21 ^{-202} $
ALLSKY_KT (Transmisión atmosférica): $ p = 2.50 ^{-179} $
Estas variables muestran una distribución altamente sesgada o multimodal, lo que indica que no siguen una normalidad en absoluto.
Variables de tiempo (año, mes, día, hora)
YEAR: $ p = 1.91 ^{-162} $
MO: $ p = 8.82 ^{-142} $
DY: $ p = 2.42 ^{-134} $
HR: $ p = 2.95 ^{-136} $
Estas variables tienen p-valores extremadamente pequeños, indicando que su distribución no es normal (lo cual era esperable porque el tiempo no suele distribuirse normalmente).
Análisis de Variables Categóricas
El test de Chi-cuadrado analiza si la distribución de categorías en “LOCALITY” y “NBHD” es uniforme o tiene patrones significativos.
LOCALITY (\chi^2 = 6,142,076, p = 0.0)
Indica una distribución altamente no uniforme de las localidades.
NBHD (\chi^2 = 4,167,836, p = 0.0)**
También muestra que la distribución de barrios no es uniforme en absoluto.
Esto sugiere que algunos barrios/localidades tienen una concentración mucho mayor de registros que otros.
Conclusiones
Ninguna variable numérica sigue una distribución normal. Algunas se acercan (T2M, T2MDEW, T2MWET), pero siguen sin cumplir el criterio de normalidad.
Muchas variables climáticas tienen distribuciones sesgadas o multimodales (especialmente precipitación, humedad y radiación solar).
Las variables categóricas muestran una distribución no uniforme, lo que sugiere que ciertos barrios/localidades tienen más representación en los datos.
Code
# Reemplazar valores NA con la mediana de la variable por localidaddataclimabq_limits <- dataclimabq_limits %>%group_by(LOCALITY) %>%mutate(across(where(is.numeric), ~ifelse(is.na(.), median(., na.rm =TRUE), .)))# Verificar si quedan valores NAcolSums(is.na(dataclimabq_limits))
Análisis visual de Variables implicadas en el problema de microclimas
Code
df_median <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(T2M_median =median(T2M, na.rm =TRUE),T2M_sd =sd(T2M, na.rm =TRUE), .groups ="drop")# Limitar la escala de la desviación estándar para evitar bandas demasiado ampliasdf_median <- df_median %>%mutate(T2M_sd =ifelse(is.na(T2M_sd), 0, pmin(T2M_sd, 0.5))) # Evitar NA y controlar valores altos# Gráfico con mejoras para evitar solapamientoggplot(df_median, aes(x = YEAR, y = T2M_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +# Evitar superposición de puntosgeom_ribbon(aes(ymin = T2M_median - T2M_sd, ymax = T2M_median + T2M_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de T2M a lo largo del tiempo",x ="Año", y ="T2M (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
df_median_RH2M <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(RH2M_median =median(RH2M, na.rm =TRUE),RH2M_sd =sd(RH2M, na.rm =TRUE), .groups ="drop")df_median_RH2M <- df_median_RH2M %>%mutate(RH2M_sd =ifelse(is.na(RH2M_sd), 0, pmin(RH2M_sd, 5))) ggplot(df_median_RH2M, aes(x = YEAR, y = RH2M_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = RH2M_median - RH2M_sd, ymax = RH2M_median + RH2M_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de RH2M a lo largo del tiempo",x ="Año", y ="RH2M (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
df_median_WS10M <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(WS10M_median =median(WS10M, na.rm =TRUE),WS10M_sd =sd(WS10M, na.rm =TRUE), .groups ="drop")df_median_WS10M <- df_median_WS10M %>%mutate(WS10M_sd =ifelse(is.na(WS10M_sd), 0, pmin(WS10M_sd, 1))) ggplot(df_median_WS10M, aes(x = YEAR, y = WS10M_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = WS10M_median - WS10M_sd, ymax = WS10M_median + WS10M_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de WS10M a lo largo del tiempo",x ="Año", y ="WS10M (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
df_median_WD10M <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(WD10M_median =median(WD10M, na.rm =TRUE),WD10M_sd =sd(WD10M, na.rm =TRUE), .groups ="drop")df_median_WD10M <- df_median_WD10M %>%mutate(WD10M_sd =ifelse(is.na(WD10M_sd), 0, pmin(WD10M_sd, 10))) ggplot(df_median_WD10M, aes(x = YEAR, y = WD10M_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = WD10M_median - WD10M_sd, ymax = WD10M_median + WD10M_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de WD10M a lo largo del tiempo",x ="Año", y ="WD10M (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
df_median_PS <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(PS_median =median(PS, na.rm =TRUE),PS_sd =sd(PS, na.rm =TRUE), .groups ="drop")df_median_PS <- df_median_PS %>%mutate(PS_sd =ifelse(is.na(PS_sd), 0, pmin(PS_sd, 2))) ggplot(df_median_PS, aes(x = YEAR, y = PS_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = PS_median - PS_sd, ymax = PS_median + PS_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de PS a lo largo del tiempo",x ="Año", y ="PS (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
# Boxplots por localidades de las variables clave ggplot(dataclimabq_limits, aes(x = LOCALITY, y = T2M)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de T2M por Localidad", x ="Localidad", y ="T2M") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = RH2M)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de RH2M por Localidad", x ="Localidad", y ="RH2M") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = WS10M)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de WS10M por Localidad", x ="Localidad", y ="WS10M") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = WD10M)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de WD10M por Localidad", x ="Localidad", y ="WD10M") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = PS)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de PS por Localidad", x ="Localidad", y ="PS") +theme_minimal()
Análisis de los cambios de variables meteorológicas para el análisis de microclimas a lo largo del tiempo
El gráfico presenta la evolución de diferentes variables meteorológicas en varias regiones (Centro, Sur, Occidente, Oriente y Norte) a lo largo del tiempo. Se analizan las siguientes variables:
T2M (Temperatura a 2 metros)
RH2M (Humedad relativa a 2 metros)
WS10M (Velocidad del viento a 10 metros)
WD10M (Dirección del viento a 10 metros)
PS (Presión atmosférica)
T2M (Temperatura a 2 metros)
Se observa una disminución de la temperatura entre 2020 y 2022, seguida de un aumento progresivo hasta alcanzar su punto más alto en 2024.
En 2025, hay una caída abrupta de la temperatura con una mayor incertidumbre en los valores, especialmente en algunas regiones como el Norte y el Occidente.
La variabilidad en los datos proyectados para 2025 sugiere que se deben monitorear con mayor detalle para confirmar si la tendencia descendente persiste.
RH2M (Humedad relativa a 2 metros)
La humedad relativa muestra una tendencia estable desde 2020 hasta 2024 en la mayoría de las regiones, con ligeras variaciones en algunos años.
En 2025, se evidencia una mayor dispersión, especialmente en el Norte, lo que puede indicar cambios locales en la humedad debido a microclimas particulares.
WS10M (Velocidad del viento a 10 metros)
La velocidad del viento presenta variaciones significativas en el tiempo, con picos en 2021 y 2024.
Se nota un incremento considerable en 2025, con un rango de variabilidad más amplio entre regiones, lo que podría estar asociado a cambios en los patrones de circulación atmosférica o eventos meteorológicos extremos.
Sin embargo, es importante señalar que esta variabilidad podría reducirse con la incorporación de más datos a lo largo del año.
WD10M (Dirección del viento a 10 metros)
La dirección del viento sigue un comportamiento oscilatorio, con descensos en 2021 y 2023, y picos en 2022 y 2024.
En 2025, la variabilidad es notoria, con diferencias considerables entre las regiones.
Este comportamiento sugiere que pueden existir factores locales (topografía, cambios estacionales o patrones climáticos específicos) que afectan la dirección del viento.
PS (Presión atmosférica)
La presión atmosférica se mantiene relativamente estable entre 2020 y 2023, con fluctuaciones menores.
A partir de 2024, se nota un ligero aumento en la dispersión de los datos, lo que indica posibles cambios en la estabilidad atmosférica.
En 2025, se observa un rango más amplio en las mediciones, lo que podría estar relacionado con fenómenos meteorológicos más dinámicos o incertidumbre en las proyecciones.
Histogramas de las Variables Clave
Temperatura a 2 metros (T2M): Se observa una distribución sesgada con valores predominantes en un rango específico, indicando posibles puntos de calor urbano.
Humedad Relativa (RH2M): La distribución muestra alta variabilidad, lo que sugiere diferentes niveles de humedad en distintas zonas.
Velocidad del Viento a 10m (WS10M): Distribución con cola larga, lo que indica eventos de viento extremos en ciertas áreas.
Diagramas de Dispersión y Correlación
Relación entre Temperatura y Humedad: Se aprecia una correlación negativa, lo que confirma que en zonas más cálidas la humedad tiende a disminuir.
Relación entre Radiación Solar y Temperatura: Existe una fuerte correlación positiva, lo que sugiere que la temperatura es influenciada directamente por la cantidad de energía solar recibida.
Code
# ALLSKY_SFC_UV_INDEXdf_median_UV <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(UV_median =median(ALLSKY_SFC_UV_INDEX, na.rm =TRUE),UV_sd =sd(ALLSKY_SFC_UV_INDEX, na.rm =TRUE), .groups ="drop")df_median_UV <- df_median_UV %>%mutate(UV_sd =ifelse(is.na(UV_sd), 0, pmin(UV_sd, 0.5))) ggplot(df_median_UV, aes(x = YEAR, y = UV_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = UV_median - UV_sd, ymax = UV_median + UV_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de ALLSKY_SFC_UV_INDEX a lo largo del tiempo",x ="Año", y ="ALLSKY_SFC_UV_INDEX (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
# ALLSKY_SFC_SW_DIFFdf_median_SW <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(SW_median =median(ALLSKY_SFC_SW_DIFF, na.rm =TRUE),SW_sd =sd(ALLSKY_SFC_SW_DIFF, na.rm =TRUE), .groups ="drop")df_median_SW <- df_median_SW %>%mutate(SW_sd =ifelse(is.na(SW_sd), 0, pmin(SW_sd, 10))) ggplot(df_median_SW, aes(x = YEAR, y = SW_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = SW_median - SW_sd, ymax = SW_median + SW_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de ALLSKY_SFC_SW_DIFF a lo largo del tiempo",x ="Año", y ="ALLSKY_SFC_SW_DIFF (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
# ALLSKY_SRF_ALBdf_median_ALB <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(ALB_median =median(ALLSKY_SRF_ALB, na.rm =TRUE),ALB_sd =sd(ALLSKY_SRF_ALB, na.rm =TRUE), .groups ="drop")df_median_ALB <- df_median_ALB %>%mutate(ALB_sd =ifelse(is.na(ALB_sd), 0, pmin(ALB_sd, 0.05))) ggplot(df_median_ALB, aes(x = YEAR, y = ALB_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = ALB_median - ALB_sd, ymax = ALB_median + ALB_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de ALLSKY_SRF_ALB a lo largo del tiempo",x ="Año", y ="ALLSKY_SRF_ALB (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
# ALLSKY_KTdf_median_KT <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(KT_median =median(ALLSKY_KT, na.rm =TRUE),KT_sd =sd(ALLSKY_KT, na.rm =TRUE), .groups ="drop")df_median_KT <- df_median_KT %>%mutate(KT_sd =ifelse(is.na(KT_sd), 0, pmin(KT_sd, 0.1))) ggplot(df_median_KT, aes(x = YEAR, y = KT_median, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2, position =position_dodge(width =0.2)) +geom_ribbon(aes(ymin = KT_median - KT_sd, ymax = KT_median + KT_sd, fill = LOCALITY), alpha =0.15) +labs(title ="Cambio de la Mediana de ALLSKY_KT a lo largo del tiempo",x ="Año", y ="ALLSKY_KT (Mediana)", color ="Localidad", fill ="Localidad") +theme_minimal() +theme(legend.position ="top")
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SFC_UV_INDEX)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de ALLSKY_SFC_UV_INDEX por Localidad", x ="Localidad", y ="ALLSKY_SFC_UV_INDEX") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SFC_SW_DIFF)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de ALLSKY_SFC_SW_DIFF por Localidad", x ="Localidad", y ="ALLSKY_SFC_SW_DIFF") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SRF_ALB)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de ALLSKY_SRF_ALB por Localidad", x ="Localidad", y ="ALLSKY_SRF_ALB") +theme_minimal()
Code
ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_KT)) +geom_boxplot(fill ="skyblue") +labs(title ="Distribución de ALLSKY_KT por Localidad", x ="Localidad", y ="ALLSKY_KT") +theme_minimal()
Análisis de variables clave para el aprovechamiento de la energía solar:
El gráfico muestra la evolución de diferentes variables meteorológicas que influyen en la captación y eficiencia de la energía solar en distintas regiones (Centro, Sur, Occidente, Oriente y Norte). Las variables analizadas incluyen:
ALLSKY_SFC_UV_INDEX (Índice UV en superficie)
ALLSKY_SFC_SW_DIFF (Radiación solar difusa en superficie)
ALLSKY_SRF_ALB (Albedo superficial bajo cielo total)
ALLSKY_KT (Índice de claridad)
ALLSKY_SFC_UV_INDEX (Índice UV en superficie)
Se observa una tendencia estable entre 2020 y 2022, con un ligero descenso en 2022.
A partir de 2023, hay un aumento pronunciado, alcanzando su punto más alto en 2024.
La región Norte presenta los valores más elevados, lo que sugiere una mayor intensidad de radiación solar en esa zona, factor clave para la eficiencia de paneles solares.
ALLSKY_SFC_SW_DIFF (Radiación solar difusa en superficie)
La radiación solar difusa se mantiene constante en la mayoría de las regiones a lo largo del tiempo.
Sin embargo, el Norte muestra valores significativamente más bajos, lo que indica una mayor predominancia de radiación directa.
Esta información es relevante para decidir entre paneles solares convencionales o tecnologías que aprovechen mejor la radiación difusa, como paneles bifaciales.
ALLSKY_SRF_ALB (Albedo superficial bajo cielo total)
Se nota una ligera disminución del albedo entre 2020 y 2023, seguida de un incremento en 2024.
La región Norte muestra valores notablemente más altos en comparación con las demás regiones, lo que sugiere una mayor reflectividad del suelo.
Un alto albedo puede afectar la eficiencia de los paneles solares al reflejar parte de la radiación en lugar de absorberla.
ALLSKY_KT (Índice de claridad)
Se observa una disminución gradual del índice de claridad entre 2020 y 2022, lo que indica un incremento en la nubosidad o aerosoles en la atmósfera.
Histogramas y Boxplots
Radiación Solar Total (ALLSKY_SFC_SW_DWN): Presenta una distribución bimodal, lo que indica diferencias significativas entre días soleados y nublados.
Albedo Superficial (ALLSKY_SRF_ALB): Se observa una distribución uniforme con valores altos en ciertas áreas, lo que sugiere que algunas superficies reflejan más energía solar de lo esperado.
Mapas de Calor y Correlación
Mapa de calor de correlación: Muestra que la radiación solar tiene una alta correlación con la temperatura y una baja correlación con la velocidad del viento.
Análisis de Dirección del Viento: Se observan patrones que podrían afectar la eficiencia de paneles solares en distintas localidades.
Concluciones generales
1. Microclimas Urbanos y Variabilidad Climática
Se confirma la existencia de islas de calor urbanas, evidenciado por la distribución de temperaturas más altas en zonas densamente pobladas.
La humedad relativa muestra alta variabilidad entre localidades, indicando la influencia de la vegetación y cuerpos de agua en el microclima.
La correlación negativa entre temperatura y humedad refuerza la hipótesis de que el incremento de temperatura disminuye la capacidad del aire para retener humedad.
2. Factores Clave en el Aprovechamiento de la Energía Solar
La radiación solar total presenta patrones bimodales, lo que sugiere diferencias significativas en la disponibilidad de energía solar en función de la nubosidad.
El albedo superficial es elevado en ciertas regiones, lo que indica una mayor reflectividad del suelo, factor que puede afectar la absorción de energía solar.
El análisis de correlaciones muestra que la radiación solar está fuertemente vinculada a la temperatura y apenas influenciada por la velocidad del viento.
3. Implicaciones Prácticas y Recomendaciones
Para mitigar el impacto de islas de calor, se recomienda aumentar la cobertura vegetal y utilizar materiales reflectantes en infraestructuras urbanas.
En términos de aprovechamiento solar, se deben considerar tecnologías de paneles adaptadas a las condiciones locales, priorizando zonas con mayor radiación solar directa.
La planificación energética debe incluir un análisis detallado de patrones de nubosidad y albedo, pues influyen directamente en la eficiencia de los sistemas fotovoltaicos.
Análisis individual de la temperatura promedio por general y por localidad:
Code
# Calcular la temperatura promedio por añoavg_temp_per_year <- dataclimabq_limits %>%group_by(YEAR) %>%summarise(T2M_mean =mean(T2M, na.rm =TRUE))# Graficar la temperatura promedio por añoggplot(avg_temp_per_year, aes(x = YEAR, y = T2M_mean)) +geom_line(color ="blue", size =1) +geom_point(color ="red", size =2) +labs(title ="Temperatura Promedio por Año",x ="Año",y ="Temperatura Promedio (°C)") +theme_minimal()
Code
# Calcular la temperatura promedio anual por localidaddf_avg_temp <- dataclimabq_limits %>%group_by(YEAR, LOCALITY) %>%summarise(T2M_mean =mean(T2M, na.rm =TRUE), .groups ="drop")# Filtrar solo las primeras 6 localidades en caso de que haya máslocalidades_seleccionadas <-unique(df_avg_temp$LOCALITY)[1:6]# Filtrar el dataset con las localidades seleccionadasdf_avg_temp <- df_avg_temp %>%filter(LOCALITY %in% localidades_seleccionadas)# Graficar la temperatura promedio por localidad con facetasggplot(df_avg_temp, aes(x = YEAR, y = T2M_mean, color = LOCALITY, group = LOCALITY)) +geom_line(size =1) +geom_point(size =2) +# Solo los puntos del promedio anualfacet_wrap(~ LOCALITY, scales ="free_y") +# Divide en subgráficos por localidadlabs(title ="Cambio de Temperatura Promedio Anual por Localidad",x ="Año",y ="Temperatura Promedio (°C)") +theme_minimal() +theme(legend.position ="none", strip.text =element_text(size =12)) # Oculta la leyenda ya que está en los títulos de los facetas
Análisis de Temperatura a lo Largo del Tiempo
Podemos observar que se muestra un patrón similar en los diferentes barrios, lo cual se debe a que se promedia la temperatura total por año. Hay varios puntos interesantes a destacar:
A partir del 2020, la temperatura comenzó a decrecer de manera constante hasta alcanzar un mínimo histórico dentro del rango de tiempo analizado.
Sin embargo, desde el 2022, la temperatura experimenta un aumento exponencial hasta el 2024, alcanzando su punto más alto.
Posteriormente, los valores vuelven a niveles similares a los registrados en 2020, lo que sugiere una posible estabilización o un ciclo climático recurrente.
Ya en el grafico que promedia la temperatura total entre todas las localidades por año se ve una tendencia de similar pero los valores son más altos.
Source Code
---title: "Microclimas urbanos en Barranquilla: Análisis de la variabilidad meteorológica según la localidad" author: "Sebastián Pérez Albor, Eliana Rodriguez Martinez"date: "2025-02-17"toc: trueformat: html: html-math-method: katex code-tools: true self-contained: true code-fold: true # Permite plegar o desplegar códigoexecute: warning: false---```{r setup, include=FALSE}# Configuración global para los chunks de códigoknitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)```En las últimas décadas, el crecimiento acelerado de las áreas urbanas ha generado cambios significativos en los patrones climáticos locales, dando lugar a la formación de microclimas urbanos. Estos microclimas se caracterizan por variaciones en la temperatura, humedad, velocidad del viento y otros factores meteorológicos, que difieren de las condiciones climáticas de las áreas rurales circundantes. Comprender y clasificar estos microclimas es crucial para la planificación urbana, la gestión de recursos energéticos y la mejora de la calidad de vida de los habitantes.Además, en un contexto global de transición hacia fuentes de energía renovable, la energía solar se ha posicionado como una de las alternativas más prometedoras. Sin embargo, la eficiencia de los sistemas de captación de energía solar depende en gran medida de las condiciones meteorológicas locales, como la radiación solar, la nubosidad y la temperatura. Por lo tanto, predecir con precisión el potencial de energía solar en diferentes áreas urbanas es fundamental para optimizar la instalación de paneles solares y maximizar su rendimiento.# Paquetes y librerias necesarias```{r libraries}# Carga de paquetes necesarios# 📊 Manejo y visualización de datoslibrary(tidyverse) # Incluye ggplot2, dplyr, tidyr, readr, tibble, stringr, forcats, purrrlibrary(ggpubr) # Gráficos mejorados con ggplot2library(patchwork) # Para combinar múltiples gráficoslibrary(ggcorrplot) # Para gráficos de correlaciónlibrary(ggplot2) # (ya incluido en tidyverse, pero puedes mantenerlo si usas versiones específicas)library(viridis) # Mejor paleta de colores para gráficos# 📋 Manejo de datos y transformaciónlibrary(Hmisc) # Funciones avanzadas de estadísticalibrary(knitr) # Para formatear tablas en R Markdownlibrary(DT) # Para tablas interactivaslibrary(pander) # Para formateo de reporteslibrary(reshape2) # Para manipulación de datos en formato largo/ancho# 📈 Estadística y análisis de datoslibrary(nortest) # Pruebas de normalidadlibrary(naniar) # Visualización y manejo de datos faltanteslibrary(EnvStats) # Métodos avanzados de análisis ambiental# 📦 Utilidades adicionaleslibrary(gridExtra) # Para organizar gráficos en cuadrículas```# Importación de datos ```{r importación Datos}dataclimabq <- read_csv("C:/Users/sebas/OneDrive/Escritorio/Clases/2025-10/DataViz/dataclimabq.csv")```### **Glosario de Variables Climáticas y Meteorológicas**Este glosario describe las variables utilizadas en el análisis de microclimas y aprovechamiento de energía solar.#### **Variables Atmosféricas y Meteorológicas**- **T2M:** MERRA-2 Temperatura a 2 Metros (°C). - Indica la temperatura del aire a una altura de 2 metros sobre la superficie.- **RH2M:** MERRA-2 Humedad Relativa a 2 Metros (%). - Mide la cantidad de humedad en el aire en relación con la máxima posible a esa temperatura.- **PRECTOTCORR:** MERRA-2 Precipitación Corregida (mm/hora). - Representa la tasa de precipitación (lluvia, nieve) ajustada según correcciones satelitales.- **WS10M:** MERRA-2 Velocidad del Viento a 10 Metros (m/s). - Velocidad del viento medida a una altura de 10 metros sobre la superficie.- **WD10M:** MERRA-2 Dirección del Viento a 10 Metros (Grados). - Indica la dirección desde la que sopla el viento, en grados (0° = Norte, 90° = Este, etc.).- **PS:** MERRA-2 Presión Superficial (kPa). - Mide la presión atmosférica en la superficie terrestre.#### **Variables Relacionadas con la Energía Solar**- **ALLSKY_SFC_UV_INDEX:** CERES SYN1deg Índice UV en Superficie Bajo Cielo Total (W m⁻² × 40). - Mide la intensidad de la radiación ultravioleta en la superficie terrestre.- **ALLSKY_SFC_SW_DIFF:** CERES SYN1deg Irradiancia Difusa de Onda Corta en Superficie Bajo Cielo Total (Wh/m²). - Cantidad de energía solar dispersada en la atmósfera que llega a la superficie terrestre.- **ALLSKY_SRF_ALB:** CERES SYN1deg Albedo Superficial Bajo Cielo Total (adimensional). - Fracción de la radiación solar reflejada por la superficie terrestre respecto a la radiación recibida.- **ALLSKY_KT:** CERES SYN1deg Índice de Claridad de Insolación Bajo Cielo Total (adimensional). - Relación entre la irradiancia solar real y la irradiancia solar máxima teórica en ausencia de atmósfera.#### **Variables Adicionales**- **T2MDEW:** MERRA-2 Punto de Rocío/Escarcha a 2 Metros (°C). - Temperatura a la cual el aire debe enfriarse para que el vapor de agua se condense en forma de rocío.- **T2MWET:** MERRA-2 Temperatura de Bulbo Húmedo a 2 Metros (°C). - Mide la temperatura mínima alcanzable por evaporación de agua en condiciones de enfriamiento adiabático.- **WS50M:** MERRA-2 Velocidad del Viento a 50 Metros (m/s). - Velocidad del viento medida a 50 metros de altura, relevante para el aprovechamiento eólico.#### **Variables Geográficas**- **Loacality:** Localidad donde se tomaron los datos. - **NHBD:** Neighborhood, barrio donde se registraron las mediciones. Este glosario permite una mejor comprensión de los datos utilizados en el análisis de microclimas y potencial de energía solar.### **Objetivos:**- **Impacto en la planificación urbana:** La clasificación de microclimas permite identificar áreas con condiciones climáticas extremas (como islas de calor urbanas) y proponer medidas de mitigación, como la creación de espacios verdes o la implementación de techos reflectantes.- **Optimización de energía renovable:** La predicción de energía solar potencial es esencial para diseñar sistemas de energía solar más eficientes y reducir la dependencia de combustibles fósiles.- **Contribución científica:** Este proyecto utiliza datos de alta resolución de fuentes como MERRA-2 y CERES SYN1deg, lo que permite un análisis detallado y preciso de las variables meteorológicas. Los resultados están pensados para ser publicados y servir como base para futuras investigaciones.## Datos ```{r vista datos}# Vista de los datosdatatable( dataclimabq[1:100, ], caption = "Data Frame: dataclimabq", options = list( scrollX = TRUE, scrollY = "450px" ))``````{r}str(dataclimabq)```## Datos nulos por columna```{r datos nulos}# Contar valores nulos en cada columnacolSums(is.na(dataclimabq))``````{r}# Contar la cantidad de valores -999 en cada columnacount_neg_999 <-colSums(dataclimabq ==-999)# Imprimir resultadoscat("\nCount of -999 values in each column:\n")print(count_neg_999)```En el análisis de datos tipo meteorológicos y climáticos, es común encontrar **valores faltantes** que no pueden ser calculados o que están fuera del rango de disponibilidad de las fuentes. Estos valores en este caso han sido representados con un código específico, como **-999**, para indicar su ausencia. En este contexto, se trabajó con un conjunto de <span style="color:skyblue;">**(1)Variables**</span>. Estos mismos, provenientes de fuentes como **MERRA-2** y **CERES SYN1deg**, son fundamentales para estudios climáticos, pero requieren un manejo cuidadoso de los **valores faltantes** para garantizar la precisión y confiabilidad de los análisis.## Limpieza de datos```{r limpieza_datos, echo=TRUE}# Seleccionar solo las columnas numéricasnumeric_cols <- sapply(dataclimabq, is.numeric)# Crear una copia del dataframe originaldataclimabq_cleaned <- dataclimabq# Reemplazar -999.0 por NA solo en columnas numéricasdataclimabq_cleaned[numeric_cols] <- lapply(dataclimabq_cleaned[numeric_cols], function(x) replace(x, x == -999.0, NA))# Calcular el porcentaje de datos faltantes por columnamissing_per_col <- colSums(is.na(dataclimabq_cleaned)) / nrow(dataclimabq_cleaned) * 100# Calcular el porcentaje total de datos faltantestotal_missing <- sum(is.na(dataclimabq_cleaned))total_values <- prod(dim(dataclimabq_cleaned))missing_percentage <- (total_missing / total_values) * 100``````{r Graficos datos nulos 1}suppressWarnings(require(Amelia))missmap(dataclimabq_cleaned, col = c("#fde725","#440154" ))``````{r Graficos datos nulos 2}gg_miss_var(dataclimabq_cleaned, show_pct = TRUE) + geom_hline(yintercept = 50, linetype = "dashed", color = "black") + labs(title = "Cantidad de NA por columna") + theme_minimal()``````{r Resultado}# Imprimir resultadoscat("Porcentaje de datos faltantes por variable:\n")print(missing_per_col)cat("\nPorcentaje total de datos faltantes:", round(missing_percentage, 2), "%\n")```Pero este porcentaje varía considerablemente entre las variables. Las variables con mayor porcentaje de datos faltantes son:Variable Porcentaje de Datos Faltantes- **ALLSKY_SFC_UV_INDEX** 8.49%- **ALLSKY_SRF_ALB** 23.77%- **ALLSKY_SFC_SW_DIFF** 37.73%- **ALLSKY_KT** 53.03%Estos valores faltantes están representados con el valor -999, que indica que los datos no pudieron calcularse o están fuera del rango de disponibilidad de las fuentes.Los porcentajes anteriormente mostrados se pueden visualizar de una mejor manera en las graficas anteriores:## Análisis de Correlación ```{r correlation}numeric_data <- dataclimabq_cleaned[sapply(dataclimabq_cleaned, is.numeric)]# Calcular la matriz de correlacióncorr_matrix <- cor(numeric_data, use = "pairwise.complete.obs")# Crear el heatmap sin números en las celdas y sin coord_fixed()ggcorrplot(corr_matrix, method = "square", type = "lower", # Mostrar solo la mitad inferior lab = FALSE, # Eliminar los números dentro de las celdas colors = c("blue", "white", "red"), title = "Matriz de Correlación de Variables Numéricas", ggtheme = theme_minimal()) + theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 10), # Rotar etiquetas para mejor legibilidad axis.text.y = element_text(size = 10))```#### **Análisis de Correlación entre Variables Climáticas** Este análisis busca entender las relaciones entre distintas variables climáticas para apoyar la planificación urbana y la optimización de energía renovable. #### **Puntos clave del análisis de correlación:** ##### 1️. Temperatura y Radiación Solar - **T2M (Temperatura a 2m) y ALLSKY_SFC_SW_DIFF (Irradiancia de onda corta difusa)** tienen una fuerte correlación positiva (**~0.73**). - Esto indica que temperaturas más altas suelen estar asociadas con una mayor irradiancia solar difusa, lo que es clave para modelos de **energía solar**. ##### 2️. Humedad y Precipitación - **RH2M (Humedad relativa a 2m) y PRECTOTCORR (Precipitación corregida)** presentan una correlación negativa moderada (**~ -0.76**). - A mayor precipitación, la humedad relativa disminuye, lo cual puede indicar **cambios abruptos en el clima urbano**. ##### 3️. Viento y Altura - **WS10M (Viento a 10m) y WS50M (Viento a 50m) tienen una correlación de casi 0.99.** - Esto sugiere que la velocidad del viento a distintas alturas está altamente relacionada, lo que es útil para evaluar **viabilidad de proyectos eólicos**. ##### 4️. Presión Superficial y Radiación Solar - **ALLSKY_SFC_UV_INDEX (Índice UV) y PS (Presión superficial)** tienen correlación negativa (**~ -0.25**). - Puede indicar que a mayor presión, la radiación UV en la superficie tiende a disminuir, lo que podría afectar la **eficiencia de paneles solares**, no obstante la relación entre ambas variables es bastante debil. ## Distribución de Variables```{r Boxplots }dataclimabq_long <- melt(dataclimabq_cleaned)dataclimabq_long <- na.omit(dataclimabq_long)# Crear boxplotggplot(dataclimabq_long, aes(x = factor(1), y = value, fill = variable)) + geom_boxplot(outlier.colour = "red", outlier.shape = 8, outlier.size = 3) + facet_wrap(~ variable, scales = "free_y") + labs(x = "Variables", y = "Valores", title = "Distribución de Variables en dataclimabq") + theme_minimal() + theme(axis.text.x = element_blank(), strip.text = element_text(size = 12), axis.text.y = element_text(size = 10), legend.position = "none") + scale_fill_viridis_d(option = "plasma") # Paleta de colores para más de 12 variables``````{r summary datos cleaned}pander(summary(dataclimabq_cleaned))```##Se detectan datos NA'S teniendo en cuenta el rango lógico de valores en los que deberían estar las variables numéricas```{r limits}# Crear una copia del dataframe limpio anteriordataclimabq_limits <- dataclimabq_cleaned# Definir los límites lógicos para cada variable en una listalimits <- list( YEAR = c(2020, 2025), MO = c(1, 12), DY = c(1, 31), HR = c(0, 23), T2M = c(-90, 60), RH2M = c(0, 100), PRECTOTCORR = c(0, 300), WS10M = c(0, 80), WD10M = c(0, 360), PS = c(50, 110), ALLSKY_SFC_UV_INDEX = c(0, 15), ALLSKY_SFC_SW_DIFF = c(0, 1500), ALLSKY_SRF_ALB = c(0, 1), T2MDEW = c(-45, 35), T2MWET = c(-35, 35), WS50M = c(0, 75), ALLSKY_KT = c(0, 1))# Reemplazar valores fuera de los límites por NAfor (col in names(limits)) { min_val <- limits[[col]][1] max_val <- limits[[col]][2] dataclimabq_limits[[col]] <- ifelse(dataclimabq_limits[[col]] < min_val | dataclimabq_limits[[col]] > max_val, NA, dataclimabq_limits[[col]])}``````{r summary datos cleaned limits}pander(summary(dataclimabq_limits))``````{r localidades}# Obtener las localidades únicaslocalidades <- unique(dataclimabq_cleaned$LOCALITY)# Imprimir resultadoscat("Localidades únicas:\n")print(localidades)``````{r Boxplots limits}dataclimabq_long <- melt(dataclimabq_limits)dataclimabq_long <- na.omit(dataclimabq_long)# Crear boxplotggplot(dataclimabq_long, aes(x = factor(1), y = value, fill = variable)) + geom_boxplot(outlier.colour = "red", outlier.shape = 8, outlier.size = 3) + facet_wrap(~ variable, scales = "free_y") + labs(x = "Variables", y = "Valores", title = "Distribución de Variables en dataclimabq_limit") + theme_minimal() + theme(axis.text.x = element_blank(), strip.text = element_text(size = 12), axis.text.y = element_text(size = 10), legend.position = "none") + scale_fill_viridis_d(option = "plasma") # Paleta de colores para más de 12 variables```Debido a que la falta de datos en las variables ALLSKY_SRF_ALB y ALLSKY_KT procederemos a analizar la correlación entre los datos y ver alternativas para el tratamiento de los datos faltantes más allá de los comunes, como lo son el reemplazo por la media, la mediana o el descarte completo de los datos.```{r Distribución de datos por localidad}library(ggplot2)library(ggpubr) library(dplyr)# Definir número máximo de variables a graficar por iteraciónmax_plots <- 6 # Ajusta este valor según tu necesidad# Variables numéricasnumeric_cols <- names(select_if(dataclimabq_limits, is.numeric))# Graficar histogramas y QQ plots por localidadfor (localidad in unique(dataclimabq_limits$LOCALITY)[1:3]) { # Limita a las primeras 3 localidades para evitar demoras df_localidad <- filter(dataclimabq_limits, LOCALITY == localidad) # Seleccionar un subconjunto de variables si hay demasiadas vars_to_plot <- head(numeric_cols, max_plots) p1 <- ggplot(df_localidad %>% select(all_of(vars_to_plot)) %>% pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor"), aes(x = Valor)) + geom_histogram(aes(y = ..density..), bins = 30, fill = "blue", alpha = 0.5) + geom_density(color = "red", size = 1) + facet_wrap(~Variable, scales = "free_x") + labs(title = paste("Histogramas en", localidad)) + theme_minimal() p2 <- ggplot(df_localidad %>% select(all_of(vars_to_plot)) %>% pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor"), aes(sample = Valor)) + stat_qq() + stat_qq_line(color = "red") + facet_wrap(~Variable, scales = "free") + labs(title = paste("QQ Plots en", localidad)) + theme_minimal() print(p1) print(p2)}# Variables categóricascategorical_cols <- names(select_if(dataclimabq_limits, is.character))for (localidad in unique(dataclimabq_limits$LOCALITY)[1:3]) { # Solo primeras 3 localidades para evitar demora df_localidad <- filter(dataclimabq_limits, LOCALITY == localidad) p_cat <- ggplot(df_localidad %>% pivot_longer(cols = all_of(categorical_cols), names_to = "Variable", values_to = "Valor"), aes(x = Valor)) + geom_bar(fill = "skyblue") + facet_wrap(~Variable, scales = "free_x") + labs(title = paste("Histogramas de variables categóricas en", localidad), x = "Categoría", y = "Frecuencia") + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) print(p_cat)}``````{r Shapiro-Wilk y Chi-cuadrado}# Test de Shapiro-Wilk (con muestreo si hay más de 5000 datos)numeric_cols <- names(select_if(dataclimabq_limits, is.numeric))normality_results <- data.frame(Variable = character(), Statistic = numeric(), P_value = numeric())for (col in numeric_cols) { data <- na.omit(dataclimabq_limits[[col]]) if (length(data) > 5000) { data <- sample(data, 5000) # Tomar solo 5000 valores aleatorios } if (length(data) >= 3) { # Verificar que haya suficientes datos shapiro_test <- shapiro.test(data) normality_results <- rbind(normality_results, data.frame(Variable = col, Statistic = shapiro_test$statistic, P_value = shapiro_test$p.value)) }}print(normality_results)# Test de Chi-cuadrado para variables categóricas vs. LOCALITYcategorical_cols <- names(select_if(dataclimabq_limits, is.character))chi2_results <- data.frame(Variable = character(), Chi2 = numeric(), P_value = numeric(), DOF = numeric())for (col in categorical_cols) { contingency_table <- table(dataclimabq_limits$LOCALITY, dataclimabq_limits[[col]]) if (min(contingency_table) > 0) { # Evitar errores por celdas vacías chi_test <- chisq.test(contingency_table) chi2_results <- rbind(chi2_results, data.frame(Variable = col, Chi2 = chi_test$statistic, P_value = chi_test$p.value, DOF = chi_test$parameter)) }}print(chi2_results)```### **Análisis de Normalidad y Distribución de Variables**El test de normalidad proporciona un valor estadístico y un **p-valor**. Si el **p-valor** es menor a 0.05, significa que rechazamos la hipótesis nula de que la variable sigue una distribución normal. ---### **Resultados Clave:**##### **Variables con mejor ajuste a la normalidad** (mayores estadísticas y p-valores más altos, pero aún no completamente normales):- **T2M** (Temperatura a 2 metros): $ p = 7.63 \times 10^{-107} $- **T2MDEW** (Punto de rocío a 2 metros): $ p = 6.92 \times 10^{-107} $- **T2MWET** (Temperatura húmeda a 2 metros): $ p = 1.67 \times 10^{-90} $- **WS10M** (Viento a 10 metros): $ p = 4.65 \times 10^{-97} $- **WS50M** (Viento a 50 metros): $ p = 1.74 \times 10^{-94} $Estas variables están relativamente cerca de una normalidad aceptable, aunque siguen mostrando desviaciones.##### **Variables que NO siguen una distribución normal** (p-valores extremadamente pequeños, estadística baja):- **WD10M** (Dirección del viento a 10m): $ p = 8.73 \times 10^{-211} $ (muy no normal)- **ALLSKY_SFC_SW_DIFF** (Radiación solar difusa): $ p = 1.65 \times 10^{-222} $- **ALLSKY_SRF_ALB** (Albedo superficial): $ p = 3.45 \times 10^{-220} $- **RH2M** (Humedad relativa a 2m): $ p = 5.41 \times 10^{-197} $- **PRECTOTCORR** (Precipitación corregida): $ p = 5.14 \times 10^{-188} $- **ALLSKY_SFC_UV_INDEX** (Índice UV): $ p = 2.21 \times 10^{-202} $- **ALLSKY_KT** (Transmisión atmosférica): $ p = 2.50 \times 10^{-179} $Estas variables muestran una distribución altamente sesgada o multimodal, lo que indica que no siguen una normalidad en absoluto.##### **Variables de tiempo (año, mes, día, hora)**- **YEAR**: $ p = 1.91 \times 10^{-162} $- **MO**: $ p = 8.82 \times 10^{-142} $- **DY**: $ p = 2.42 \times 10^{-134} $- **HR**: $ p = 2.95 \times 10^{-136} $Estas variables tienen p-valores extremadamente pequeños, indicando que su distribución no es normal (lo cual era esperable porque el tiempo no suele distribuirse normalmente).---### **Análisis de Variables Categóricas** El test de **Chi-cuadrado** analiza si la distribución de categorías en "LOCALITY" y "NBHD" es uniforme o tiene patrones significativos. - **LOCALITY** ($\chi^2 = 6,142,076, p = 0.0$) - Indica una distribución altamente no uniforme de las localidades. - **NBHD** ($\chi^2 = 4,167,836, p = 0.0$)** - También muestra que la distribución de barrios no es uniforme en absoluto.Esto sugiere que algunos barrios/localidades tienen una concentración mucho mayor de registros que otros.---### **Conclusiones**- **Ninguna variable numérica sigue una distribución normal**. Algunas se acercan (T2M, T2MDEW, T2MWET), pero siguen sin cumplir el criterio de normalidad.- **Muchas variables climáticas tienen distribuciones sesgadas o multimodales** (especialmente precipitación, humedad y radiación solar).- **Las variables categóricas muestran una distribución no uniforme**, lo que sugiere que ciertos barrios/localidades tienen más representación en los datos.```{r Tratamiento de datos faltantes}# Reemplazar valores NA con la mediana de la variable por localidaddataclimabq_limits <- dataclimabq_limits %>% group_by(LOCALITY) %>% mutate(across(where(is.numeric), ~ifelse(is.na(.), median(., na.rm = TRUE), .)))# Verificar si quedan valores NAcolSums(is.na(dataclimabq_limits))```### **Análisis visual post limpieza:**#### **Análisis visual de Variables implicadas en el problema de microclimas**```{r Series de tiempo localidades 1 T2M,RH2M,WS10M,WD10M, PS }df_median <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(T2M_median = median(T2M, na.rm = TRUE), T2M_sd = sd(T2M, na.rm = TRUE), .groups = "drop")# Limitar la escala de la desviación estándar para evitar bandas demasiado ampliasdf_median <- df_median %>% mutate(T2M_sd = ifelse(is.na(T2M_sd), 0, pmin(T2M_sd, 0.5))) # Evitar NA y controlar valores altos# Gráfico con mejoras para evitar solapamientoggplot(df_median, aes(x = YEAR, y = T2M_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + # Evitar superposición de puntos geom_ribbon(aes(ymin = T2M_median - T2M_sd, ymax = T2M_median + T2M_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de T2M a lo largo del tiempo", x = "Año", y = "T2M (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")df_median_RH2M <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(RH2M_median = median(RH2M, na.rm = TRUE), RH2M_sd = sd(RH2M, na.rm = TRUE), .groups = "drop")df_median_RH2M <- df_median_RH2M %>% mutate(RH2M_sd = ifelse(is.na(RH2M_sd), 0, pmin(RH2M_sd, 5))) ggplot(df_median_RH2M, aes(x = YEAR, y = RH2M_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = RH2M_median - RH2M_sd, ymax = RH2M_median + RH2M_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de RH2M a lo largo del tiempo", x = "Año", y = "RH2M (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")df_median_WS10M <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(WS10M_median = median(WS10M, na.rm = TRUE), WS10M_sd = sd(WS10M, na.rm = TRUE), .groups = "drop")df_median_WS10M <- df_median_WS10M %>% mutate(WS10M_sd = ifelse(is.na(WS10M_sd), 0, pmin(WS10M_sd, 1))) ggplot(df_median_WS10M, aes(x = YEAR, y = WS10M_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = WS10M_median - WS10M_sd, ymax = WS10M_median + WS10M_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de WS10M a lo largo del tiempo", x = "Año", y = "WS10M (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")df_median_WD10M <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(WD10M_median = median(WD10M, na.rm = TRUE), WD10M_sd = sd(WD10M, na.rm = TRUE), .groups = "drop")df_median_WD10M <- df_median_WD10M %>% mutate(WD10M_sd = ifelse(is.na(WD10M_sd), 0, pmin(WD10M_sd, 10))) ggplot(df_median_WD10M, aes(x = YEAR, y = WD10M_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = WD10M_median - WD10M_sd, ymax = WD10M_median + WD10M_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de WD10M a lo largo del tiempo", x = "Año", y = "WD10M (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")df_median_PS <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(PS_median = median(PS, na.rm = TRUE), PS_sd = sd(PS, na.rm = TRUE), .groups = "drop")df_median_PS <- df_median_PS %>% mutate(PS_sd = ifelse(is.na(PS_sd), 0, pmin(PS_sd, 2))) ggplot(df_median_PS, aes(x = YEAR, y = PS_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = PS_median - PS_sd, ymax = PS_median + PS_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de PS a lo largo del tiempo", x = "Año", y = "PS (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")``````{r Boxplots por localidad 1 T2M,RH2M,WS10M,WD10M, PS}# Boxplots por localidades de las variables clave ggplot(dataclimabq_limits, aes(x = LOCALITY, y = T2M)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de T2M por Localidad", x = "Localidad", y = "T2M") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = RH2M)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de RH2M por Localidad", x = "Localidad", y = "RH2M") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = WS10M)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de WS10M por Localidad", x = "Localidad", y = "WS10M") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = WD10M)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de WD10M por Localidad", x = "Localidad", y = "WD10M") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = PS)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de PS por Localidad", x = "Localidad", y = "PS") + theme_minimal()``````{r Correlación por localidad 1 T2M,RH2M,WS10M,WD10M, PS}library(corrplot)# Centrodf_centro <- subset(dataclimabq_limits, LOCALITY == "Centro", select = c("T2M", "RH2M", "WS10M", "WD10M", "PS"))df_centro[] <- lapply(df_centro, as.numeric)corr_matrix_centro <- cor(df_centro, use = "pairwise.complete.obs")corrplot(corr_matrix_centro, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Centro")# Surdf_sur <- subset(dataclimabq_limits, LOCALITY == "Sur", select = c("T2M", "RH2M", "WS10M", "WD10M", "PS"))df_sur[] <- lapply(df_sur, as.numeric)corr_matrix_sur <- cor(df_sur, use = "pairwise.complete.obs")corrplot(corr_matrix_sur, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Sur")# Occidentedf_occidente <- subset(dataclimabq_limits, LOCALITY == "Occidente", select = c("T2M", "RH2M", "WS10M", "WD10M", "PS"))df_occidente[] <- lapply(df_occidente, as.numeric)corr_matrix_occidente <- cor(df_occidente, use = "pairwise.complete.obs")corrplot(corr_matrix_occidente, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Occidente")# Orientedf_oriente <- subset(dataclimabq_limits, LOCALITY == "Oriente", select = c("T2M", "RH2M", "WS10M", "WD10M", "PS"))df_oriente[] <- lapply(df_oriente, as.numeric)corr_matrix_oriente <- cor(df_oriente, use = "pairwise.complete.obs")corrplot(corr_matrix_oriente, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Oriente")# Nortedf_norte <- subset(dataclimabq_limits, LOCALITY == "Norte", select = c("T2M", "RH2M", "WS10M", "WD10M", "PS"))df_norte[] <- lapply(df_norte, as.numeric)corr_matrix_norte <- cor(df_norte, use = "pairwise.complete.obs")corrplot(corr_matrix_norte, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Norte")```#### **Análisis de los cambios de variables meteorológicas para el análisis de microclimas a lo largo del tiempo**El gráfico presenta la evolución de diferentes variables meteorológicas en varias regiones (Centro, Sur, Occidente, Oriente y Norte) a lo largo del tiempo. Se analizan las siguientes variables:- **T2M** (Temperatura a 2 metros)- **RH2M** (Humedad relativa a 2 metros)- **WS10M** (Velocidad del viento a 10 metros)- **WD10M** (Dirección del viento a 10 metros)- **PS** (Presión atmosférica)---##### **T2M (Temperatura a 2 metros)**- Se observa una disminución de la temperatura entre 2020 y 2022, seguida de un aumento progresivo hasta alcanzar su punto más alto en 2024.- En 2025, hay una caída abrupta de la temperatura con una mayor incertidumbre en los valores, especialmente en algunas regiones como el Norte y el Occidente.- La variabilidad en los datos proyectados para 2025 sugiere que se deben monitorear con mayor detalle para confirmar si la tendencia descendente persiste.---##### **RH2M (Humedad relativa a 2 metros)**- La humedad relativa muestra una tendencia estable desde 2020 hasta 2024 en la mayoría de las regiones, con ligeras variaciones en algunos años.- En 2025, se evidencia una mayor dispersión, especialmente en el Norte, lo que puede indicar cambios locales en la humedad debido a microclimas particulares.---##### **WS10M (Velocidad del viento a 10 metros)**- La velocidad del viento presenta variaciones significativas en el tiempo, con picos en 2021 y 2024.- Se nota un incremento considerable en 2025, con un rango de variabilidad más amplio entre regiones, lo que podría estar asociado a cambios en los patrones de circulación atmosférica o eventos meteorológicos extremos.- Sin embargo, es importante señalar que esta variabilidad podría reducirse con la incorporación de más datos a lo largo del año.---##### **WD10M (Dirección del viento a 10 metros)**- La dirección del viento sigue un comportamiento oscilatorio, con descensos en 2021 y 2023, y picos en 2022 y 2024.- En 2025, la variabilidad es notoria, con diferencias considerables entre las regiones.- Este comportamiento sugiere que pueden existir factores locales (topografía, cambios estacionales o patrones climáticos específicos) que afectan la dirección del viento.---##### **PS (Presión atmosférica)**- La presión atmosférica se mantiene relativamente estable entre 2020 y 2023, con fluctuaciones menores.- A partir de 2024, se nota un ligero aumento en la dispersión de los datos, lo que indica posibles cambios en la estabilidad atmosférica.- En 2025, se observa un rango más amplio en las mediciones, lo que podría estar relacionado con fenómenos meteorológicos más dinámicos o incertidumbre en las proyecciones.---#### **Histogramas de las Variables Clave**- **Temperatura a 2 metros (T2M):** Se observa una distribución sesgada con valores predominantes en un rango específico, indicando posibles puntos de calor urbano.- **Humedad Relativa (RH2M):** La distribución muestra alta variabilidad, lo que sugiere diferentes niveles de humedad en distintas zonas.- **Velocidad del Viento a 10m (WS10M):** Distribución con cola larga, lo que indica eventos de viento extremos en ciertas áreas.#### **Diagramas de Dispersión y Correlación**- **Relación entre Temperatura y Humedad:** Se aprecia una correlación negativa, lo que confirma que en zonas más cálidas la humedad tiende a disminuir.- **Relación entre Radiación Solar y Temperatura:** Existe una fuerte correlación positiva, lo que sugiere que la temperatura es influenciada directamente por la cantidad de energía solar recibida.```{r Series de tiempo localidades 2 ALLSKY_SFC_UV_INDEX, ALLSKY_SFC_SW_DIFF, ALLSKY_SRF_ALB ALLSKY_KT}# ALLSKY_SFC_UV_INDEXdf_median_UV <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(UV_median = median(ALLSKY_SFC_UV_INDEX, na.rm = TRUE), UV_sd = sd(ALLSKY_SFC_UV_INDEX, na.rm = TRUE), .groups = "drop")df_median_UV <- df_median_UV %>% mutate(UV_sd = ifelse(is.na(UV_sd), 0, pmin(UV_sd, 0.5))) ggplot(df_median_UV, aes(x = YEAR, y = UV_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = UV_median - UV_sd, ymax = UV_median + UV_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de ALLSKY_SFC_UV_INDEX a lo largo del tiempo", x = "Año", y = "ALLSKY_SFC_UV_INDEX (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")# ALLSKY_SFC_SW_DIFFdf_median_SW <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(SW_median = median(ALLSKY_SFC_SW_DIFF, na.rm = TRUE), SW_sd = sd(ALLSKY_SFC_SW_DIFF, na.rm = TRUE), .groups = "drop")df_median_SW <- df_median_SW %>% mutate(SW_sd = ifelse(is.na(SW_sd), 0, pmin(SW_sd, 10))) ggplot(df_median_SW, aes(x = YEAR, y = SW_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = SW_median - SW_sd, ymax = SW_median + SW_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de ALLSKY_SFC_SW_DIFF a lo largo del tiempo", x = "Año", y = "ALLSKY_SFC_SW_DIFF (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")# ALLSKY_SRF_ALBdf_median_ALB <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(ALB_median = median(ALLSKY_SRF_ALB, na.rm = TRUE), ALB_sd = sd(ALLSKY_SRF_ALB, na.rm = TRUE), .groups = "drop")df_median_ALB <- df_median_ALB %>% mutate(ALB_sd = ifelse(is.na(ALB_sd), 0, pmin(ALB_sd, 0.05))) ggplot(df_median_ALB, aes(x = YEAR, y = ALB_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = ALB_median - ALB_sd, ymax = ALB_median + ALB_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de ALLSKY_SRF_ALB a lo largo del tiempo", x = "Año", y = "ALLSKY_SRF_ALB (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")# ALLSKY_KTdf_median_KT <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(KT_median = median(ALLSKY_KT, na.rm = TRUE), KT_sd = sd(ALLSKY_KT, na.rm = TRUE), .groups = "drop")df_median_KT <- df_median_KT %>% mutate(KT_sd = ifelse(is.na(KT_sd), 0, pmin(KT_sd, 0.1))) ggplot(df_median_KT, aes(x = YEAR, y = KT_median, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2, position = position_dodge(width = 0.2)) + geom_ribbon(aes(ymin = KT_median - KT_sd, ymax = KT_median + KT_sd, fill = LOCALITY), alpha = 0.15) + labs(title = "Cambio de la Mediana de ALLSKY_KT a lo largo del tiempo", x = "Año", y = "ALLSKY_KT (Mediana)", color = "Localidad", fill = "Localidad") + theme_minimal() + theme(legend.position = "top")``````{r Boxplots por localidad 2 ALLSKY_SFC_UV_INDEX, ALLSKY_SFC_SW_DIFF, ALLSKY_SRF_ALB ALLSKY_KT}ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SFC_UV_INDEX)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de ALLSKY_SFC_UV_INDEX por Localidad", x = "Localidad", y = "ALLSKY_SFC_UV_INDEX") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SFC_SW_DIFF)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de ALLSKY_SFC_SW_DIFF por Localidad", x = "Localidad", y = "ALLSKY_SFC_SW_DIFF") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_SRF_ALB)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de ALLSKY_SRF_ALB por Localidad", x = "Localidad", y = "ALLSKY_SRF_ALB") + theme_minimal()ggplot(dataclimabq_limits, aes(x = LOCALITY, y = ALLSKY_KT)) + geom_boxplot(fill = "skyblue") + labs(title = "Distribución de ALLSKY_KT por Localidad", x = "Localidad", y = "ALLSKY_KT") + theme_minimal()``````{r Correlación por localidad 2 ALLSKY_SFC_UV_INDEX, ALLSKY_SFC_SW_DIFF, ALLSKY_SRF_ALB ALLSKY_KT}library(corrplot)# Centrodf_centro <- subset(dataclimabq_limits, LOCALITY == "Centro", select = c("ALLSKY_SFC_UV_INDEX", "ALLSKY_SFC_SW_DIFF", "ALLSKY_SRF_ALB", "ALLSKY_KT"))df_centro[] <- lapply(df_centro, as.numeric)corr_matrix_centro <- cor(df_centro, use = "pairwise.complete.obs")corrplot(corr_matrix_centro, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Centro")# Surdf_sur <- subset(dataclimabq_limits, LOCALITY == "Sur", select = c("ALLSKY_SFC_UV_INDEX", "ALLSKY_SFC_SW_DIFF", "ALLSKY_SRF_ALB", "ALLSKY_KT"))df_sur[] <- lapply(df_sur, as.numeric)corr_matrix_sur <- cor(df_sur, use = "pairwise.complete.obs")corrplot(corr_matrix_sur, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Sur")# Occidentedf_occidente <- subset(dataclimabq_limits, LOCALITY == "Occidente", select = c("ALLSKY_SFC_UV_INDEX", "ALLSKY_SFC_SW_DIFF", "ALLSKY_SRF_ALB", "ALLSKY_KT"))df_occidente[] <- lapply(df_occidente, as.numeric)corr_matrix_occidente <- cor(df_occidente, use = "pairwise.complete.obs")corrplot(corr_matrix_occidente, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Occidente")# Orientedf_oriente <- subset(dataclimabq_limits, LOCALITY == "Oriente", select = c("ALLSKY_SFC_UV_INDEX", "ALLSKY_SFC_SW_DIFF", "ALLSKY_SRF_ALB", "ALLSKY_KT"))df_oriente[] <- lapply(df_oriente, as.numeric)corr_matrix_oriente <- cor(df_oriente, use = "pairwise.complete.obs")corrplot(corr_matrix_oriente, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Oriente")# Nortedf_norte <- subset(dataclimabq_limits, LOCALITY == "Norte", select = c("ALLSKY_SFC_UV_INDEX", "ALLSKY_SFC_SW_DIFF", "ALLSKY_SRF_ALB", "ALLSKY_KT"))df_norte[] <- lapply(df_norte, as.numeric)corr_matrix_norte <- cor(df_norte, use = "pairwise.complete.obs")corrplot(corr_matrix_norte, method = "color", type = "upper", col = colorRampPalette(c("blue", "white", "red"))(200), tl.col = "black", tl.cex = 1, number.cex = 0.8, addCoef.col = "black", main = "Matriz de Correlación - Norte")```#### **Análisis de variables clave para el aprovechamiento de la energía solar:**El gráfico muestra la evolución de diferentes variables meteorológicas que influyen en la captación y eficiencia de la energía solar en distintas regiones (Centro, Sur, Occidente, Oriente y Norte). Las variables analizadas incluyen:- **ALLSKY_SFC_UV_INDEX** (Índice UV en superficie)- **ALLSKY_SFC_SW_DIFF** (Radiación solar difusa en superficie)- **ALLSKY_SRF_ALB** (Albedo superficial bajo cielo total)- **ALLSKY_KT** (Índice de claridad)---#### **ALLSKY_SFC_UV_INDEX (Índice UV en superficie)**- Se observa una tendencia estable entre 2020 y 2022, con un ligero descenso en 2022.- A partir de 2023, hay un aumento pronunciado, alcanzando su punto más alto en 2024.- La región Norte presenta los valores más elevados, lo que sugiere una mayor intensidad de radiación solar en esa zona, factor clave para la eficiencia de paneles solares.---#### **ALLSKY_SFC_SW_DIFF (Radiación solar difusa en superficie)**- La radiación solar difusa se mantiene constante en la mayoría de las regiones a lo largo del tiempo.- Sin embargo, el Norte muestra valores significativamente más bajos, lo que indica una mayor predominancia de radiación directa.- Esta información es relevante para decidir entre paneles solares convencionales o tecnologías que aprovechen mejor la radiación difusa, como paneles bifaciales.---#### **ALLSKY_SRF_ALB (Albedo superficial bajo cielo total)**- Se nota una ligera disminución del albedo entre 2020 y 2023, seguida de un incremento en 2024.- La región Norte muestra valores notablemente más altos en comparación con las demás regiones, lo que sugiere una mayor reflectividad del suelo.- Un alto albedo puede afectar la eficiencia de los paneles solares al reflejar parte de la radiación en lugar de absorberla.---#### **ALLSKY_KT (Índice de claridad)**- Se observa una disminución gradual del índice de claridad entre 2020 y 2022, lo que indica un incremento en la nubosidad o aerosoles en la atmósfera.---#### **Histogramas y Boxplots**- **Radiación Solar Total (ALLSKY_SFC_SW_DWN):** Presenta una distribución bimodal, lo que indica diferencias significativas entre días soleados y nublados.- **Albedo Superficial (ALLSKY_SRF_ALB):** Se observa una distribución uniforme con valores altos en ciertas áreas, lo que sugiere que algunas superficies reflejan más energía solar de lo esperado.#### **Mapas de Calor y Correlación**- **Mapa de calor de correlación:** Muestra que la radiación solar tiene una alta correlación con la temperatura y una baja correlación con la velocidad del viento.- **Análisis de Dirección del Viento:** Se observan patrones que podrían afectar la eficiencia de paneles solares en distintas localidades.### **Concluciones generales**#### **1. Microclimas Urbanos y Variabilidad Climática**- Se confirma la existencia de **islas de calor urbanas**, evidenciado por la distribución de temperaturas más altas en zonas densamente pobladas.- La humedad relativa muestra alta variabilidad entre localidades, indicando la influencia de la vegetación y cuerpos de agua en el microclima.- La correlación negativa entre temperatura y humedad refuerza la hipótesis de que el incremento de temperatura disminuye la capacidad del aire para retener humedad.#### **2. Factores Clave en el Aprovechamiento de la Energía Solar**- La radiación solar total presenta **patrones bimodales**, lo que sugiere diferencias significativas en la disponibilidad de energía solar en función de la nubosidad.- El albedo superficial es elevado en ciertas regiones, lo que indica una mayor reflectividad del suelo, factor que puede afectar la absorción de energía solar.- El análisis de correlaciones muestra que la radiación solar está fuertemente vinculada a la temperatura y apenas influenciada por la velocidad del viento.#### **3. Implicaciones Prácticas y Recomendaciones**- Para mitigar el impacto de islas de calor, se recomienda **aumentar la cobertura vegetal y utilizar materiales reflectantes en infraestructuras urbanas**.- En términos de aprovechamiento solar, se deben considerar tecnologías de paneles adaptadas a las condiciones locales, priorizando zonas con mayor radiación solar directa.- La planificación energética debe incluir un análisis detallado de **patrones de nubosidad y albedo**, pues influyen directamente en la eficiencia de los sistemas fotovoltaicos.#### **Análisis individual de la temperatura promedio por general y por localidad:**```{r Temperatura promedio por año}# Calcular la temperatura promedio por añoavg_temp_per_year <- dataclimabq_limits %>% group_by(YEAR) %>% summarise(T2M_mean = mean(T2M, na.rm = TRUE))# Graficar la temperatura promedio por añoggplot(avg_temp_per_year, aes(x = YEAR, y = T2M_mean)) + geom_line(color = "blue", size = 1) + geom_point(color = "red", size = 2) + labs(title = "Temperatura Promedio por Año", x = "Año", y = "Temperatura Promedio (°C)") + theme_minimal()``````{r Temperatura promedio por localidad}# Calcular la temperatura promedio anual por localidaddf_avg_temp <- dataclimabq_limits %>% group_by(YEAR, LOCALITY) %>% summarise(T2M_mean = mean(T2M, na.rm = TRUE), .groups = "drop")# Filtrar solo las primeras 6 localidades en caso de que haya máslocalidades_seleccionadas <- unique(df_avg_temp$LOCALITY)[1:6]# Filtrar el dataset con las localidades seleccionadasdf_avg_temp <- df_avg_temp %>% filter(LOCALITY %in% localidades_seleccionadas)# Graficar la temperatura promedio por localidad con facetasggplot(df_avg_temp, aes(x = YEAR, y = T2M_mean, color = LOCALITY, group = LOCALITY)) + geom_line(size = 1) + geom_point(size = 2) + # Solo los puntos del promedio anual facet_wrap(~ LOCALITY, scales = "free_y") + # Divide en subgráficos por localidad labs(title = "Cambio de Temperatura Promedio Anual por Localidad", x = "Año", y = "Temperatura Promedio (°C)") + theme_minimal() + theme(legend.position = "none", strip.text = element_text(size = 12)) # Oculta la leyenda ya que está en los títulos de los facetas```#### **Análisis de Temperatura a lo Largo del Tiempo**Podemos observar que se muestra un **patrón similar** en los diferentes barrios, lo cual se debe a que se promedia la **temperatura total por año**. Hay varios puntos interesantes a destacar: - A partir del **2020**, la temperatura comenzó a **decrecer** de manera constante hasta alcanzar un **mínimo histórico** dentro del rango de tiempo analizado. - Sin embargo, desde el **2022**, la temperatura experimenta un **aumento exponencial** hasta el **2024**, alcanzando su punto más alto. - Posteriormente, los valores vuelven a **niveles similares a los registrados en 2020**, lo que sugiere una posible estabilización o un ciclo climático recurrente. *Ya en el grafico que promedia la temperatura total entre todas las localidades por año se ve una tendencia de similar pero los valores son más altos.*