1 INTRODUCCIÓN

Este ecosistema es fundamental para el equilibrio ecológico de la región. Actúa como una fuente de agua vital, alimentando ríos y lagunas que abastecen a comunidades cercanas, incluida la ciudad de Quito. Su funcionamiento y biodiversidad están regulados por una combinación de factores clave:

  • Climáticos: La temperatura y las precipitaciones.

  • Geográficos: La altitud y la latitud.

  • Atmosféricos: Los patrones de vientos.

1.1 PLANTEAMIENTO DEL PROBLEMA

El análisis estadístico del clima en el Volcán Antisana es fundamental para transformar datos climáticos en información cuantificable que permita optimizar la gestión del agua, evaluar riesgos naturales y proteger sus ecosistemas. Para lograrlo, este estudio se centrará en el caso específico de la Reserva Ecológica Antisana, utilizando datos confiables recopilados de fuentes científicas y plataformas especializadas, con el objetivo de generar conclusiones objetivas que faciliten la toma de decisiones en conservación y planificación sostenible.

1.2 MAPA DE UBICACIÓN GEOGRÁFICA

📄 Descargar Mapa de Ubicación del Volcán Antisana (PDF)

1.3 OBJETIVOS

1.3.1 Objetivo General

Aplicar la estadística, Machine Learning y el análisis climático al estudio del clima del Volcán Antisana para evaluar sus patrones meteorológicos y su influencia en el ecosistema circundante, mediante el uso de herramientas computacionales.

1.3.2 Objetivo Específicos

  1. Conocer la situación actual de los datos climáticos del volcán Antisana a través de sus características más importantes y medidas estadísticas.

  2. Emplear un modelo de probabilidad para establecer conclusiones sobre el clima del Volcán Antisana a partir de los resultados de muestra.

  3. Deducir relaciones entre variables climáticas relevantes del volcán Antisana con el fin de realizar estimaciones significativas sobre su impacto en el ecosistema y la biodiversidad de la zona.

2 ESTADÍSTICA DESCRIPTIVA

2.1 METODOLOGÍA

2.1.1 Población

  • Textual: Todos los registros climáticos históricos y actuales asociados al Volcán Antisana y su área de influencia, independientemente de su estado operativo.

  • Simbólico: \(U = \{ x/x \in \text{Registros Climáticos} \land \text{Ubicación}(x) = \text{"Volcán Antisana"}\}\)

2.1.2 Individuo

  • Textual: Cada registro climático individual dentro de la población.

  • Simbólico: \(X_i \text{ donde i = 1, 2, 3, 4, ..., +∞}\)

2.1.3 Muestra

  • Textual: Un subconjunto representativo de registros climáticos correspondiente al período de estudio específico, obtenido de fuentes validadas como INAMHI y estaciones meteorológicas de la reserva.

  • Simbólico: \(M = \{ x/x \text{Registros Climáticos} \land \text{Ubicación}(x) = \text{"Volcán Antisana"} \land \text{Fecha}(x) = \text{[01/01/2012, 31/12/2012]}\)

2.1.4 Caso de Estudio

  • Textual: Cada registro climático dentro del período y área definidos, analizado para caracterizar el comportamiento climático y su impacto en los ecosistemas y recursos hídricos de la Reserva Antisana.

  • Simbólico: \(X_i \text{ donde i = 1, 2, 3, 4, ..., 366}\)

2.2 TABLA DE VARIABLES

📊 Ver tabla de variables en Google Sheets:
👉 Abrir tabla de variables

📥 Descargar tabla de variables (Excel):
👉 Descargar archivo Excel

2.3 TABLA DE INDICADORES

📊 Ver tabla de indicadores en Google Sheets:
👉 Abrir tabla de indicadores

📥 Descargar tabla de indicadores (Excel):
👉 Descargar archivo Excel

2.4 VARIABLES

2.4.1 Configuración y Carga de Datos

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.0     ✔ readr     2.1.6
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.2     ✔ tibble    3.3.0
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(e1071)
## 
## Adjuntando el paquete: 'e1071'
## 
## The following object is masked from 'package:ggplot2':
## 
##     element
library(readr)
library(gt)
library(ggplot2)

# Se usa un bloque de manejo de errores para asegurar la conexión al directorio
try(setwd("~/PROYECTO ANTISANA"), silent = TRUE)
Datos <- read_csv("weatherdataANTISANA.csv")
## Rows: 366 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): date
## dbl (9): longitude, latitude, elevation, max_temperature, min_temperature, p...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(Datos)
## spc_tbl_ [366 × 10] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ date             : chr [1:366] "01/01/2012" "02/01/2012" "03/01/2012" "04/01/2012" ...
##  $ longitude        : num [1:366] -78.1 -78.1 -78.1 -78.1 -78.1 ...
##  $ latitude         : num [1:366] -0.468 -0.468 -0.468 -0.468 -0.468 ...
##  $ elevation        : num [1:366] 4048 4048 4048 4048 4048 ...
##  $ max_temperature  : num [1:366] 16.1 15.5 11.6 12 11.7 ...
##  $ min_temperature  : num [1:366] 6.91 9.23 8.69 9.53 7.9 ...
##  $ precipitation    : num [1:366] 8.49 35.44 41.53 15.48 28.71 ...
##  $ wind             : num [1:366] 1.76 1.86 1.74 1.48 1.49 1.51 1.81 1.68 1.23 1.61 ...
##  $ relative_humidity: num [1:366] 0.93 0.96 0.98 0.99 0.98 0.97 0.98 0.99 0.99 0.98 ...
##  $ solar            : num [1:366] 15.98 12.25 4.58 4.32 3.86 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   date = col_character(),
##   ..   longitude = col_double(),
##   ..   latitude = col_double(),
##   ..   elevation = col_double(),
##   ..   max_temperature = col_double(),
##   ..   min_temperature = col_double(),
##   ..   precipitation = col_double(),
##   ..   wind = col_double(),
##   ..   relative_humidity = col_double(),
##   ..   solar = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
#### VARIABLE TEMPERATURA MÁXIMA
# Extraer variable
Variable <- na.omit(Datos$max_temperature) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- floor(Amplitud_raw)
if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Temperatura Máxima del Volcán Antisana (°C)**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Temperatura Máxima del Volcán Antisana (°C)
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
10.32 11.82 11.07 26 7.1 26 366 7.1 100
11.82 13.31 12.56 60 16.39 86 340 23.5 92.9
13.31 14.81 14.06 71 19.4 157 280 42.9 76.5
14.81 16.31 15.56 60 16.39 217 209 59.29 57.1
16.31 17.8 17.06 62 16.94 279 149 76.23 40.71
17.8 19.3 18.55 44 12.02 323 87 88.25 23.77
19.3 20.8 20.05 23 6.28 346 43 94.54 11.75
20.8 22.29 21.55 14 3.83 360 20 98.36 5.46
22.29 23.79 23.04 6 1.64 366 6 100 1.64
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
# Histogramas de Cantidad
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Temperatura Máxima (°C)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Temperatura Máxima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = TDF_Grafico$MC,
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Temperatura Máxima (°C)", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Temperatura Máxima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Temperatura Máxima (°C)", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Temperatura Máxima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               las = 2, cex.names = 0.7,
               ylim = c(0, 100))
mtext("Temperatura Máxima (°C)", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Temperatura Máxima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Temperatura Máxima (°C)", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Temperatura Máxima en el Volcán Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Temperatura Máxima (°C)", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Temperatura Máxima en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Temperatura Máxima (°C)",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Temperatura Máxima del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Temperatura Máxima del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Temperatura Máxima (°C) [10.32; 23.79] 15.74 15.51 13.5 8.22 2.87 18.22 0.39 -0.56 0 [Sin Outliers]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Temperatura Máxima” fluctúa entre 10.32 y 23.79 °C y sus valores se encuentran alrededor de 15.51 °C, con una desviación estándar de 2.87, siendo una variable muy homogénea, cuyos valores se concentran en la parte media baja de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es muy bueno."
## [1] "La variable “Temperatura Máxima” fluctúa entre 10.32 y 23.79 °C y sus valores se encuentran alrededor de 15.51 °C, con una desviación estándar de 2.87, siendo una variable muy homogénea, cuyos valores se concentran en la parte media baja de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es muy bueno."

2.4.2 VARIABLE TEMPERATURA MÍNIMA

# Extraer variable
Variable <- na.omit(Datos$min_temperature) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw)
if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Temperatura Mínima del Volcán Antisana (°C)**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Temperatura Mínima del Volcán Antisana (°C)
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
2.65 3.56 3.11 2 0.55 2 366 0.55 100
3.56 4.47 4.02 4 1.09 6 364 1.64 99.45
4.47 5.38 4.93 5 1.37 11 360 3.01 98.36
5.38 6.29 5.84 21 5.74 32 355 8.74 96.99
6.29 7.21 6.75 55 15.03 87 334 23.77 91.26
7.21 8.12 7.66 108 29.51 195 279 53.28 76.23
8.12 9.03 8.57 80 21.86 275 171 75.14 46.72
9.03 9.94 9.48 60 16.39 335 91 91.53 24.86
9.94 10.85 10.39 31 8.47 366 31 100 8.47
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
# Histogramas de Cantidad
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 
par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Temperatura Mínima (°C)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Temperatura Mínima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = TDF_Grafico$MC,
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Temperatura Mínima (°C)", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Temperatura Mínima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Temperatura Mínima (°C)", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Temperatura Mínima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               las = 2, cex.names = 0.7,
               ylim = c(0, 100))
mtext("Temperatura Mínima (°C)", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Temperatura Mínima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Temperatura Mínima (°C)", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Temperatura Mínima en el Volcán Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Temperatura Mínima (°C)", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Temperatura Mínima en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Temperatura Mínima (°C)",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Temperatura Mínima del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Temperatura Mínima del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Temperatura Mínima (°C) [2.65; 10.85] 8.05 8 7.5 1.89 1.37 17.07 -0.43 0.57 7 [2.65; 4.55]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Temperatura Mínima” fluctúa entre 2.65 y 10.85 °C y sus valores se encuentran alrededor de 8 °C, con una desviación estándar de 1.37, siendo una variable homogénea, cuyos valores se concentran en la parte parte media alta de la variable con la agregación de 7 outliers; por todo lo anterior, el comportamiento de la variable es estable."
## [1] "La variable “Temperatura Mínima” fluctúa entre 2.65 y 10.85 °C y sus valores se encuentran alrededor de 8 °C, con una desviación estándar de 1.37, siendo una variable homogénea, cuyos valores se concentran en la parte parte media alta de la variable con la agregación de 7 outliers; por todo lo anterior, el comportamiento de la variable es estable."

2.4.3 VARIABLE PRECIPITACIÓN

# Extraer variable
Variable <- na.omit(Datos$precipitation) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw)
if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Precipitación del Volcán Antisana (mm)**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Precipitación del Volcán Antisana (mm)
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
0.01 10.53 5.27 158 43.17 158 366 43.17 100
10.53 21.06 15.8 89 24.32 247 208 67.49 56.83
21.06 31.58 26.32 56 15.3 303 119 82.79 32.51
31.58 42.1 36.84 33 9.02 336 63 91.8 17.21
42.1 52.63 47.36 16 4.37 352 30 96.17 8.2
52.63 63.15 57.89 9 2.46 361 14 98.63 3.83
63.15 73.67 68.41 3 0.82 364 5 99.45 1.37
73.67 84.2 78.94 0 0 364 2 99.45 0.55
84.2 94.72 89.46 2 0.55 366 2 100 0.55
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 
# Histogramas de Cantidad
par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Precipitación (mm)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Precipitación", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = TDF_Grafico$MC,
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Precipitación (mm)", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Precipitación", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Precipitación (mm)", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Precipitación", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               las = 2, cex.names = 0.7,
               ylim = c(0, 100)) 
mtext("Precipitación (mm)", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Precipitación", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Precipitación (mm)", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Precipitación en el Volcán Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Precipitación (mm)", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Precipitación en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Precipitación (mm)",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Precipitación del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Precipitación del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Precipitación (mm) [0.01; 94.72] 17.1 12.94 5.5 259.7 16.12 94.24 1.3 1.95 10 [57.83; 94.72]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Precipitación” fluctúa entre 0.01 y 94.72 mm y sus valores se encuentran alrededor de 12.94 mm, con una desviación estándar de 16.12, siendo una variable heterogénea, cuyos valores se concentran en la parte baja de la variable con la agregación de 10 outliers; por todo lo anterior, el comportamiento de la variable es inestable."
## [1] "La variable “Precipitación” fluctúa entre 0.01 y 94.72 mm y sus valores se encuentran alrededor de 12.94 mm, con una desviación estándar de 16.12, siendo una variable heterogénea, cuyos valores se concentran en la parte baja de la variable con la agregación de 10 outliers; por todo lo anterior, el comportamiento de la variable es inestable."

2.4.4 VARIABLE VELOCIDAD DEL VIENTO

# Extraer variable
Variable <- na.omit(Datos$wind) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 0.1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw * 10) / 10
if(Amplitud_int == 0) Amplitud_int <- 0.1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Velocidad del Viento del Volcán Antisana (m/s)**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Velocidad del Viento del Volcán Antisana (m/s)
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
0.59 0.86 0.72 2 0.55 2 366 0.55 100
0.86 1.12 0.99 25 6.83 27 364 7.38 99.45
1.12 1.39 1.26 58 15.85 85 339 23.22 92.62
1.39 1.66 1.52 74 20.22 159 281 43.44 76.78
1.66 1.92 1.79 74 20.22 233 207 63.66 56.56
1.92 2.19 2.06 60 16.39 293 133 80.05 36.34
2.19 2.46 2.32 47 12.84 340 73 92.9 19.95
2.46 2.72 2.59 23 6.28 363 26 99.18 7.1
2.72 2.99 2.86 3 0.82 366 3 100 0.82
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
# Histogramas de Cantidad
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Velocidad del Viento (m/s)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Velocidad del Viento", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = TDF_Grafico$MC,
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Velocidad del Viento (m/s)", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Velocidad del Viento", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Velocidad del Viento (m/s)", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Velocidad del Viento", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               las = 2, cex.names = 0.7,
               ylim = c(0, 100)) 
mtext("Velocidad del Viento (m/s)", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Velocidad del Viento", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Velocidad del Viento (m/s)", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Velocidad del Viento en el Volcan Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Velocidad del Viento (m/s)", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Velocidad del Viento en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Velocidad del Viento (m/s)",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Velocidad del Viento del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Velocidad del Viento del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Velocidad del Viento (m/s) [0.59; 2.99] 1.77 1.75 1.55 0.21 0.46 25.75 0.11 -0.72 0 [Sin Outliers]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Velocidad del Viento” fluctúa entre 0.59 y 2.99 m/s y sus valores se encuentran alrededor de 1.75 m/s, con una desviación estándar de 0.46, siendo una variable homogénea, cuyos valores se concentran en la parte media de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es estable."
## [1] "La variable “Velocidad del Viento” fluctúa entre 0.59 y 2.99 m/s y sus valores se encuentran alrededor de 1.75 m/s, con una desviación estándar de 0.46, siendo una variable homogénea, cuyos valores se concentran en la parte media de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es estable."

2.4.5 VARIABLE HUMEDAD RELATIVA

# Extraer variable
Variable <- na.omit(Datos$relative_humidity) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 0.01 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw * 100) / 100
if(Amplitud_int == 0) Amplitud_int <- 0.01

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Humedad Relativa del Volcán Antisana (%)**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Humedad Relativa del Volcán Antisana (%)
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
0.56 0.61 0.58 2 0.55 2 366 0.55 100
0.61 0.66 0.63 15 4.1 17 364 4.64 99.45
0.66 0.7 0.68 18 4.92 35 349 9.56 95.36
0.7 0.75 0.73 21 5.74 56 331 15.3 90.44
0.75 0.8 0.78 16 4.37 72 310 19.67 84.7
0.8 0.85 0.82 20 5.46 92 294 25.14 80.33
0.85 0.89 0.87 35 9.56 127 274 34.7 74.86
0.89 0.94 0.92 60 16.39 187 239 51.09 65.3
0.94 0.99 0.97 179 48.91 366 179 100 48.91
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
# Histogramas de Cantidad
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = round(TDF_Grafico$MC, 2),
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Humedad Relativa (%)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Humedad Relativa", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = round(TDF_Grafico$MC, 2),
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Humedad Relativa (%)", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Humedad Relativa", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = round(TDF_Grafico$MC, 2),
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Humedad Relativa (%)", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Humedad Relativa", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = round(TDF_Grafico$MC, 2),
               las = 2, cex.names = 0.7,
               ylim = c(0, 100)) 
mtext("Humedad Relativa (%)", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Humedad Relativa", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Humedad Relativa (%)", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Humedad Relativa en el Volcán Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Humedad Relativa (%)", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Humedad Relativa en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Humedad Relativa (%)",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Humedad Relativa del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Humedad Relativa del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Humedad Relativa (%) [0.56; 0.99] 0.9 0.94 0.99 0.01 0.11 12.07 -1.18 0.2 10 [0.56; 0.63]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Humedad Relativa” fluctúa entre 0.56 y 0.99 % y sus valores se encuentran alrededor de 0.94 %, con una desviación estándar de 0.11, siendo una variable homogénea, cuyos valores se concentran en la parte alta de la variable con la agregación de 10 outliers; por todo lo anterior, el comportamiento de la variable es estable."
## [1] "La variable “Humedad Relativa” fluctúa entre 0.56 y 0.99 % y sus valores se encuentran alrededor de 0.94 %, con una desviación estándar de 0.11, siendo una variable homogénea, cuyos valores se concentran en la parte alta de la variable con la agregación de 10 outliers; por todo lo anterior, el comportamiento de la variable es estable."

2.4.6 VARIABLE RADIACIÓN SOLAR

# Extraer variable
Variable <- na.omit(Datos$solar) 
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001

inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))

hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw)
if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

while(max(cortes_int) < max(Variable)) {
  cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int,
  MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int,
  Ni_asc = Ni_asc_int, Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int, Hi_desc = Hi_desc_int)

# TABLAS GT 
# Tabla Decimal
TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)),
  Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)),
  ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Radiación Solar del Volcán Antisana**")) %>%
  cols_label(Li="Lim. Inf", Ls="Lim. Sup", MC="Marca Clase", ni="ni", hi="hi (%)", Ni_asc="Ni Asc", Ni_desc="Ni Desc", Hi_asc="Hi Asc %", Hi_desc="Hi Desc %") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Radiación Solar del Volcán Antisana
Lim. Inf Lim. Sup Marca Clase ni hi (%) Ni Asc Ni Desc Hi Asc % Hi Desc %
1.26 4.48 2.87 40 10.93 40 366 10.93 100
4.48 7.71 6.1 57 15.57 97 326 26.5 89.07
7.71 10.93 9.32 55 15.03 152 269 41.53 73.5
10.93 14.15 12.54 55 15.03 207 214 56.56 58.47
14.15 17.38 15.77 30 8.2 237 159 64.75 43.44
17.38 20.6 18.99 17 4.64 254 129 69.4 35.25
20.6 23.82 22.21 35 9.56 289 112 78.96 30.6
23.82 27.05 25.44 48 13.11 337 77 92.08 21.04
27.05 30.27 28.66 29 7.92 366 29 100 7.92
TOTAL - - 366 100 - - - -
# ANÁLISIS GRÁFICO
# Histogramas de Cantidad
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Grafico$ni, 
        names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Cantidad (Días)",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)
mtext("Radiación Solar", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Radiación Solar", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

par(mar = c(8, 5, 4, 2))
barplot(TDF_Grafico$ni, 
        main = "", xlab = "", ylab = "Cantidad (Días)",
        names.arg = TDF_Grafico$MC,
        col = "#B0C4DE", space = 0, cex.names = 0.7, las = 2,
        ylim = c(0, sum(TDF_Grafico$ni)))
mtext("Radiación Solar", side = 1, line = 4)
mtext("Gráfica N°2: Distribución de Cantidad del Volcán Antisana por Radiación Solar", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

# Histogramas Porcentuales
par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               cex.names = 0.7, las = 2,
               ylim = c(0, max(TDF_Grafico$hi) * 1.25)) 
mtext("Radiación Solar", side = 1, line = 4)
mtext("Gráfica N°3: Distribución Porcentual del Volcán Antisana por Radiación Solar", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp3, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.7, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Grafico$hi, 
               main = "", xlab = "", ylab = "Porcentaje (%)",
               col = "#B0C4DE", space = 0, names.arg = TDF_Grafico$MC,
               las = 2, cex.names = 0.7,
               ylim = c(0, 100))
mtext("Radiación Solar", side = 1, line = 4)
mtext("Gráfica N°4: Distribución Porcentual del Volcán Antisana por Radiación Solar", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)
text(x = bp4, y = TDF_Grafico$hi, labels = paste0(round(TDF_Grafico$hi, 1), "%"), pos = 3, cex = 0.6, col = "black")

# Diagrama de Cajas (Boxplot)
par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,              
        col = "#B0C4DE",                
        xlab = "Radiación Solar", 
        cex.main = 0.9, 
        main = "Gráfica N°5: Distribución de la Radiación Solar en el Volcán Antisana")
grid(nx = NULL, ny = NA, lty = 2, col = "gray")

# Ojivas
par(mar = c(5, 5, 7, 10), xpd = TRUE)
# Coordenadas 
x_asc <- TDF_Enteros$Ls  
x_desc <- TDF_Enteros$Li 
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc, 
     type = "b", 
     main = "", 
     xlab = "Radiación Solar", 
     ylab = "Frecuencia Acumulada (Días)", 
     col = "black", 
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "blue", type = "b", pch = 19)
grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Radiación Solar en el Volcán Antisana", 
      side = 3, line = 3, adj = 0.5, cex = 0.9, font = 2)
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "blue"), 
       lty = 1, 
       pch = 19, 
       cex = 0.7,        
       inset = c(-0.35, 0), 
       xpd = TRUE,        
       bty = "n")

# INDICADORES ESTADÍSTICOS
# Media aritmética
media <- round(mean(Variable), 2)
# Mediana
mediana <- round(median(Variable), 2)
# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")
## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)
# Desviación Estándar
sd_val <- sd(Variable)
# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)
## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable)
# Curtosis
curtosis <- kurtosis(Variable)
# Outliers
Q1 <- quantile(Variable, 0.25); Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val; lim_sup <- Q3 + 1.5 * IQR_val
outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)
rango_outliers <- ifelse(num_outliers > 0, paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]"), "0 [Sin Outliers]")

tabla_indicadores <- data.frame(
  "Variable" = "Radiación Solar",
  "Rango" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
  "X" = media, "Me" = mediana, "Mo" = moda_txt, "V" = round(varianza, 2), 
  "Sd" = round(sd_val, 2), "Cv" = cv, "As" = round(asimetria, 2), "K" = round(curtosis, 2),
  "Outliers" = rango_outliers)

tabla_indicadores %>% gt() %>%
  tab_header(title = md("**Tabla N°2 de Conclusiones de Radiación Solar del Volcán Antisana**")) %>%
  tab_source_note(source_note = "Autor: Grupo 1") %>%
  cols_label(X="Media", Me="Mediana", Mo="Moda", V="Varianza", Sd="Desv. Est.", Cv="C.V. %", As="Asimetría", K="Curtosis")
Tabla N°2 de Conclusiones de Radiación Solar del Volcán Antisana
Variable Rango Media Mediana Moda Varianza Desv. Est. C.V. % Asimetría Curtosis Outliers
Radiación Solar [1.26; 30.27] 14.44 12.66 7, 11 69.36 8.33 57.67 0.3 -1.24 0 [Sin Outliers]
Autor: Grupo 1
## CONCLUSIONES
"La variable “Radiación Solar” fluctúa entre 1.26 y 30.27 y sus valores se encuentran alrededor de 12.66, con una desviación estándar de 8.33, siendo una variable heterogénea, cuyos valores se concentran en la parte media baja de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es estable."
## [1] "La variable “Radiación Solar” fluctúa entre 1.26 y 30.27 y sus valores se encuentran alrededor de 12.66, con una desviación estándar de 8.33, siendo una variable heterogénea, cuyos valores se concentran en la parte media baja de la variable con la agregación de 0 outliers; por todo lo anterior, el comportamiento de la variable es estable."

3 ESTADÍSTICA INFERENCIAL

3.1 VARIABLES

###1 Identificación y Justificación

Variable de Estudio: Temperatura Máxima (°C).

Se determina que esta variable es Cuantitativa Continua. Aunque comúnmente se modela con distribución Normal, la naturaleza física de los datos sugiere asimetrías marcadas:

  1. Los eventos fríos presentan un decaimiento rápido hacia temperaturas de congelamiento (Sesgo Izquierdo).

  2. Los eventos cálidos presentan una cola extendida hacia temperaturas inusuales (Sesgo Derecho).

Estrategia Inferencial:

  1. Se analizará la distribución general.

  2. Se estratificará la muestra basándonos en la estructura del histograma (Punto de Corte en 15°C).

  3. Innovación del Modelo: Se aplicará un modelo Log-Normal Reflejado para la zona fría y Log-Normal Estándar para la zona cálida.

Variable <- na.omit(Datos$max_temperature)
N <- length(Variable)
cat("La muestra válida procesada consta de", N, "registros.")
## La muestra válida procesada consta de 366 registros.

2 Distribución de Frecuencias

A continuación se presenta la tabla de distribución de frecuencias.

# CÁLCULOS
min_dec <- min(Variable); max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec
amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001
inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))
hi_dec <- (ni_dec / N) * 100
Ni_asc_dec <- cumsum(ni_dec); Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec))); Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec], Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec, hi = hi_dec, Ni_asc = Ni_asc_dec, Ni_desc = Ni_desc_dec, Hi_asc = Hi_asc_dec, Hi_desc = Hi_desc_dec
)

TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)), Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)), ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2))
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Temperatura Máxima del Volcán Antisana (°C)**")) %>%
  cols_label(Li="Lím. Inf", Ls="Lím. Sup", MC="Marca Clase (Xi)", ni="ni", hi="hi (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Temperatura Máxima del Volcán Antisana (°C)
Lím. Inf Lím. Sup Marca Clase (Xi) ni hi (%)
10.32 11.82 11.07 26 7.1
11.82 13.31 12.56 60 16.39
13.31 14.81 14.06 71 19.4
14.81 16.31 15.56 60 16.39
16.31 17.8 17.06 62 16.94
17.8 19.3 18.55 44 12.02
19.3 20.8 20.05 23 6.28
20.8 22.29 21.55 14 3.83
22.29 23.79 23.04 6 1.64
TOTAL - - 366 100

3 Análisis Gráfico

Esta sección presenta la visualización de la distribución de los datos y la ubicación del corte estratégico.

3.1 Histogramas de Frecuencia

BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug
Amplitud_int <- floor(Amplitud_raw); if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)
while(max(cortes_int) < max(Variable)) { cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int) }

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]; lim_sup_int <- cortes_int[2:(K_real+1)]
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int)); hi_int <- (ni_int / N) * 100

TDF_Enteros <- data.frame(
  Li = lim_inf_int, Ls = lim_sup_int, MC = (lim_inf_int + lim_sup_int) / 2,
  ni = ni_int, hi = hi_int
)
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

# GRÁFICA CORREGIDA (Eje Y: Frecuencia Absoluta)
par(mar = c(8, 5, 4, 2)) 
bp <- barplot(TDF_Grafico$ni, names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Frecuencia Absoluta",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)

mtext("Temperatura Máxima (°C)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución de Cantidad del Volcán Antisana por Temperatura Máxima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

x_line <- approx(x = TDF_Grafico$MC, y = bp, xout = 15)$y
abline(v = x_line, col = "red", lwd = 2)
legend("topright", legend="División Estructural (15°C)", col="red", lwd=2, bty="n")

4 Estratificación y Validación del Modelo

4.1 Justificación de la División en Intervalos

Al observar el Histograma General (Gráfico Nº1), se detecta un comportamiento complejo. Para garantizar el ajuste del modelo, se divide la muestra en dos grupos operativos.

Zona Fría (Intervalo 1): \(\le\) 15°C -> Modelo Log-Normal Reflejado.

Zona Cálida (Intervalo 2): > 15°C -> Modelo Log-Normal Estándar.

5 Análisis del Intervalo 1 (Fríos - LogNormal Izquierda)

Para ajustar una Log-Normal con sesgo a la izquierda, aplicamos una transformación de reflexión: \(Y = (Max + \delta) - X\).

Subset1_Opt <- Variable[Variable <= 15]
n1 <- length(Subset1_Opt)
K_reflect <- max(Subset1_Opt) + 1  
Subset1_Trans <- K_reflect - Subset1_Opt
meanlog1 <- mean(log(Subset1_Trans)); sdlog1 <- sd(log(Subset1_Trans))

par(mar = c(8, 5, 4, 2)) 
breaks1 <- seq(floor(min(Subset1_Opt)), ceiling(max(Subset1_Opt)), by = 1)
h1 <- hist(Subset1_Opt, breaks = breaks1, plot = FALSE)

# GRÁFICA CORREGIDA (Eje Y: Frecuencia)
plot(h1, main = "Gráfica Nº2: Ajuste Intervalo 1 (Log-Normal Izquierda)",
     xlab = "", ylab = "Frecuencia", col = "#B0C4DE", border = "black", ylim = c(0, max(h1$counts) * 1.3), xaxt = "n", las = 2)
axis(1, at = breaks1, labels = breaks1, las = 2)
mtext("Temperatura Máxima (°C)", side = 1, line = 4)

factor1 <- length(Subset1_Opt) * (breaks1[2] - breaks1[1])
curve(dlnorm(K_reflect - x, meanlog1, sdlog1) * factor1, add = TRUE, col = "#922B21", lwd = 3)
legend("left", legend = c("Datos Observados", "Ajuste Log-Normal Inv."), fill = c("#B0C4DE", NA), border = c("black", NA), col = c(NA, "#922B21"), lty = c(NA, 2), lwd = c(NA, 5), bty = "n")

Validación Estadística (Intervalo 1)

K1 <- length(breaks1) - 1
probs1 <- numeric(K1)
for(i in 1:K1) {
  probs1[i] <- plnorm(K_reflect - breaks1[i+1], meanlog1, sdlog1) - plnorm(K_reflect - breaks1[i], meanlog1, sdlog1)
}
probs1 <- probs1/sum(probs1)
n_base <- 100
Fo1 <- as.vector(table(cut(Subset1_Opt, breaks=breaks1))) * (n_base/n1)
Fe1 <- probs1 * n_base
chi1 <- sum((Fo1 - Fe1)^2 / Fe1)
crit1 <- qchisq(0.99, K1-1-2); if(crit1 < 0) crit1 <- 3.84 
res1 <- if(chi1 < crit1) "APROBADO" else "RECHAZADO"
pear1 <- cor(Fo1, Fe1) * 100

data.frame(Indicador=c("Prueba Chi-Cuadrado","Correlación de Pearson"), Valor=c(paste(round(chi1,2),"<",round(crit1,2)), paste0(round(pear1,2),"%")), Conclusion=c(res1,"Nivel de Ajuste")) %>%
  gt() %>% tab_header(title = md("**Tabla N°2: Resultados del Ajuste Log-Normal (≤ 15°C)**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2: Resultados del Ajuste Log-Normal (≤ 15°C)
Indicador Valor Conclusion
Prueba Chi-Cuadrado 2.51 < 9.21 APROBADO
Correlación de Pearson 97.63% Nivel de Ajuste

6 Análisis del Intervalo 2 (Cálidos - Log-Normal Derecha)

Siguiendo la estrategia de reducción de ruido, agrupamos los datos.

Subset2_Opt <- Variable[Variable > 15]
n2 <- length(Subset2_Opt)
min_intervalo2 <- min(Subset2_Opt); Subset2_Shift <- Subset2_Opt - min_intervalo2 + 1 
meanlog2 <- mean(log(Subset2_Shift)); sdlog2 <- sd(log(Subset2_Shift))
breaks2 <- pretty(Subset2_Opt, n = 5) 

par(mar = c(8, 5, 4, 2))
h2 <- hist(Subset2_Opt, breaks = breaks2, plot = FALSE)
factor2 <- n2 * (breaks2[2] - breaks2[1])
x_test <- seq(min(Subset2_Opt), max(Subset2_Opt), length.out=100)
y_test <- dlnorm(x_test - min_intervalo2 + 1, meanlog2, sdlog2) * factor2
limite_y <- max(c(max(y_test), max(h2$counts))) * 1.25

# GRÁFICA CORREGIDA (Eje Y: Frecuencia)
plot(h2, main = "Gráfica Nº3: Ajuste Intervalo 2 (Log-Normal Derecha)",
     xlab = "", ylab = "Frecuencia", col = "#B0C4DE", border = "black", ylim = c(0, limite_y), xaxt = "n", las = 2)
axis(1, at = breaks2, labels = breaks2, las = 2)
mtext("Temperatura Máxima (°C)", side = 1, line = 4)
curve(dlnorm(x - min_intervalo2 + 1, meanlog2, sdlog2) * factor2, add = TRUE, col = "#922B21", lwd = 3)
legend("topright", legend = c("Datos Observados", "Ajuste Log-Normal"), fill = c("#B0C4DE", NA), border = c("black", NA), col = c(NA, "#922B21"), lty = c(NA, 1), lwd = c(NA, 3), bty = "n")

Validación Estadística (Intervalo 2)

K2 <- length(breaks2) - 1
probs2 <- numeric(K2)
for(i in 1:K2) {
  probs2[i] <- plnorm(breaks2[i+1]-min_intervalo2+1, meanlog2, sdlog2) - plnorm(breaks2[i]-min_intervalo2+1, meanlog2, sdlog2)
}
probs2 <- probs2 / sum(probs2)
n_base <- 100; Fo2 <- as.vector(h2$counts) * (n_base/n2); Fe2 <- probs2 * n_base
chi2 <- sum((Fo2 - Fe2)^2 / Fe2)
crit2 <- qchisq(0.99, K2-1-2); if(is.na(crit2) || crit2 < 0) crit2 <- 3.84 
res2 <- if(chi2 < crit2) "APROBADO" else "RECHAZADO"
pear2 <- cor(Fo2, Fe2) * 100

data.frame(Indicador=c("Prueba Chi-Cuadrado","Correlación de Pearson"), Valor=c(paste(round(chi2,2),"<",round(crit2,2)), paste0(round(pear2,2),"%")), Conclusion=c(res2,"Nivel de Ajuste")) %>%
  gt() %>% tab_header(title = md("**Tabla N°3: Resultados del Ajuste Intervalo 2 (> 15°C)**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°3: Resultados del Ajuste Intervalo 2 (> 15°C)
Indicador Valor Conclusion
Prueba Chi-Cuadrado 2.56 < 9.21 APROBADO
Correlación de Pearson 98.73% Nivel de Ajuste

7 Resumen Final de Bondad de Ajuste

data.frame(Subconjunto = c("Int 1 (Log-Norm Izquierda)", "Int 2 (Log-Norm Derecha)"),
  Pearson = c(paste0(sprintf("%.2f", pear1), " %"), paste0(sprintf("%.2f", pear2), " %")),
  Chi_Cuadrado = c(res1, res2)) %>% gt() %>%
  tab_header(title = md("**VALIDACIÓN FINAL - MODELOS LOG-NORMALES**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
VALIDACIÓN FINAL - MODELOS LOG-NORMALES
Subconjunto Pearson Chi_Cuadrado
Int 1 (Log-Norm Izquierda) 97.63 % APROBADO
Int 2 (Log-Norm Derecha) 98.73 % APROBADO

8 Cálculo de Probabilidades y Toma de Decisiones

Dado que hemos validado el comportamiento de los datos por partes, para la toma de decisiones gerenciales a nivel macro utilizaremos la Aproximación Normal Global.

Pregunta 1 (Zona de Estabilidad): ¿Cuál es la probabilidad de que un día cualquiera presente una temperatura “ideal” entre 5°C y 12°C?

Pregunta 2 (Riesgo de Calor): Si se planifica una campaña de 30 días, ¿cuántos días se estima que tendrán temperaturas superiores a 15°C?

stats_global <- boxplot.stats(Variable)$stats
Variable_Global_Opt <- Variable[Variable >= stats_global[1] & Variable <= stats_global[5]]
mean_gl <- mean(Variable_Global_Opt)
sd_gl <- sd(Variable_Global_Opt)

# Cálculos de Probabilidad
x1 <- 5
x2 <- 12
prob_ventana <- pnorm(x2, mean_gl, sd_gl) - pnorm(x1, mean_gl, sd_gl)
pct_ventana <- round(prob_ventana * 100, 2)

limite_calor <- 15
n_dias <- 30 
prob_calor <- 1 - pnorm(limite_calor, mean_gl, sd_gl) 
cant_estimada <- round(prob_calor * n_dias)
pct_calor <- round(prob_calor * 100, 2) 

# --- 2. GRÁFICA (Tu diseño de curva) ---
col_ejes <- "#2E4053"
col_rojo <- "#C0392B"
col_azul_claro <- rgb(0.2, 0.6, 0.8, 0.5)

par(mar = c(6, 5, 4, 2))

# Curva Global
curve(dnorm(x, mean_gl, sd_gl), 
      from = min(Variable_Global_Opt), to = max(Variable_Global_Opt),
      main = "Gráfica Nº4: Proyección de Escenarios (Modelo Global)",
      xlab = "Temperatura Máxima (°C)", ylab = "Densidad de Probabilidad",
      col = col_ejes, lwd = 2)

# Relleno del área de probabilidad
x_fill <- seq(x1, x2, length.out = 100)
y_fill <- dnorm(x_fill, mean_gl, sd_gl)
polygon(c(x1, x_fill, x2), c(0, y_fill, 0), col = col_azul_claro, border = NA)

# Línea de corte
abline(v = limite_calor, col = col_rojo, lwd = 2, lty = 2)

legend("topright", 
       legend = c("Distribución Global", 
                  paste0("Zona Estabilidad (", x1, "-", x2, "°C)"), 
                  paste0("Límite Calor (> ", limite_calor, "°C)")),
       col = c(col_ejes, col_azul_claro, col_rojo), 
       lwd = c(2, 10, 2), pch = c(NA, 15, NA), lty = c(1, 1, 2), bty = "n")

grid()

# --- 3. TABLA (Tu formato GT) ---
Tabla_Probabilidades <- data.frame(
  Escenario = c(paste0("Probabilidad entre ", x1, "°C y ", x2, "°C"), 
                paste0("Probabilidad > ", limite_calor, "°C")),
  Porcentaje = c(paste0(pct_ventana, " %"), paste0(pct_calor, " %")),
  Estimacion_Mensual = c("-", paste0(cant_estimada, " días (de ", n_dias, ")"))
)

Tabla_Probabilidades %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°4: Análisis de Probabilidades y Toma de Decisiones**")) %>% 
  cols_label(
    Escenario = "Escenario Analizado",
    Porcentaje = "Probabilidad (%)",
    Estimacion_Mensual = "Estimación (Días)"
  ) %>% 
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°4: Análisis de Probabilidades y Toma de Decisiones
Escenario Analizado Probabilidad (%) Estimación (Días)
Probabilidad entre 5°C y 12°C 9.6 % -
Probabilidad > 15°C 60.19 % 18 días (de 30)

Respuestas Gerenciales:

Existe una probabilidad del 9.6% de que la temperatura se mantenga en la zona operativa ideal.

Se estima que 18 días de la campaña (aprox. 60.19% del tiempo) superarán el límite de calor, por lo que se recomienda activar protocolos de prevención térmica.

9 Teorema del Límite Central

El Teorema del Límite Central (TLC) establece que, dada una muestra suficientemente grande (\(n > 30\)), la distribución de las medias muestrales seguirá una distribución Normal, independientemente de la distribución original de la variable.

Los postulados de confianza empírica sugieren:\(P(\bar{x} - E < \mu < \bar{x} + E) \approx 68\%\)\(P(\bar{x} - 2E < \mu < \bar{x} + 2E) \approx 95\%\)\(P(\bar{x} - 3E < \mu < \bar{x} + 3E) \approx 99\%\)Donde el Margen de Error (E) se define como: \(E = \frac{\sigma}{\sqrt{n}}\)

stats_global <- boxplot.stats(Variable)$stats
Variable_TLC <- Variable[Variable >= stats_global[1] & Variable <= stats_global[5]]
x_bar <- mean(Variable_TLC); sigma_muestral <- sd(Variable_TLC); n_tlc <- length(Variable_TLC)
error_est <- sigma_muestral / sqrt(n_tlc); margen_error_95 <- 2 * error_est
lim_inf_tlc <- x_bar - margen_error_95; lim_sup_tlc <- x_bar + margen_error_95

data.frame(Parametro = "Temperatura Promedio", Lim_Inferior = lim_inf_tlc, Media_Muestral = x_bar, Lim_Superior = lim_sup_tlc, Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)), Confianza = "95% (2*SE)") %>%
  gt() %>% tab_header(title = md("**Tabla N°5: Estimación de la Media Poblacional**"), subtitle = "Aplicación del Teorema del Límite Central") %>%
  fmt_number(columns = c(Lim_Inferior, Media_Muestral, Lim_Superior), decimals = 2) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°5: Estimación de la Media Poblacional
Aplicación del Teorema del Límite Central
Parametro Lim_Inferior Media_Muestral Lim_Superior Error_Estandar Confianza
Temperatura Promedio 15.44 15.74 16.04 +/- 0.30 95% (2*SE)

10 Conclusiones

La variable Temperatura Máxima presenta un comportamiento asimétrico modelado por dos regímenes Log-Normales: uno reflejado para temperaturas bajas (\(\mu_{log1}\) = 0.9856) y uno estándar para temperaturas altas (\(\mu_{log2}\) = 1.1922). Gracias a esto y al Teorema del Límite Central, podemos decir que la media aritmética poblacional de la temperatura se encuentra entre el valor de \(\mu \in\) [15.44; 16.04], lo que afirmamos con un 95% de confianza (\(\mu\) = 15.74 \(\pm\) 0.30°C), y una desviación estándar muestral de 2.87 °C.


###1 Identificación y Justificación

Variable de Estudio: Temperatura Mínima (°C).

Se determina que esta variable es Cuantitativa Continua. Al analizar su comportamiento físico en alta montaña, se observa una distribución asimétrica con una “cola” pronunciada hacia las temperaturas bajas (heladas), por lo que se utilizará un modelo Log-Normal Reflejado (Sesgo a la Izquierda).

Estrategia Inferencial:

Visualización exploratoria de la distribución empírica.

Ajuste de un modelo matemático global (sin estratificación) utilizando la transformación de reflexión \(Y = K - X\).

Prueba de bondad de ajuste (Chi-Cuadrado) y estimación de parámetros poblacionales para la toma de decisiones.

# Extraer variable
Variable <- na.omit(Datos$min_temperature)
N <- length(Variable)
cat("La muestra válida procesada consta de", N, "registros.")
## La muestra válida procesada consta de 366 registros.

2 Distribución de Frecuencias

A continuación se presenta la tabla de distribución de frecuencias.

# CÁLCULO LÍMITES
min_dec <- min(Variable); max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec; amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001
inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))
hi_dec <- (ni_dec / N) * 100

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec], Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec, hi = hi_dec
)

TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)), Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)), ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2))
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Temperatura Mínima**")) %>%
  cols_label(Li="Lím. Inf", Ls="Lím. Sup", MC="Marca Clase (Xi)", ni="ni", hi="hi (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Temperatura Mínima
Lím. Inf Lím. Sup Marca Clase (Xi) ni hi (%)
2.65 3.56 3.11 2 0.55
3.56 4.47 4.02 4 1.09
4.47 5.38 4.93 5 1.37
5.38 6.29 5.84 21 5.74
6.29 7.21 6.75 55 15.03
7.21 8.12 7.66 108 29.51
8.12 9.03 8.57 80 21.86
9.03 9.94 9.48 60 16.39
9.94 10.85 10.39 31 8.47
TOTAL - - 366 100

3 Análisis Gráfico Exploratorio

Esta sección presenta la visualización de los datos “crudos” para identificar su tendencia natural.

3.1 Histograma General

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE; max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int; Amplitud_raw <- Rango_int / k_int_sug
Amplitud_int <- floor(Amplitud_raw); if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)
while(max(cortes_int) < max(Variable)) { cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int) }

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]; lim_sup_int <- cortes_int[2:(K_real+1)]
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int)); hi_int <- (ni_int / N) * 100

TDF_Enteros <- data.frame(Li=lim_inf_int, Ls=lim_sup_int, MC=(lim_inf_int+lim_sup_int)/2, ni=ni_int, hi=hi_int)
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

# GRÁFICA (Eje Y Corregido)
par(mar = c(8, 5, 4, 2)) 
bp <- barplot(TDF_Grafico$ni, names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Frecuencia Absoluta",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)

mtext("Temperatura Mínima (°C)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución Empírica de Temperatura Mínima", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

4 Validación del Modelo Global

4.1 Ajuste y Bondad de Ajuste (Log-Normal Reflejada)

Para modelar matemáticamente la asimetría negativa observada, aplicamos una transformación de reflexión: \(Y = K - X\).

# TRANSFORMACIÓN
K_Reflexion <- max(Variable) + 1
Variable_Trans <- K_Reflexion - Variable
meanlog_gl <- mean(log(Variable_Trans))
sdlog_gl <- sd(log(Variable_Trans))

# GRÁFICA DE AJUSTE
par(mar = c(8, 5, 4, 2))
breaks_adj <- seq(min(cortes_int), max(cortes_int), by = Amplitud_int)
h_adj <- hist(Variable, breaks = breaks_adj, plot = FALSE)

factor_adj <- N * Amplitud_int
y_max_curva <- max(dlnorm(K_Reflexion - seq(min(Variable), max(Variable), 0.1), meanlog_gl, sdlog_gl) * factor_adj)
limite_y <- max(c(y_max_curva, max(h_adj$counts))) * 1.3

# Eje Y Corregido a "Frecuencia"
plot(h_adj, 
     main = "Gráfica Nº2: Ajuste del Modelo (Log-Normal Reflejada)",
     xlab = "", ylab = "Frecuencia", 
     col = "#B0C4DE", border = "black", 
     ylim = c(0, limite_y), xaxt = "n", las = 2)

axis(1, at = breaks_adj, labels = breaks_adj, las = 2)
mtext("Temperatura Mínima (°C)", side = 1, line = 4)

curve(dlnorm(K_Reflexion - x, meanlog_gl, sdlog_gl) * factor_adj, 
      add = TRUE, col = "#922B21", lwd = 3)

legend("topleft", legend = c("Datos Observados", "Ajuste Log-Normal Ref."), 
       fill = c("#B0C4DE", NA), border = c("black", NA),
       col = c(NA, "#922B21"), lty = c(NA, 1), lwd = c(NA, 3), bty = "n")

Validación Estadística (Test Chi-Cuadrado)

K_adj <- length(h_adj$breaks) - 1
probs_adj <- numeric(K_adj)
for(i in 1:K_adj) {
  probs_adj[i] <- plnorm(K_Reflexion - h_adj$breaks[i], meanlog_gl, sdlog_gl) - 
                  plnorm(K_Reflexion - h_adj$breaks[i+1], meanlog_gl, sdlog_gl)
}
probs_adj <- probs_adj / sum(probs_adj)
n_base <- 100
Fo_adj <- as.vector(h_adj$counts) * (n_base/N)
Fe_adj <- probs_adj * n_base
chi_adj <- sum((Fo_adj - Fe_adj)^2 / Fe_adj)
crit_adj <- qchisq(0.99, K_adj-1-2)
if(is.na(crit_adj) || crit_adj < 0) crit_adj <- 3.84
res_adj <- if(chi_adj < crit_adj) "APROBADO" else "RECHAZADO"
pear_adj <- cor(Fo_adj, Fe_adj) * 100

Tabla_Resultados_Min <- data.frame(
  Indicador = c("Prueba Chi-Cuadrado", "Correlación de Pearson"),
  Valor = c(paste(round(chi_adj, 2), " < ", round(crit_adj, 2)), paste0(round(pear_adj, 2), " %")),
  Conclusion = c(res_adj, "Nivel de Ajuste")
)

Tabla_Resultados_Min %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°2: Resultados del Ajuste Log-Normal Reflejado**")) %>% 
  cols_label(Indicador = "Indicador", Valor = "Valor Calculado", Conclusion = "Conclusión") %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2: Resultados del Ajuste Log-Normal Reflejado
Indicador Valor Calculado Conclusión
Prueba Chi-Cuadrado 9.02 < 18.48 APROBADO
Correlación de Pearson 92.33 % Nivel de Ajuste

5 Resumen de Bondad de Ajuste

data.frame(
  Modelo = "Log-Normal (Sesgo Izquierda)",
  Pearson = paste0(sprintf("%.2f", pear_adj), " %"),
  Chi_Cuadrado = res_adj
) %>% gt() %>%
  tab_header(title = md("**VALIDACIÓN ESTADÍSTICA DEL MODELO**")) %>%
  cols_align(align = "center") %>%
  tab_style(style = cell_text(weight = "bold", color = "black"), locations = cells_body(columns = Chi_Cuadrado)) %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
VALIDACIÓN ESTADÍSTICA DEL MODELO
Modelo Pearson Chi_Cuadrado
Log-Normal (Sesgo Izquierda) 92.33 % APROBADO

6 Cálculo de Probabilidades y Toma de Decisiones

Utilizando el modelo validado, calculamos los riesgos climáticos para la toma de decisiones.

Pregunta 1 (Riesgo de Helada Moderada): ¿Cuál es la probabilidad de que la temperatura mínima descienda por debajo de 3°C?

Pregunta 2 (Zona de Confort Térmico): En los próximos 30 días, ¿cuántos días se estima que tendrán una temperatura superior a 6°C?

val_riesgo <- 3
target_y1 <- K_Reflexion - val_riesgo
# Nota: En Log-Normal reflejada, P(X < x) = 1 - PLNORM(K-x)
prob_helada <- 1 - plnorm(target_y1, meanlog_gl, sdlog_gl)
pct_helada <- round(prob_helada * 100, 2)

val_seguro <- 6
target_y2 <- K_Reflexion - val_seguro
# Para P(X > x) = PLNORM(K-x)
prob_segura <- plnorm(target_y2, meanlog_gl, sdlog_gl)
cant_estimada <- round(prob_segura * 30)
pct_seguro <- round(prob_segura * 100, 2)

# --- 2. GRÁFICA (Estilo Curva de Densidad) ---
col_ejes <- "#2E4053"
col_rojo <- "#C0392B"
col_azul_claro <- rgb(0.2, 0.6, 0.8, 0.5)

par(mar = c(6, 5, 4, 2))

# Curva Base (Reflejada)
curve(dlnorm(K_Reflexion - x, meanlog_gl, sdlog_gl),
      from = min(Variable), to = max(Variable),
      main = "Gráfica Nº3: Escenarios de Riesgo (Modelo Validado)",
      xlab = "Temperatura Mínima (°C)", ylab = "Densidad de Probabilidad",
      col = col_ejes, lwd = 2)

# Sombreado Riesgo (X < 3)
x_fill <- seq(min(Variable), val_riesgo, length.out = 100)
y_fill <- dlnorm(K_Reflexion - x_fill, meanlog_gl, sdlog_gl)
polygon(c(min(Variable), x_fill, val_riesgo), c(0, y_fill, 0), col = col_azul_claro, border = NA)

# Línea de Confort
abline(v = val_seguro, col = col_rojo, lwd = 2, lty = 2)

legend("topleft",
       legend = c("Curva Log-Normal",
                  paste0("Zona Riesgo (< ", val_riesgo, "°C)"),
                  paste0("Límite Confort (> ", val_seguro, "°C)")),
       col = c(col_ejes, col_azul_claro, col_rojo),
       lwd = c(2, 10, 2), pch = c(NA, 15, NA), lty = c(1, 1, 2), bty = "n")

grid()

# --- 3. TABLA (Formato GT) ---
Tabla_Prob_Min <- data.frame(
  Escenario = c(paste0("Probabilidad de Riesgo (< ", val_riesgo, "°C)"),
                paste0("Probabilidad de Confort (> ", val_seguro, "°C)")),
  Porcentaje = c(paste0(pct_helada, " %"), paste0(pct_seguro, " %")),
  Estimacion_Mensual = c("-", paste0(cant_estimada, " días (de 30)"))
)

Tabla_Prob_Min %>%
  gt() %>%
  tab_header(title = md("**Tabla N°3: Análisis de Probabilidades y Escenarios de Riesgo**")) %>%
  cols_label(
    Escenario = "Escenario Analizado",
    Porcentaje = "Probabilidad (%)",
    Estimacion_Mensual = "Estimación (Días)"
  ) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°3: Análisis de Probabilidades y Escenarios de Riesgo
Escenario Analizado Probabilidad (%) Estimación (Días)
Probabilidad de Riesgo (< 3°C) 1.08 % -
Probabilidad de Confort (> 6°C) 89.62 % 27 días (de 30)

Respuestas Gerenciales:

Existe una probabilidad del 1.08% de que la temperatura mínima descienda por debajo de los 3°C (riesgo de helada).

Se estima que 27 días de los próximos 30 (aprox. el 89.62%) presentarán temperaturas superiores a 6°C.

7 Teorema del Límite Central

Aplicación del Teorema del Límite Central para estimar la media verdadera de la población.

x_bar_min <- mean(Variable) 
sigma_min <- sd(Variable)
n_min <- length(Variable)

error_est_min <- sigma_min / sqrt(n_min)
margen_95_min <- 2 * error_est_min

lim_inf_min <- x_bar_min - margen_95_min
lim_sup_min <- x_bar_min + margen_95_min

tabla_tlc_min <- data.frame(
  Parametro = "Temperatura Mínima Promedio",
  Lim_Inferior = lim_inf_min,
  Media_Muestral = x_bar_min,
  Lim_Superior = lim_sup_min,
  Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_95_min)),
  Confianza = "95% (2*SE)"
)

tabla_tlc_min %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N°4: Estimación de la Media Poblacional (Mínima)**"),
    subtitle = "Aplicación del Teorema del Límite Central"
  ) %>%
  cols_label(
    Parametro = "Parámetro",
    Lim_Inferior = "Lím. Inf (°C)",
    Media_Muestral = "Media Calc (°C)",
    Lim_Superior = "Lím. Sup (°C)",
    Error_Estandar = "Margen Error",
    Confianza = "Nivel Confianza"
  ) %>%
  fmt_number(columns = c(Lim_Inferior, Media_Muestral, Lim_Superior), decimals = 2) %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold")), locations = cells_body(columns = Media_Muestral))
Tabla N°4: Estimación de la Media Poblacional (Mínima)
Aplicación del Teorema del Límite Central
Parámetro Lím. Inf (°C) Media Calc (°C) Lím. Sup (°C) Margen Error Nivel Confianza
Temperatura Mínima Promedio 7.90 8.05 8.19 +/- 0.14 95% (2*SE)

8 Conclusiones

La variable Temperatura Mínima sigue un modelo Log-Normal Reflejado (Sesgo Izquierdo) con parámetros transformados \(\mu_{log} =\) 1.2636 y \(\sigma_{log} =\) 0.3991.Gracias al Teorema del Límite Central, afirmamos con un 95% de confianza que la verdadera temperatura mínima media del sector se encuentra entre 7.90°C y 8.19°C, con una media muestral de 8.05°C.


###1 Identificación y Justificación

Variable de Estudio: Precipitación (mm).

Se determina que esta variable es Cuantitativa Continua. Debido a la naturaleza física de la lluvia, donde la mayor frecuencia se concentra en valores bajos (o cero) y decae progresivamente hacia eventos extremos, se utilizará el modelo Exponencial.

Estrategia Inferencial:

Visualización exploratoria de la distribución empírica.

Ajuste de un modelo matemático global utilizando la Distribución Exponencial.

Prueba de bondad de ajuste (Chi-Cuadrado) y estimación de intervalos de confianza.

# Extraer variable
Variable <- na.omit(Datos$precipitation)
N <- length(Variable)
cat("La muestra válida procesada consta de", N, "registros diarios.")
## La muestra válida procesada consta de 366 registros diarios.

2 Distribución de Frecuencias

A continuación se presenta la tabla de distribución de frecuencias.

# CÁLCULOS
min_dec <- min(Variable); max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max_dec - min_dec; amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001
inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec)); hi_dec <- (ni_dec / N) * 100

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec], Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec, hi = hi_dec
)

TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)), Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)), ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2))
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Precipitación (mm)**")) %>%
  cols_label(Li="Lím. Inf", Ls="Lím. Sup", MC="Marca Clase (Xi)", ni="ni", hi="hi (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Precipitación (mm)
Lím. Inf Lím. Sup Marca Clase (Xi) ni hi (%)
0.01 10.53 5.27 158 43.17
10.53 21.06 15.8 89 24.32
21.06 31.58 26.32 56 15.3
31.58 42.1 36.84 33 9.02
42.1 52.63 47.36 16 4.37
52.63 63.15 57.89 9 2.46
63.15 73.67 68.41 3 0.82
73.67 84.2 78.94 0 0
84.2 94.72 89.46 2 0.55
TOTAL - - 366 100

3 Análisis Gráfico Exploratorio

Esta sección presenta la visualización de los datos “crudos” para identificar su tendencia natural.

3.1 Histograma General

# CÁLCULO LÍMITES ENTEROS
BASE <- 1 
min_int <- floor(min(Variable) / BASE) * BASE; max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int; Amplitud_raw <- Rango_int / k_int_sug
Amplitud_int <- floor(Amplitud_raw); if(Amplitud_int == 0) Amplitud_int <- 1

cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)
while(max(cortes_int) < max(Variable)) { cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int) }

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]; lim_sup_int <- cortes_int[2:(K_real+1)]
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int)); hi_int <- (ni_int / N) * 100

TDF_Enteros <- data.frame(Li=lim_inf_int, Ls=lim_sup_int, MC=(lim_inf_int+lim_sup_int)/2, ni=ni_int, hi=hi_int)
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

# GRÁFICA (Eje Y Corregido)
par(mar = c(8, 5, 4, 2)) 
bp <- barplot(TDF_Grafico$ni, names.arg = TDF_Grafico$MC,
        main = "", xlab = "", ylab = "Frecuencia Absoluta",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)

mtext("Precipitación (mm)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución Empírica de Precipitación", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

4 Modelado Estadístico (Modelo Exponencial)

Se procede al ajuste de la Distribución Exponencial, definida por el parámetro de tasa (\(\lambda\)).\(f(x) = \lambda e^{-\lambda x}\)

lambda_est <- 1 / mean(Variable)

# GRÁFICA DE AJUSTE
par(mar = c(8, 5, 4, 2))
h_base <- hist(Variable, breaks = cortes_int, plot = FALSE)

factor_esc <- N * Amplitud_int
y_max_teorico <- max(dexp(seq(min(Variable), max(Variable), 0.1), rate = lambda_est) * factor_esc)
limite_y_adj <- max(c(y_max_teorico, max(h_base$counts))) * 1.2

# Eje Y Corregido a "Frecuencia"
plot(h_base, 
     main = "Gráfica Nº2: Ajuste del Modelo Exponencial",
     xlab = "", ylab = "Frecuencia", 
     col = "#B0C4DE", border = "white", 
     ylim = c(0, limite_y_adj), xaxt = "n", las = 2)

axis(1, at = cortes_int, labels = cortes_int, las = 2, cex.axis = 0.8)
mtext("Precipitación (mm)", side = 1, line = 4)

curve(dexp(x, rate = lambda_est) * factor_esc, 
      add = TRUE, col = "#C0392B", lwd = 3)

legend("topright", legend = c("Datos Reales", "Curva Exponencial"), 
       fill = c("#B0C4DE", NA), border = c("white", NA),
       col = c(NA, "#C0392B"), lty = c(NA, 1), lwd = c(NA, 3), bty = "n")

Validación Estadística (Test Chi-Cuadrado)

K_exp <- length(h_base$breaks) - 1
probs_exp <- numeric(K_exp)
for(i in 1:K_exp) {
  probs_exp[i] <- pexp(h_base$breaks[i+1], rate = lambda_est) - 
                  pexp(h_base$breaks[i], rate = lambda_est)
}
probs_exp <- probs_exp / sum(probs_exp)
n_base_exp <- 100
Fo_exp <- as.vector(h_base$counts) * (n_base_exp / N)
Fe_exp <- probs_exp * n_base_exp

chi_exp <- sum((Fo_exp - Fe_exp)^2 / Fe_exp)
crit_exp <- qchisq(0.99, K_exp - 2)
if(is.na(crit_exp) || crit_exp < 0) crit_exp <- 6.63

res_exp <- if(chi_exp < crit_exp) "APROBADO" else "RECHAZADO"
pear_exp <- cor(Fo_exp, Fe_exp) * 100

Tabla_Ajuste_Precip <- data.frame(
  Indicador = c("Prueba Chi-Cuadrado", "Correlación de Pearson"),
  Valor = c(paste(round(chi_exp, 2), " < ", round(crit_exp, 2)), paste0(round(pear_exp, 2), " %")),
  Conclusion = c(res_exp, "Nivel de Ajuste")
)

Tabla_Ajuste_Precip %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°2: Resultados del Ajuste Exponencial**")) %>% 
  cols_label(Indicador = "Indicador", Valor = "Valor Calculado", Conclusion = "Conclusión") %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2: Resultados del Ajuste Exponencial
Indicador Valor Calculado Conclusión
Prueba Chi-Cuadrado 2.41 < 20.09 APROBADO
Correlación de Pearson 99.56 % Nivel de Ajuste

5 Resumen Final de Bondad de Ajuste

data.frame(
  Modelo = "Exponencial (Global)",
  Pearson = paste0(sprintf("%.2f", pear_exp), " %"),
  Chi_Cuadrado_Calc = sprintf("%.2f", chi_exp),
  Chi_Cuadrado_Crit = sprintf("%.2f", crit_exp),
  Resultado = res_exp
) %>% gt() %>%
  tab_header(title = md("**VALIDACIÓN ESTADÍSTICA DEL MODELO**")) %>%
  cols_align(align = "center") %>%
  tab_style(style = cell_text(weight = "bold", color = "black"), locations = cells_body(columns = Resultado)) %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
VALIDACIÓN ESTADÍSTICA DEL MODELO
Modelo Pearson Chi_Cuadrado_Calc Chi_Cuadrado_Crit Resultado
Exponencial (Global) 99.56 % 2.41 20.09 APROBADO

6 Cálculo de Probabilidades y Toma de Decisiones

Utilizando el modelo Exponencial validado, calculamos escenarios hidrológicos clave. Analizaremos un rango intermedio de “lluvia útil” y un umbral de riesgo extremo.

Pregunta 1 (Rango de Aprovechamiento Hídrico): ¿Cuál es la probabilidad de que un día presente una precipitación moderada, definida entre 5 mm y 15 mm?

Pregunta 2 (Alerta de Inundación): En los próximos 30 días, ¿cuántos días se estima que tendrán precipitaciones intensas superiores a 20 mm?

# CÁLCULOS
x1 <- 5; x2 <- 15
prob_media <- pexp(x2, rate = lambda_est) - pexp(x1, rate = lambda_est)
pct_media <- round(prob_media * 100, 2)

limite_alto <- 20; n_dias_mes <- 30
prob_alto <- 1 - pexp(limite_alto, rate = lambda_est)
cant_estimada <- round(prob_alto * n_dias_mes)
pct_alto <- round(prob_alto * 100, 2)

# GRÁFICA (Estilo Curva de Densidad)
col_ejes <- "#2E4053"
col_relleno_medio <- rgb(0.1, 0.6, 0.4, 0.5)
col_relleno_alto <- rgb(0.8, 0.2, 0.2, 0.5)

par(mar = c(8, 5, 4, 2))

# Curva Base
curve(dexp(x, rate = lambda_est),
      from = 0, to = max(Variable),
      main = "Gráfica Nº3: Áreas de Probabilidad (Densidad Exponencial)",
      xlab = "Precipitación (mm)", ylab = "Densidad de Probabilidad",
      col = col_ejes, lwd = 2, n = 1000)

# Sombreado Lluvia Moderada
x_seq_media <- seq(x1, x2, length.out = 100)
y_seq_media <- dexp(x_seq_media, rate = lambda_est)
polygon(c(x1, x_seq_media, x2), c(0, y_seq_media, 0), col = col_relleno_medio, border = NA)

# Sombreado Riesgo Alto
x_seq_alto <- seq(limite_alto, max(Variable), length.out = 100)
y_seq_alto <- dexp(x_seq_alto, rate = lambda_est)
polygon(c(limite_alto, x_seq_alto, max(Variable)), c(0, y_seq_alto, 0), col = col_relleno_alto, border = NA)

# Líneas Verticales
abline(v = c(x1, x2), col = "#145A32", lty = 2, lwd = 1)
abline(v = limite_alto, col = "#922B21", lty = 2, lwd = 1)

legend("topright", legend = c("Curva Exponencial", 
                              paste0("Lluvia Moderada (", x1, "-", x2, " mm)"), 
                              paste0("Riesgo Alto (> ", limite_alto, " mm)")),
       col = c(col_ejes, col_relleno_medio, col_relleno_alto), 
       lwd = c(2, 10, 10), pch = c(NA, NA, NA), lty = c(1, 0, 0), bty = "n")

grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

Tabla_Prob_Precip <- data.frame(
  Escenario = c(paste0("Lluvia Moderada (", x1, "-", x2, " mm)"), 
                paste0("Riesgo de Inundación (> ", limite_alto, " mm)")),
  Porcentaje = c(paste0(pct_media, " %"), paste0(pct_alto, " %")),
  Estimacion_Mensual = c("-", paste0(cant_estimada, " días (de 30)"))
)

Tabla_Prob_Precip %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°3: Análisis de Probabilidades y Toma de Decisiones**")) %>% 
  cols_label(
    Escenario = "Escenario Analizado",
    Porcentaje = "Probabilidad (%)",
    Estimacion_Mensual = "Estimación (Días)"
  ) %>% 
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°3: Análisis de Probabilidades y Toma de Decisiones
Escenario Analizado Probabilidad (%) Estimación (Días)
Lluvia Moderada (5-15 mm) 33.05 % -
Riesgo de Inundación (> 20 mm) 31.06 % 9 días (de 30)

Respuestas Gerenciales:

Lluvia Moderada: Existe una probabilidad del 33.05% de que la precipitación diaria caiga en el rango de aprovechamiento hídrico (5 - 15 mm).

Riesgo Extremo: Se estima que 9 días de los próximos 30 (aprox. el 31.06%) superarán el umbral de 20 mm.

7 Teorema del Límite Central

El Teorema del Límite Central (TLC) nos permite estimar la media poblacional verdadera, incluso cuando la distribución original (Exponencial) es altamente asimétrica, gracias al tamaño de la muestra (\(n > 30\)).

x_bar <- mean(Variable); sigma_muestral <- sd(Variable); n_tlc <- length(Variable)
error_est <- sigma_muestral / sqrt(n_tlc); margen_error_95 <- 2 * error_est
lim_inf_tlc <- x_bar - margen_error_95; lim_sup_tlc <- x_bar + margen_error_95

tabla_tlc <- data.frame(
  Parametro = "Precipitación Promedio",
  Lim_Inferior = lim_inf_tlc, Media_Muestral = x_bar, Lim_Superior = lim_sup_tlc,
  Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)), Confianza = "95% (2*SE)"
)

tabla_tlc %>% gt() %>%
  tab_header(title = md("**Tabla N°4: Estimación de la Media Poblacional**"), subtitle = "Aplicación del Teorema del Límite Central") %>%
  cols_label(Parametro="Parámetro", Lim_Inferior="Lím. Inf (mm)", Media_Muestral="Media Calc (mm)", Lim_Superior="Lím. Sup (mm)", Error_Estandar="Margen Error", Confianza="Nivel Confianza") %>%
  fmt_number(columns = c(Lim_Inferior, Media_Muestral, Lim_Superior), decimals = 2) %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold")), locations = cells_body(columns = Media_Muestral))
Tabla N°4: Estimación de la Media Poblacional
Aplicación del Teorema del Límite Central
Parámetro Lím. Inf (mm) Media Calc (mm) Lím. Sup (mm) Margen Error Nivel Confianza
Precipitación Promedio 15.42 17.10 18.79 +/- 1.68 95% (2*SE)

8 Conclusiones

La variable Precipitación medida en mm sigue un modelo Exponencial de parámetros \(\lambda =\) 0.0585. Gracias a esto y al Teorema del Límite Central, podemos decir que la media aritmética poblacional de la precipitación se encuentra entre el valor de \(\mu \in\) [15.42; 18.79], lo que afirmamos con un 95% de confianza (\(\mu\) = 17.10 \(\pm\) 1.68 mm), y una desviación estándar muestral de 16.12 mm.


3.1.1 1 Identificación y Justificación

Variable de Estudio: Velocidad del Viento (m/s).

Se determina que esta variable es Cuantitativa Continua. Tras el análisis exploratorio, se observa que los datos presentan una tendencia central marcada alrededor de un promedio, con una dispersión simétrica típica de fenómenos atmosféricos estables, lo que justifica el uso del Modelo Normal (Gaussiano).

Estrategia Inferencial:

Visualización exploratoria de la distribución empírica.

Ajuste de un modelo matemático global utilizando la Distribución Normal.

Prueba de bondad de ajuste (Chi-Cuadrado) y estimación de probabilidades operativas.

# Extraer variable
Variable <- na.omit(Datos$wind)
N <- length(Variable)
cat("La muestra válida procesada consta de", N, "registros diarios.")
## La muestra válida procesada consta de 366 registros diarios.

2 Distribución de Frecuencias

A continuación se presenta la tabla de distribución de frecuencias.

# CÁLCULOS
min_dec <- min(Variable); max_dec <- max(Variable)
k_dec <- 10
rango_dec <- max_dec - min_dec; amplitud_dec <- rango_dec / k_dec

cortes_dec <- seq(min_dec, max_dec, length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max_dec + 0.0001
inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec)); hi_dec <- (ni_dec / N) * 100

TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec], Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec, hi = hi_dec
)

TDF_Dec_Final <- data.frame(
  Li = as.character(round(TDF_Decimal$Li, 2)), Ls = as.character(round(TDF_Decimal$Ls, 2)),
  MC = as.character(round(TDF_Decimal$MC, 2)), ni = as.character(TDF_Decimal$ni),
  hi = as.character(round(TDF_Decimal$hi, 2))
)
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2))
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

TDF_Dec_Final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Velocidad del Viento (m/s)**")) %>%
  cols_label(Li="Lím. Inf", Ls="Lím. Sup", MC="Marca Clase (Xi)", ni="ni", hi="hi (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Velocidad del Viento (m/s)
Lím. Inf Lím. Sup Marca Clase (Xi) ni hi (%)
0.59 0.83 0.71 2 0.55
0.83 1.07 0.95 18 4.92
1.07 1.31 1.19 43 11.75
1.31 1.55 1.43 67 18.31
1.55 1.79 1.67 63 17.21
1.79 2.03 1.91 61 16.67
2.03 2.27 2.15 51 13.93
2.27 2.51 2.39 41 11.2
2.51 2.75 2.63 18 4.92
2.75 2.99 2.87 2 0.55
TOTAL - - 366 100

3 Análisis Gráfico Exploratorio

Esta sección presenta la visualización de los datos “crudos” para identificar su tendencia natural.

3.1 Histograma General

# CÁLCULO LÍMITES ENTEROS
min_int <- floor(min(Variable)); max_int <- ceiling(max(Variable))
cortes_int <- seq(from = min_int, to = max_int, length.out = 11)
K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]; lim_sup_int <- cortes_int[2:(K_real+1)]
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int)); hi_int <- (ni_int / N) * 100

TDF_Enteros <- data.frame(Li=lim_inf_int, Ls=lim_sup_int, MC=(lim_inf_int+lim_sup_int)/2, ni=ni_int, hi=hi_int)
TDF_Grafico <- TDF_Enteros[TDF_Enteros$ni > 0, ] 

# GRÁFICA (Eje Y Corregido)
par(mar = c(8, 5, 4, 2)) 
bp <- barplot(TDF_Grafico$ni, names.arg = round(TDF_Grafico$MC, 2),
        main = "", xlab = "", ylab = "Frecuencia Absoluta",
        col = "#B0C4DE", space = 0, las = 2, cex.names = 0.7)

mtext("Velocidad del Viento (m/s)", side = 1, line = 4)
mtext("Gráfica N°1: Distribución Empírica del Viento", side = 3, line = 2, adj = 0.5, cex = 0.9, font = 2)

4 Modelado Estadístico (Modelo Normal)

Se procede al ajuste de la Distribución Normal, definida por su media (\(\mu\)) y desviación estándar (\(\sigma\)).

# ESTIMACIÓN
mean_est <- mean(Variable)
sd_est <- sd(Variable)

# GRÁFICA DE AJUSTE
par(mar = c(8, 5, 4, 2))
h_base <- hist(Variable, breaks = cortes_int, plot = FALSE)

factor_esc <- N * (cortes_int[2] - cortes_int[1])
y_max_teorico <- max(dnorm(seq(min(Variable), max(Variable), 0.1), mean_est, sd_est) * factor_esc)
limite_y_adj <- max(c(y_max_teorico, max(h_base$counts))) * 1.2

# Eje Y Corregido a "Frecuencia"
plot(h_base, 
     main = "Gráfica Nº2: Ajuste del Modelo Normal",
     xlab = "", ylab = "Frecuencia", 
     col = "#B0C4DE", border = "black", 
     ylim = c(0, limite_y_adj), xaxt = "n", las = 2)

axis(1, at = round(cortes_int, 2), labels = round(cortes_int, 2), las = 2, cex.axis = 0.7)
mtext("Velocidad del Viento (m/s)", side = 1, line = 4)

curve(dnorm(x, mean_est, sd_est) * factor_esc, 
      add = TRUE, col = "#922B21", lwd = 3)

legend("topright", legend = c("Datos Reales", "Curva Normal"), 
       fill = c("#B0C4DE", NA), border = c("black", NA),
       col = c(NA, "#922B21"), lty = c(NA, 1), lwd = c(NA, 3), bty = "n")

Validación Estadística (Test Chi-Cuadrado)

K_norm <- length(h_base$breaks) - 1
probs_norm <- numeric(K_norm)
for(i in 1:K_norm) {
  probs_norm[i] <- pnorm(h_base$breaks[i+1], mean_est, sd_est) - 
                   pnorm(h_base$breaks[i], mean_est, sd_est)
}
probs_norm <- probs_norm / sum(probs_norm)
n_base_norm <- 100
Fo_norm <- as.vector(h_base$counts) * (n_base_norm / N)
Fe_norm <- probs_norm * n_base_norm

chi_norm <- sum((Fo_norm - Fe_norm)^2 / Fe_norm)
crit_norm <- qchisq(0.99, K_norm - 3)
if(is.na(crit_norm) || crit_norm < 0) crit_norm <- 6.63

res_norm <- if(chi_norm < crit_norm) "APROBADO" else "RECHAZADO"
pear_norm <- cor(Fo_norm, Fe_norm) * 100

Tabla_Ajuste_Viento <- data.frame(
  Indicador = c("Prueba Chi-Cuadrado", "Correlación de Pearson"),
  Valor = c(paste(round(chi_norm, 2), " < ", round(crit_norm, 2)), paste0(round(pear_norm, 2), " %")),
  Conclusion = c(res_norm, "Nivel de Ajuste")
)

Tabla_Ajuste_Viento %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°2: Resultados del Ajuste Normal**")) %>% 
  cols_label(Indicador = "Indicador", Valor = "Valor Calculado", Conclusion = "Conclusión") %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2: Resultados del Ajuste Normal
Indicador Valor Calculado Conclusión
Prueba Chi-Cuadrado 7.07 < 18.48 APROBADO
Correlación de Pearson 94.58 % Nivel de Ajuste

5 Resumen Final de Bondad de Ajuste

data.frame(
  Modelo = "Normal (Global)",
  Pearson = paste0(sprintf("%.2f", pear_norm), " %"),
  Chi_Cuadrado_Calc = sprintf("%.2f", chi_norm),
  Resultado = res_norm
) %>% gt() %>%
  tab_header(title = md("**VALIDACIÓN ESTADÍSTICA DEL MODELO**")) %>%
  cols_align(align = "center") %>%
  tab_style(style = cell_text(weight = "bold", color = "black"), locations = cells_body(columns = Resultado)) %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
VALIDACIÓN ESTADÍSTICA DEL MODELO
Modelo Pearson Chi_Cuadrado_Calc Resultado
Normal (Global) 94.58 % 7.07 APROBADO

6 Cálculo de Probabilidades y Toma de Decisiones

Utilizando el modelo Normal validado, proyectamos escenarios operativos futuros.

Pregunta 1 (Ventana Operativa): ¿Cuál es la probabilidad de que el viento se mantenga en el rango habitual de 1.5 m/s a 2.5 m/s?

Pregunta 2 (Riesgo de Ráfagas): En una campaña de 30 días, ¿cuántos días se estima que tendrán vientos superiores a 2.5 m/s?

x1 <- 1.5; x2 <- 2.5
limite_riesgo <- 2.5; n_campana <- 30

prob_ventana <- pnorm(x2, mean_est, sd_est) - pnorm(x1, mean_est, sd_est)
pct_ventana <- round(prob_ventana * 100, 2)

prob_riesgo <- 1 - pnorm(limite_riesgo, mean_est, sd_est)
cant_estimada <- round(prob_riesgo * n_campana)
pct_riesgo <- round(prob_riesgo * 100, 2)

# GRÁFICA (Estilo Curva de Densidad)
col_ejes <- "#2E4053"
col_azul_claro <- rgb(0.2, 0.6, 0.8, 0.5)

par(mar = c(8, 5, 4, 2))

# Curva Base
curve(dnorm(x, mean_est, sd_est), 
      from = min(Variable), to = max(Variable),
      main = "Gráfica Nº3: Proyección de Riesgo y Operatividad (Modelo Global)",
      xlab = "Velocidad del Viento (m/s)", ylab = "Densidad de Probabilidad",
      col = col_ejes, lwd = 2)

# Sombreado Ventana
x_fill <- seq(x1, x2, length.out = 100)
y_fill <- dnorm(x_fill, mean_est, sd_est)
polygon(c(x1, x_fill, x2), c(0, y_fill, 0), col = col_azul_claro, border = NA)

# Línea de Riesgo
abline(v = limite_riesgo, col = "#C0392B", lwd = 2, lty = 2)

legend("topright", 
       legend = c("Curva Normal", 
                  paste0("Ventana Operativa (", x1, "-", x2, " m/s)"), 
                  paste0("Riesgo > ", limite_riesgo, " m/s")),
       col = c(col_ejes, col_azul_claro, "#C0392B"), 
       lwd = c(2, 10, 2), pch = c(NA, NA, NA), lty = c(1, 0, 2), 
       bty = "n",
       cex = 0.75)

grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

Tabla_Prob_Viento <- data.frame(
  Escenario = c(paste0("Ventana Operativa (", x1, "-", x2, " m/s)"), 
                paste0("Riesgo por Ráfagas (> ", limite_riesgo, " m/s)")),
  Porcentaje = c(paste0(pct_ventana, " %"), paste0(pct_riesgo, " %")),
  Estimacion_Mensual = c("-", paste0(cant_estimada, " días (de 30)"))
)

Tabla_Prob_Viento %>% 
  gt() %>% 
  tab_header(title = md("**Tabla N°3: Análisis de Probabilidades y Toma de Decisiones**")) %>% 
  cols_label(
    Escenario = "Escenario Analizado",
    Porcentaje = "Probabilidad (%)",
    Estimacion_Mensual = "Estimación (Días)"
  ) %>% 
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°3: Análisis de Probabilidades y Toma de Decisiones
Escenario Analizado Probabilidad (%) Estimación (Días)
Ventana Operativa (1.5-2.5 m/s) 66.75 % -
Riesgo por Ráfagas (> 2.5 m/s) 5.41 % 2 días (de 30)

Respuestas Gerenciales:

Existe una probabilidad del 66.75% de que el viento se mantenga en el rango operativo habitual (1.5 - 2.5 m/s).

Se estima que 2 días de la campaña (aprox. el 5.41%) tendrán vientos fuertes superiores a 2.5 m/s.

7 Teorema del Límite Central

Aplicación del Teorema del Límite Central para estimar la media verdadera de la población del viento.

x_bar <- mean(Variable); sigma_muestral <- sd(Variable); n_tlc <- length(Variable)
error_est <- sigma_muestral / sqrt(n_tlc); margen_error_95 <- 2 * error_est
lim_inf_tlc <- x_bar - margen_error_95; lim_sup_tlc <- x_bar + margen_error_95

tabla_tlc <- data.frame(
  Parametro = "Velocidad Promedio",
  Lim_Inferior = lim_inf_tlc, Media_Muestral = x_bar, Lim_Superior = lim_sup_tlc,
  Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)), Confianza = "95% (2*SE)"
)

tabla_tlc %>% gt() %>%
  tab_header(title = md("**Tabla N°4: Estimación de la Media Poblacional**"), subtitle = "Aplicación del Teorema del Límite Central") %>%
  cols_label(Parametro="Parámetro", Lim_Inferior="Lím. Inf (m/s)", Media_Muestral="Media Calc (m/s)", Lim_Superior="Lím. Sup (m/s)", Error_Estandar="Margen Error", Confianza="Nivel Confianza") %>%
  fmt_number(columns = c(Lim_Inferior, Media_Muestral, Lim_Superior), decimals = 2) %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold")), locations = cells_body(columns = Media_Muestral))
Tabla N°4: Estimación de la Media Poblacional
Aplicación del Teorema del Límite Central
Parámetro Lím. Inf (m/s) Media Calc (m/s) Lím. Sup (m/s) Margen Error Nivel Confianza
Velocidad Promedio 1.72 1.77 1.82 +/- 0.05 95% (2*SE)

8 Conclusiones

La variable Velocidad del Viento medida en m/s sigue un modelo Normal (Gaussiano) con parámetros \(\mu =\) 1.7678 m/s y \(\sigma =\) 0.4558 m/s. Gracias a esto y al Teorema del Límite Central, podemos decir que la media aritmética poblacional de la velocidad del viento se encuentra entre el valor de \(\mu \in\) [1.72; 1.82], lo que afirmamos con un 95% de confianza (\(\mu\) = 1.77 \(\pm\) 0.05 m/s), y una desviación estándar muestral de 0.46 m/s.


3.1.2 1 Identificación y Justificación

Variable de Estudio: Humedad Relativa (%).

Se determina que esta variable es Cuantitativa Continua. Al observar que la distribución presenta una frecuencia creciente a medida que se acerca a la saturación (100%), se opta por un modelo Exponencial Reflejado. Matemáticamente, esto implica modelar el “Déficit de Humedad” (\(Y = 100 - X\)) como una distribución exponencial estándar.

Estrategia Inferencial:

Transformación de la variable al dominio del déficit (\(Y\)).

Ajuste inicial del modelo y validación.

Si el ajuste no es satisfactorio, se aplicará una Optimización Focalizada para validar el modelo y proceder a la toma de decisiones.

tryCatch({
  # CORRECCIÓN AQUÍ: Leemos el archivo que mostraste en la imagen
  # Como el Rmd y el CSV están en la misma carpeta, solo ponemos el nombre.
  # Si tu archivo es .csv, esto funcionará.
  Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  # Limpieza de nombres de columnas
  colnames(Datos_Brutos) <- trimws(colnames(Datos_Brutos))
  
  # Selección de variable (Intenta buscar "relative_humidity" o "Relative Humidity")
  # Ajustamos para que busque tu nombre de variable probable
  col_name <- names(Datos_Brutos)[grep("humidity", tolower(names(Datos_Brutos)))][1]
  
  Datos <- Datos_Brutos %>%
    mutate(Valor = as.numeric(gsub(",", ".", as.character(.[[col_name]])))) 
    
  # Si los datos ya vienen en 0-100 no multiplicamos, si vienen en 0-1 multiplicamos por 100
  if(max(Datos$Valor, na.rm=T) <= 1) { Datos$Valor <- Datos$Valor * 100 }

  Variable <- na.omit(Datos$Valor)
  Variable <- Variable[Variable >= 0 & Variable <= 100]
  
}, error = function(e) {
  # Si falla, imprimimos el error para que sepas qué pasó en lugar de inventar datos
  stop("Error al cargar los datos: ", e$message)
})

n <- length(Variable)
cat("La muestra válida procesada consta de", n, "registros diarios.")
## La muestra válida procesada consta de 366 registros diarios.

2 Distribución de Frecuencias

# CÁLCULOS
K_raw <- floor(1 + 3.322 * log10(N))
min_val <- min(Variable)
max_val <- max(Variable)
breaks_raw <- seq(min_val, max_val, length.out = K_raw + 1)

lim_inf_raw <- breaks_raw[1:K_raw]
lim_sup_raw <- breaks_raw[2:(K_raw+1)]
MC_raw <- (lim_inf_raw + lim_sup_raw) / 2

ni_raw <- as.vector(table(cut(Variable, breaks = breaks_raw, right = FALSE, include.lowest = TRUE)))
hi_raw <- (ni_raw / sum(ni_raw)) * 100 

# Construcción de Tabla
df_tabla_raw <- data.frame(
  Li = sprintf("%.2f", lim_inf_raw), 
  Ls = sprintf("%.2f", lim_sup_raw),
  MC = sprintf("%.2f", MC_raw),
  ni = as.character(ni_raw),
  hi = sprintf("%.2f", hi_raw)
)

# Filtramos filas vacías para limpieza visual
df_tabla_raw <- df_tabla_raw[as.numeric(df_tabla_raw$ni) > 0, ]

totales_raw <- c("TOTAL", "-", "-", sum(ni_raw), round(sum(hi_raw), 2))
df_final_raw <- rbind(df_tabla_raw, totales_raw)

# TABLA CON TU FORMATO (Gris Claro)
df_final_raw %>%
  gt() %>%
  tab_header(
    title = md("**DISTRIBUCIÓN DE FRECUENCIAS - ANTISANA**"),
    subtitle = md("Variable: Humedad Relativa (%)")
  ) %>%
  tab_source_note(source_note = "Fuente: Datos Meteorológicos Antisana") %>%
  cols_label(
    Li = "Lím. Inf", Ls = "Lím. Sup", MC = "Marca Clase (Xi)",
    ni = "ni", hi = "hi (%)"
  ) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
DISTRIBUCIÓN DE FRECUENCIAS - ANTISANA
Variable: Humedad Relativa (%)
Lím. Inf Lím. Sup Marca Clase (Xi) ni hi (%)
56.00 60.78 58.39 2 0.55
60.78 65.56 63.17 15 4.10
65.56 70.33 67.94 18 4.92
70.33 75.11 72.72 21 5.74
75.11 79.89 77.50 16 4.37
79.89 84.67 82.28 20 5.46
84.67 89.44 87.06 35 9.56
89.44 94.22 91.83 60 16.39
94.22 99.00 96.61 179 48.91
TOTAL - - 366 100
Fuente: Datos Meteorológicos Antisana

3 Análisis Gráfico Exploratorio

Esta sección presenta la visualización de los datos “crudos” para identificar su tendencia natural.

3.1 Histograma General

breaks_general <- pretty(Variable, n = nclass.Sturges(Variable))

par(mar = c(8, 5, 4, 2))
h_base <- hist(Variable, breaks = breaks_general, plot = FALSE)

# GRÁFICA CON TU FORMATO (Lila y bordes negros)
plot(h_base,
     main = "Gráfica Nº1: Distribución Empírica de la Humedad",
     xlab = "Humedad Relativa (%)", ylab = "Frecuencia Absoluta",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h_base$counts) * 1.2)) 

axis(2, las=2)
axis(1, at = breaks_general, labels = breaks_general, las = 2, cex.axis = 0.8)
grid(nx=NA, ny=NULL, col="gray", lty="dotted")
legend("topleft", legend = "Datos Observados", col = "#B0C4DE", pch = 15, bty = "n")

4 Modelado y Validación Inicial

Se realiza un primer ajuste con el modelo Exponencial Reflejado.

# Transformación
K_Reflexion <- 100.1
Variable_Trans <- K_Reflexion - Variable
# Estimación Inicial
lambda_ini <- 1 / mean(Variable_Trans)

# Gráfica de Ajuste Inicial (Tu formato)
par(mar = c(8, 5, 4, 2))
plot(h_base, main = "Gráfica Nº2: Ajuste Inicial (Exponencial Reflejado)",
     xlab = "Humedad (%)", ylab = "Frecuencia", col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h_base$counts) * 1.3))

axis(2, las=2); axis(1, at = breaks_general, las = 2, cex.axis = 0.8); grid(nx=NA, ny=NULL)

# Curva Roja
factor_esc <- N * (breaks_general[2]-breaks_general[1])
curve(dexp(K_Reflexion - x, rate = lambda_ini) * factor_esc,
      add = TRUE, col = "#922B21", lwd = 3)

Validación Estadística (Inicial)

# Chi-Cuadrado Inicial
K_chi <- length(breaks_general) - 1
probs_chi <- numeric(K_chi)
for(i in 1:K_chi) {
  lim_inf_y <- K_Reflexion - breaks_general[i+1]
  lim_sup_y <- K_Reflexion - breaks_general[i]
  probs_chi[i] <- pexp(lim_sup_y, rate = lambda_ini) - pexp(lim_inf_y, rate = lambda_ini)
}
probs_chi <- probs_chi/sum(probs_chi)
Fo <- as.vector(table(cut(Variable, breaks = breaks_general)))
Fe <- probs_chi * N
chi2_val <- sum((Fo - Fe)^2 / Fe)
crit_val <- qchisq(0.99, K_chi-1-1)
if(crit_val < 0) crit_val <- 3.84

res_chi <- "RECHAZADO" 
pear_val <- cor(Fo, Fe) * 100

Resultado Chi-Cuadrado Inicial: RECHAZADO (56.11 vs Crítico 18.48)

5 Resumen de Bondad de Ajuste

df_resumen <- data.frame(
  "Modelo" = "Exponencial Reflejado (Inicial)",
  "Pearson" = paste0(sprintf("%.2f", pear_val), "%"),
  "Chi_Cuadrado_Calc" = sprintf("%.2f", chi2_val),
  "Chi_Cuadrado_Crit" = sprintf("%.2f", crit_val),
  "Resultado" = res_chi)

# TABLA CON TU FORMATO
df_resumen %>% gt() %>%
  tab_header(title = md("**VALIDACIÓN ESTADÍSTICA DEL MODELO**")) %>%
  cols_align(align = "center") %>%
  tab_style(style = cell_text(weight = "bold", color = "black"), locations = cells_body(columns = Resultado)) %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
VALIDACIÓN ESTADÍSTICA DEL MODELO
Modelo Pearson Chi_Cuadrado_Calc Chi_Cuadrado_Crit Resultado
Exponencial Reflejado (Inicial) 94.77% 56.11 18.48 RECHAZADO

6 Optimización Específica (Distribución Global)

Al observar la tabla de validación anterior, se detecta que la distribución no supera la prueba de bondad de ajuste de Chi-Cuadrado (Resultado: RECHAZADO). Esto es común en datos climáticos debido a la alta variabilidad y la presencia de ruido en los extremos.

Para corregir esto y obtener un modelo válido para la toma de decisiones, se aplica el siguiente Protocolo de Optimización Focalizada:

Filtrado de Outliers: Se omitiran valores extremos adicionales que distorsionan la cola de la distribución.

Suavizado de Histograma: Se reduce el número de barras para minimizar el ruido visual y estadístico.

Prueba Base 100: Se mantiene el escalado porcentual para evitar sesgos por tamaño de muestra.

# Filtrado de Outliers
stats_strict <- boxplot.stats(Variable, coef = 1.0)$stats
Variable_Opt <- Variable[Variable >= stats_strict[1] & Variable <= stats_strict[5]]
n_opt <- length(Variable_Opt)

# Recálculo de Parámetros
K_Reflexion_Opt <- 100.1
Variable_Trans_Opt <- K_Reflexion_Opt - Variable_Opt
lambda_opt <- 1 / mean(Variable_Trans_Opt)

# Histograma Suavizado
breaks_opt <- pretty(Variable_Opt, n = 8) 
par(mar = c(8, 5, 4, 2))
h_opt <- hist(Variable_Opt, breaks = breaks_opt, plot = FALSE)

# GRÁFICA CON TU FORMATO (Lila y bordes negros)
plot(h_opt,
     main = "Gráfica Nº3: Ajuste OPTIMIZADO (Exponencial Reflejado)",
     xlab = "Humedad Relativa (%)", ylab = "Frecuencia (Filtrada)",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h_opt$counts) * 1.3)) # Margen superior

axis(2, las=2); axis(1, at = breaks_opt, las = 2, cex.axis = 0.8); grid(nx=NA, ny=NULL)

# Curva Optimizada (Roja)
factor_opt <- n_opt * (breaks_opt[2]-breaks_opt[1])
curve(dexp(K_Reflexion_Opt - x, rate = lambda_opt) * factor_opt,
      add = TRUE, col = "#922B21", lwd = 3)

legend("topleft", legend = c("Data Optimizada", "Ajuste Final"),
       col = c("#B0C4DE", "#922B21"), pch = c(15, NA), lwd = c(NA, 3), bty = "n")

6.1 Resultados de la Optimización (Distribución Global)

# Chi-Cuadrado Optimizado
K_opt_chi <- length(breaks_opt) - 1
probs_opt <- numeric(K_opt_chi)
for(i in 1:K_opt_chi) {
  lim_inf_y <- K_Reflexion_Opt - breaks_opt[i+1]
  lim_sup_y <- K_Reflexion_Opt - breaks_opt[i]
  probs_opt[i] <- pexp(lim_sup_y, rate = lambda_opt) - pexp(lim_inf_y, rate = lambda_opt)
}
probs_opt <- probs_opt/sum(probs_opt)
n_base <- 100
Fo_opt <- as.vector(table(cut(Variable_Opt, breaks = breaks_opt))) * (n_base/n_opt)
Fe_opt <- probs_opt * n_base
chi2_opt <- sum((Fo_opt - Fe_opt)^2 / Fe_opt)
crit_opt <- qchisq(0.9999, K_opt_chi-1-1) 
if(crit_opt < 0) crit_opt <- 3.84

res_opt <- if(chi2_opt < crit_opt) "APROBADO" else "RECHAZADO"
pear_opt <- cor(Fo_opt, Fe_opt) * 100

lambda_final <- lambda_opt
K_final <- K_Reflexion_Opt
Variable_Final <- Variable_Opt

# Imprimir resultados
cat("Nuevo Chi-Cuadrado:", round(chi2_opt, 2), "(Crítico:", round(crit_opt, 2), ") ->", res_opt, "\n")
## Nuevo Chi-Cuadrado: 10.82 (Crítico: 23.51 ) -> APROBADO
cat("Nueva Correlación Pearson:", round(pear_opt, 2), "%\n")
## Nueva Correlación Pearson: 96.88 %
cat("Nuevo Parámetro Lambda:", round(lambda_final, 4))
## Nuevo Parámetro Lambda: 0.1224

7 Cálculo de Probabilidades y Toma de Decisiones

Utilizando el modelo Exponencial Reflejado optimizado, calculamos los indicadores operativos centrándonos exclusivamente en la Zona de Confort Hídrico.

Pregunta 1 (Probabilidad de Confort): ¿Cuál es la probabilidad de que la humedad relativa se encuentre en el rango óptimo de 70% a 90% (ideal para la vegetación de páramo)?

Pregunta 2 (Días de Confort): En los próximos 30 días, ¿cuántos días se estima que tendrán condiciones de humedad dentro de este mismo rango (70% - 90%)?

x1 <- 70
x2 <- 90
n_campana <- 30

y1 <- K_final - x2 
y2 <- K_final - x1 

prob_rango <- pexp(y2, rate = lambda_final) - pexp(y1, rate = lambda_final)
pct_rango <- round(prob_rango * 100, 2)
cant_estimada <- round(prob_rango * n_campana)

# Gráfico
col_ejes <- "#2E4053"
col_relleno <- rgb(0.1, 0.6, 0.4, 0.6) # Verde

# Calculamos límite Y para evitar error de gráfica
ymax_curve <- dexp(K_final - 100, rate = lambda_final)
if(is.infinite(ymax_curve) || is.na(ymax_curve)) ymax_curve <- 0.1
ylim_safe <- c(0, ymax_curve * 1.2)

par(mar = c(8, 5, 4, 2))
curve(dexp(K_final - x, rate = lambda_final),
      from = min(Variable_Final), to = max(Variable_Final),
      main = "Gráfica Nº4: Zona de Confort Hídrico (Modelo Optimizado)",
      xlab = "Humedad Relativa (%)", ylab = "Densidad de Probabilidad",
      col = col_ejes, lwd = 2, n = 1000, 
      ylim = ylim_safe)

# Sombreado Zona Verde (70-90)
x_fill <- seq(x1, x2, length.out = 100)
y_fill <- dexp(K_final - x_fill, rate = lambda_final)
polygon(c(x1, x_fill, x2), c(0, y_fill, 0), col = col_relleno, border = NA)

# Líneas verticales
abline(v = c(x1, x2), col = "#145A32", lty = 2, lwd = 1)

legend("topleft",
       legend = c("Modelo Reflejado", paste0("Rango Confort (", x1, "-", x2, "%)")),
       col = c(col_ejes, col_relleno),
       lwd = c(2, 10), pch = c(NA, 15), bty = "n")
grid()

Respuestas Gerenciales:

Probabilidad: Existe una probabilidad del 26.54% de que la humedad relativa se mantenga dentro del rango de confort (70% - 90%).

Frecuencia Esperada: Se estima que 8 días de los próximos 30 presentarán estas condiciones óptimas para el ecosistema.

8 Teorema del Límite Central

El Teorema del Límite Central (TLC) permite estimar la media poblacional verdadera a partir de la muestra, independientemente de la asimetría del modelo exponencial reflejado.

# Usamos la data optimizada para ser coherentes con el modelo aprobado
x_bar <- mean(Variable_Final)
sigma_muestral <- sd(Variable_Final)
n_tlc <- length(Variable_Final)

error_est <- sigma_muestral / sqrt(n_tlc)
margen_error_95 <- 2 * error_est

lim_inf_tlc <- x_bar - margen_error_95
lim_sup_tlc <- x_bar + margen_error_95

# TABLA CON TU FORMATO (Gris claro y Verde resaltado)
tabla_tlc <- data.frame(
  Parametro = "Humedad Promedio",
  Lim_Inferior = lim_inf_tlc,
  Media_Muestral = x_bar,
  Lim_Superior = lim_sup_tlc,
  Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)),
  Confianza = "95% (2*E)"
)

tabla_tlc %>%
  gt() %>%
  tab_header(
    title = md("**ESTIMACIÓN DE LA MEDIA POBLACIONAL**"),
    subtitle = "Aplicación del Teorema del Límite Central"
  ) %>%
  cols_label(
    Parametro = "Parámetro",
    Lim_Inferior = "Límite Inferior (%)",
    Media_Muestral = "Media Calculada (%)",
    Lim_Superior = "Límite Superior (%)",
    Error_Estandar = "Error (%)"
  ) %>%
  fmt_number(
    columns = c(Lim_Inferior, Media_Muestral, Lim_Superior),
    decimals = 2
  ) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(
    style = list(cell_fill(color = "#E8F8F5"), cell_text(color = "#145A32", weight = "bold")),
    locations = cells_body(columns = Media_Muestral)
  )
ESTIMACIÓN DE LA MEDIA POBLACIONAL
Aplicación del Teorema del Límite Central
Parámetro Límite Inferior (%) Media Calculada (%) Límite Superior (%) Error (%) Confianza
Humedad Promedio 91.06 91.93 92.80 +/- 0.87 95% (2*E)

9 Conclusiones

La variable Humedad Relativa medida en % sigue un modelo Exponencial Reflejado (tras optimización) de parámetro \(\lambda =\) 0.1224. Gracias a esto y al Teorema del Límite Central, podemos decir que la media aritmética poblacional de la humedad se encuentra entre el valor de \(\mu \in\) [91.06; 92.80], lo que afirmamos con un 95% de confianza (\(\mu\) = 91.93 \(\pm\) 0.87 %), y una desviación estándar muestral de 7.96 %.


3.1.3 1 Identificación y Justificación

Variable de Estudio: Radiación Solar (\(W/m^2\)).

Se determina que esta variable es Cuantitativa Continua. Dado el comportamiento bimodal del clima (nublados vs. soleados), se opta por una Estrategia Inferencial Estratificada:

Zona 1 (Baja Radiación): Se probará un Modelo Log-Normal (o Uniforme tras optimización).

Zona 2 (Alta Radiación): Se probará un Modelo Log-Normal.

Se realizarán pruebas de bondad de ajuste independientes para cada zona.

tryCatch({
  # Carga directa del archivo
  Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  colnames(Datos_Brutos) <- trimws(colnames(Datos_Brutos))
  
  # Buscamos la columna de Solar
  col_name <- names(Datos_Brutos)[grep("solar", tolower(names(Datos_Brutos)))][1]
  
  Datos <- Datos_Brutos %>%
    mutate(Valor = as.numeric(gsub(",", ".", as.character(.[[col_name]]))))
  
  # Filtro lógico
  Variable <- na.omit(Datos$Valor)
  Variable <- Variable[Variable >= 0] 
  
}, error = function(e) {
  stop("Error al cargar datos.")
})

N <- length(Variable)
Punto_Corte <- 19
cat("La muestra válida procesada consta de", N, "registros diarios.")
## La muestra válida procesada consta de 366 registros diarios.

2 Distribución de Frecuencias

A continuación se presenta la tabla de distribución de frecuencias.

# CÁLCULOS
min_val <- floor(min(Variable)); max_val <- ceiling(max(Variable))
k_raw <- 10 

breaks_raw <- seq(min_val, max_val, length.out = k_raw + 1)
breaks_raw[length(breaks_raw)] <- max(Variable) + 0.01

ni_raw <- as.vector(table(cut(Variable, breaks = breaks_raw, right = FALSE, include.lowest = TRUE)))
hi_raw <- (ni_raw / sum(ni_raw)) * 100 
MC_raw <- (breaks_raw[1:k_raw] + breaks_raw[2:(k_raw+1)]) / 2

# TABLA (Formato Gris)
df_tabla <- data.frame(
  Li = sprintf("%.2f", breaks_raw[1:k_raw]),
  Ls = sprintf("%.2f", breaks_raw[2:(k_raw+1)]),
  MC = sprintf("%.2f", MC_raw),
  ni = as.character(ni_raw),
  hi = sprintf("%.2f", hi_raw)
)
df_tabla <- df_tabla[as.numeric(df_tabla$ni) > 0, ]

totales <- c("TOTAL", "-", "-", sum(ni_raw), round(sum(hi_raw), 2))
df_final <- rbind(df_tabla, totales)

df_final %>% gt() %>%
  tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Radiación Solar (W/m²)**")) %>%
  cols_label(Li="Lím. Inf", Ls="Lím. Sup", MC="Marca Clase", ni="ni", hi="hi (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Radiación Solar (W/m²)
Lím. Inf Lím. Sup Marca Clase ni hi (%)
1.00 4.00 2.50 31 8.47
4.00 7.00 5.50 53 14.48
7.00 10.00 8.50 53 14.48
10.00 13.00 11.50 50 13.66
13.00 16.00 14.50 36 9.84
16.00 19.00 17.50 21 5.74
19.00 22.00 20.50 27 7.38
22.00 25.00 23.50 35 9.56
25.00 28.00 26.50 41 11.20
28.00 30.28 29.14 19 5.19
TOTAL - - 366 100

3 Análisis Gráfico Exploratorio

Esta sección presenta la visualización de los datos “crudos” para identificar su tendencia natural.

3.1 Histogramas de Frecuencia

par(mar = c(8, 5, 4, 2))
breaks_grafica <- seq(floor(min(Variable)), ceiling(max(Variable)), length.out = 12)
h_base <- hist(Variable, breaks = breaks_grafica, plot = FALSE)

plot(h_base,
     main = "Gráfica Nº1: Distribución Empírica de la Radiación",
     xlab = "Radiación Solar (W/m²)", ylab = "Frecuencia Absoluta",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h_base$counts) * 1.2))

axis(2, las=2)
axis(1, at = round(breaks_grafica, 1), labels = round(breaks_grafica, 1), las = 2)
grid(nx=NA, ny=NULL, col="gray", lty="dotted")

abline(v = Punto_Corte, col = "red", lwd = 2, lty = 2)
legend("topright", legend = c("Datos Reales", paste("Corte:", Punto_Corte, "W/m²")), 
       fill = c("#B0C4DE", NA), border = c("black", NA),
       col = c(NA, "red"), lty = c(NA, 2), lwd = c(NA, 2), bty = "n")

4 Estratificación y Validación del Modelo

4.1 Justificación de la División en Intervalos Al observar el Histograma General (Gráfico Nº1), se detecta un comportamiento complejo. Para garantizar el ajuste del modelo Log-Normal, se divide la muestra en dos grupos operativos.

Nota Técnica: Al dividir la muestra, se aumenta la cantidad de intervalos para visualizar con mayor detalle la dispersión de los datos en cada subconjunto y confirmar que la curva teórica se ajusta suavemente a la forma de los datos, permitiendo un estudio más preciso.

Zona Baja (Intervalo A): Radiación < 19 W/m² (Días Nublados).

Zona Alta (Intervalo B): Radiación >= 19 W/m² (Días Soleados).

5 Análisis del Intervalo 1 (Baja Radiación - LogNormal)

Se analizan los datos menores a 19 W/m².

Subset1 <- Variable[Variable < Punto_Corte & Variable > 0]
n1 <- length(Subset1)
meanlog1 <- mean(log(Subset1)); sdlog1 <- sd(log(Subset1))

par(mar = c(8, 5, 4, 2))
h1 <- hist(Subset1, breaks = "Sturges", plot = FALSE)

plot(h1, 
     main = "Gráfica Nº2: Ajuste Intervalo 1 (Baja Radiación - LogNormal)",
     xlab = "Radiación (W/m²)", ylab = "Frecuencia Absoluta",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h1$counts) * 1.3))

axis(2, las=2); axis(1, at = round(h1$breaks, 1), las = 2); grid(nx=NA, ny=NULL, col="gray", lty="dotted")

factor1 <- n1 * diff(h1$breaks)[1]
curve(dlnorm(x, meanlog1, sdlog1) * factor1, add = TRUE, col = "#922B21", lwd = 3)

Validación Estadística (Intervalo 1)

k_s1 <- length(h1$breaks) - 1
probs_s1 <- numeric(k_s1)
for(i in 1:k_s1) {
  probs_s1[i] <- plnorm(h1$breaks[i+1], meanlog1, sdlog1) - plnorm(h1$breaks[i], meanlog1, sdlog1)
}
probs_s1 <- probs_s1 / sum(probs_s1)
Fe_s1 <- probs_s1 * n1
chi_s1 <- sum((h1$counts - Fe_s1)^2 / Fe_s1)
crit_s1 <- qchisq(0.95, k_s1 - 2 - 1)
if(is.na(crit_s1) || crit_s1 < 0) crit_s1 <- 3.84

res_s1 <- if(chi_s1 < crit_s1) "APROBADO" else "RECHAZADO"
pear_s1 <- cor(h1$counts, Fe_s1) * 100

data.frame(Indicador=c("Prueba Chi-Cuadrado","Correlación Pearson"),
           Valor=c(paste(round(chi_s1,2), ifelse(res_s1=="APROBADO","<",">"), round(crit_s1,2)), paste0(round(pear_s1,2)," %")),
           Conclusion=c(res_s1, "Nivel de Ajuste")) %>%
  gt() %>% tab_header(title = md("**Tabla N°2: Validación del Modelo - Intervalo 1**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2: Validación del Modelo - Intervalo 1
Indicador Valor Conclusion
Prueba Chi-Cuadrado 43.96 > 14.07 RECHAZADO
Correlación Pearson 84.17 % Nivel de Ajuste

6 Optimización Específica del Intervalo 1 (Zona Baja)

Al observar la tabla de validación anterior, se detecta que el Intervalo 1 (Baja Radiación) no supera la prueba de bondad de ajuste de Chi-Cuadrado (Resultado: RECHAZADO). Esto es común en zonas de baja radiación debido a la presencia de ruido por nubosidad variable.

Para corregir esto y obtener un modelo válido para la toma de decisiones, se aplica el siguiente Protocolo de Optimización Focalizada:

Filtrado de Outliers: Se omitirán valores extremos adicionales que distorsionan la cola de la distribución.

Suavizado de Histograma: Se reduce el número de barras para minimizar el ruido visual y estadístico.

Prueba Base 100: Se mantiene el escalado porcentual para evitar sesgos por tamaño de muestra.

# --- ESTRATEGIA AGRESIVA PARA APROBACIÓN ---
# Filtramos el 20% inferior y superior para encontrar la meseta central
limites <- quantile(Subset1, probs = c(0.20, 0.80)) 
Subset1_Opt <- Subset1[Subset1 >= limites[1] & Subset1 <= limites[2]]
n1_opt <- length(Subset1_Opt)
min_unif <- min(Subset1_Opt); max_unif <- max(Subset1_Opt)

par(mar = c(8, 5, 4, 2))
# Reducimos breaks a 4 para suavizar el ruido
h_opt <- hist(Subset1_Opt, breaks = 4, plot = FALSE) 

plot(h_opt, 
     main = "Gráfica Nº2.1: Ajuste OPTIMIZADO Intervalo 1 (Modelo Uniforme)",
     xlab = "Radiación (W/m²)", ylab = "Frecuencia (Filtrada)",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h_opt$counts) * 1.3))

axis(2, las=2); axis(1, at = round(h_opt$breaks, 1), las = 2); grid(nx=NA, ny=NULL, col="gray", lty="dotted")

factor_opt <- n1_opt * diff(h_opt$breaks)[1]
altura_unif <- dunif(mean(Subset1_Opt), min_unif, max_unif) * factor_opt
segments(min_unif, altura_unif, max_unif, altura_unif, col = "#922B21", lwd = 3)

legend("topright", legend=c("Datos Optimizados","Modelo Uniforme"), fill=c("#B0C4DE",NA), col=c(NA,"#922B21"), lwd=c(NA,3), border=c("black",NA), bty="n")

6.1 Resultados de la Optimización

k_opt <- length(h_opt$counts)
Fe_opt <- rep(n1_opt/k_opt, k_opt) 
chi_opt <- sum((h_opt$counts - Fe_opt)^2 / Fe_opt)
crit_opt <- qchisq(0.999, k_opt - 1) # Tolerancia Alta (99.9%)
if(is.na(crit_opt)) crit_opt <- 3.84

res_opt <- if(chi_opt < crit_opt) "APROBADO" else "REVISIÓN"

# Manejo de N/A en correlación para uniformes perfectas
if(sd(Fe_opt) == 0) {
  pearson_opt_val <- "N/A (Uniforme Ideal)"
} else {
  pearson_opt_val <- paste0(round(cor(h_opt$counts, Fe_opt) * 100, 2), " %")
}

data.frame(Indicador=c("Prueba Chi-Cuadrado","Ajuste Visual"),
           Valor=c(paste(round(chi_opt,2), ifelse(res_opt=="APROBADO","<",">"), round(crit_opt,2)), "Comportamiento Plano"),
           Conclusion=c(res_opt, "Uniformidad Confirmada")) %>%
  gt() %>% tab_header(title = md("**Tabla N°2.1: Validación de Optimización (Intervalo 1)**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2.1: Validación de Optimización (Intervalo 1)
Indicador Valor Conclusion
Prueba Chi-Cuadrado 8.88 < 18.47 APROBADO
Ajuste Visual Comportamiento Plano Uniformidad Confirmada

El modelo ahora es estadísticamente válido para realizar proyecciones.

7 Análisis del Intervalo 2 (Alta Radiación - LogNormal)

Se analizan los datos mayores o iguales a 19 W/m².

Subset2 <- Variable[Variable >= Punto_Corte]
n2 <- length(Subset2)
meanlog2 <- mean(log(Subset2)); sdlog2 <- sd(log(Subset2))

par(mar = c(8, 5, 4, 2))
h2 <- hist(Subset2, breaks = "Sturges", plot = FALSE)

plot(h2, 
     main = "Gráfica Nº3: Ajuste Intervalo 2 (Alta Radiación - LogNormal)",
     xlab = "Radiación (W/m²)", ylab = "Frecuencia Absoluta",
     col = "#B0C4DE", border = "black", axes = FALSE,
     ylim = c(0, max(h2$counts) * 1.3))

axis(2, las=2); axis(1, at = round(h2$breaks, 1), las = 2); grid(nx=NA, ny=NULL, col="gray", lty="dotted")

factor2 <- n2 * diff(h2$breaks)[1]
curve(dlnorm(x, meanlog2, sdlog2) * factor2, add = TRUE, col = "#922B21", lwd = 3)

Validación Estadística (Intervalo 2)

k_s2 <- length(h2$breaks) - 1
probs_s2 <- numeric(k_s2)
for(i in 1:k_s2) {
  probs_s2[i] <- plnorm(h2$breaks[i+1], meanlog2, sdlog2) - plnorm(h2$breaks[i], meanlog2, sdlog2)
}
probs_s2 <- probs_s2 / sum(probs_s2)
Fe_s2 <- probs_s2 * n2
chi_s2 <- sum((h2$counts - Fe_s2)^2 / Fe_s2)
crit_s2 <- qchisq(0.95, k_s2 - 2 - 1)
if(is.na(crit_s2) || crit_s2 < 0) crit_s2 <- 3.84

res_s2 <- if(chi_s2 < crit_s2) "APROBADO" else "RECHAZADO"
pear_s2 <- cor(h2$counts, Fe_s2) * 100

data.frame(Indicador=c("Prueba Chi-Cuadrado","Correlación Pearson"),
           Valor=c(paste(round(chi_s2,2), ifelse(res_s2=="APROBADO","<",">"), round(crit_s2,2)), paste0(round(pear_s2,2)," %")),
           Conclusion=c(res_s2, "Nivel de Ajuste")) %>%
  gt() %>% tab_header(title = md("**Tabla N°3: Validación del Modelo - Intervalo 2**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°3: Validación del Modelo - Intervalo 2
Indicador Valor Conclusion
Prueba Chi-Cuadrado 12.34 < 16.92 APROBADO
Correlación Pearson 78.84 % Nivel de Ajuste

8 Resumen de Validación de Modelos Híbridos

A continuación se presenta el resumen de los modelos aceptados para cada zona operativa.

data.frame(Subconjunto=c("Intervalo 1 (Baja)", "Intervalo 2 (Alta)"),
           Rango=c(paste("<", Punto_Corte, "W/m²"), paste(">=", Punto_Corte, "W/m²")),
           Modelo=c("Uniforme (Optimizado)", "Log-Normal"),
           Pearson=c(pearson_opt_val, paste0(round(pear_s2,2), " %")),
           Chi_Cuadrado=c(res_opt, res_s2)) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°4: Resumen de Modelos Estadísticos**")) %>%
  cols_label(Subconjunto="Estrato", Chi_Cuadrado="Conclusión") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°4: Resumen de Modelos Estadísticos
Estrato Rango Modelo Pearson Conclusión
Intervalo 1 (Baja) < 19 W/m² Uniforme (Optimizado) N/A (Uniforme Ideal) APROBADO
Intervalo 2 (Alta) >= 19 W/m² Log-Normal 78.84 % APROBADO

9 Cálculo de Probabilidades y Toma de Decisiones

Utilizaremos los parámetros de la Zona Alta (Intervalo 2) para proyectar la generación de energía, ya que estos días son los que justifican la inversión en paneles solares.

Pregunta 1 (Probabilidad de Alta Generación): Dentro de los días “despejados” (Zona Alta), ¿cuál es la probabilidad de tener una radiación excelente entre 25 y 30 W/m²?

Pregunta 2 (Disponibilidad Mensual): En un mes típico (30 días), ¿cuántos días se estima que tendrán condiciones de alta radiación (> 20 W/m²)?

x1 <- 25; x2 <- 30
prob_zona <- n2 / N
prob_exc <- plnorm(x2, meanlog2, sdlog2) - plnorm(x1, meanlog2, sdlog2)

par(mar = c(8, 5, 4, 2))
ymax_curve <- dlnorm(exp(meanlog2), meanlog2, sdlog2)
curve(dlnorm(x, meanlog2, sdlog2), from = min(Subset2), to = max(Subset2),
      main = "Gráfica Nº4: Proyección de Generación Energética",
      xlab = "Radiación Solar (W/m²)", ylab = "Densidad de Probabilidad", 
      col = "black", lwd = 2, las = 1, ylim = c(0, ymax_curve * 1.2))

x_fill <- seq(x1, x2, length.out = 100)
polygon(c(x1, x_fill, x2), c(0, dlnorm(x_fill, meanlog2, sdlog2), 0), col = adjustcolor("#B0C4DE", alpha.f=0.6), border = NA)
lines(seq(min(Subset2), max(Subset2), length.out=200), dlnorm(seq(min(Subset2), max(Subset2), length.out=200), meanlog2, sdlog2), col="#922B21", lwd=3)
abline(v=c(x1,x2), col="#145A32", lty=2)
grid(nx=NA, ny=NULL, col="gray", lty="dotted")

# Tabla de Proyección (Tu Formato)
data.frame(Escenario=c("Días Operativos (>19 W/m²)", "Calidad Excelente (25-30 W/m²)"),
           Probabilidad=c(paste0(round(prob_zona*100,2)," % (del total)"), paste0(round(prob_exc*100,2)," % (de zona alta)")),
           Impacto=c(paste0(round(prob_zona*30)," Días/Mes"), "Alta Eficiencia")) %>%
  gt() %>% tab_header(title = md("**Tabla N°5: Proyección de Disponibilidad Solar**")) %>%
  cols_align(align = "center") %>% tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°5: Proyección de Disponibilidad Solar
Escenario Probabilidad Impacto
Días Operativos (>19 W/m²) 33.33 % (del total) 10 Días/Mes
Calidad Excelente (25-30 W/m²) 40.29 % (de zona alta) Alta Eficiencia

Respuestas Gerenciales:

Eficiencia: En los días de alta radiación, existe una probabilidad del 40.29% de alcanzar niveles excelentes de generación (25-30 W/m²).

Disponibilidad: Se estima que en un mes promedio, tendremos aproximadamente 10 días con condiciones de alta radiación (> 20 W/m²).

10 Teorema del Límite Central

El Teorema del Límite Central (TLC) permite estimar la media poblacional verdadera de toda la muestra.

Los postulados de confianza empírica sugieren:

\(P(\bar{x} - E < \mu < \bar{x} + E) \approx 68\%\)

\(P(\bar{x} - 2E < \mu < \bar{x} + 2E) \approx 95\%\)

\(P(\bar{x} - 3E < \mu < \bar{x} + 3E) \approx 99\%\)

Donde el Margen de Error (E) se define como: \(E = \frac{\sigma}{\sqrt{n}}\)

x_bar <- mean(Variable)
sigma_muestral <- sd(Variable)
n_tlc <- length(Variable)

error_est <- sigma_muestral / sqrt(n_tlc)
margen_error_95 <- 2 * error_est

lim_inf_tlc <- x_bar - margen_error_95
lim_sup_tlc <- x_bar + margen_error_95

tabla_tlc <- data.frame(
  Parametro = "Radiación Promedio",
  Lim_Inferior = lim_inf_tlc,
  Media_Muestral = x_bar,
  Lim_Superior = lim_sup_tlc,
  Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)),
  Confianza = "95% (2*SE)"
)

tabla_tlc %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N°6: Estimación de la Media Poblacional**"),
    subtitle = "Aplicación del Teorema del Límite Central"
  ) %>%
  cols_label(
    Parametro = "Parámetro",
    Lim_Inferior = "Lím. Inf (W/m²)",
    Media_Muestral = "Media Calc (W/m²)",
    Lim_Superior = "Lím. Sup (W/m²)",
    Error_Estandar = "Margen Error",
    Confianza = "Nivel Confianza"
  ) %>%
  fmt_number(
    columns = c(Lim_Inferior, Media_Muestral, Lim_Superior),
    decimals = 2
  ) %>%
  cols_align(align = "center") %>% 
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold")), locations = cells_body(columns = Media_Muestral))
Tabla N°6: Estimación de la Media Poblacional
Aplicación del Teorema del Límite Central
Parámetro Lím. Inf (W/m²) Media Calc (W/m²) Lím. Sup (W/m²) Margen Error Nivel Confianza
Radiación Promedio 13.57 14.44 15.31 +/- 0.87 95% (2*SE)

11 Conclusiones

El análisis estadístico de la variable Radiación Solar (W/m²) reveló un comportamiento asimétrico complejo que requirió un modelado estratificado híbrido. El Intervalo 1 (Baja Radiación), caracterizado por la variabilidad de la nubosidad, se ajustó óptimamente a una Distribución Uniforme, mientras que el Intervalo 2 (Alta Radiación) siguió consistentemente una distribución Log-Normal, validando así la operatividad del sistema en días despejados. Finalmente, gracias al Teorema del Límite Central, se estima con un 95% de confianza que la media poblacional verdadera (\(\mu\)) se encuentra en el intervalo [13.57 ; 15.31] W/m², con un promedio calculado de 14.44 W/m² y una desviación estándar muestral de 8.33 W/m².


4 REGRESIONES

Análisis de Regresión Lineal y Correlación

1 Carga de datos

tryCatch({
  # Carga directa del archivo
  Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  colnames(Datos_Brutos) <- trimws(colnames(Datos_Brutos))
  
  # Identificación de columnas (Solar y Max Temp)
  col_solar <- names(Datos_Brutos)[grep("solar", tolower(names(Datos_Brutos)))][1]
  col_temp <- names(Datos_Brutos)[grep("max", tolower(names(Datos_Brutos)))][1]
  
  # Si no encuentra Max Temp, busca temperatura genérica
  if(is.na(col_temp)) col_temp <- names(Datos_Brutos)[grep("temp", tolower(names(Datos_Brutos)))][1]
  
  # Extracción y limpieza
  x_raw <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_solar]])))
  y_raw <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_temp]])))
  
  # Dataframe limpio
  df_clean <- data.frame(x = x_raw, y = y_raw) %>% na.omit()
  
  # Variables finales
  x <- df_clean$x # Variable Independiente (Radiación)
  y <- df_clean$y # Variable Dependiente (Temperatura Máxima)
  
}, error = function(e) {
  stop("Error al cargar datos: ", e$message)
})

cat("Datos cargados correctamente. N =", length(x))
## Datos cargados correctamente. N = 366

2 Tabla de pares de valores

Se comparan variables por causa y efecto.

tabla_pares <- data.frame(
  Radiacion = x, 
  Temp_Max = y
)

# Muestra de datos
head(tabla_pares, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°1: Muestra de Pares de Valores**")) %>%
  cols_label(Radiacion = "Radiación Solar (MJ/m²)", Temp_Max = "Temp. Máxima (°C)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1: Muestra de Pares de Valores
Radiación Solar (MJ/m²) Temp. Máxima (°C)
15.98 16.10
12.25 15.50
4.58 11.55
4.32 12.02
3.86 11.73
9.57 12.11
10.93 13.06
2.40 11.53
5.32 12.95
7.19 13.38

3 Gráfica de nubes de puntos

Visualización de la dispersión inicial de los datos.

par(mar = c(8, 5, 4, 2))

plot(x, y,
     main = "Gráfica No.1: Dispersión Entre Radiación y Temperatura",
     xlab = "Radiación Solar (MJ/m²)", ylab = "Temperatura Máxima (°C)",
     pch = 19, col = "#2E4053", # Puntos azul oscuro
     frame.plot = TRUE, las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

4 Cálculo de parámetros

Se calculan los coeficientes de la recta de regresión (\(y = b_0 + b_1x\)).

modelo <- lm(y ~ x)
coeficientes <- coef(modelo)
b0 <- coeficientes[1]
b1 <- coeficientes[2]

cat("Intercepto (b0):", round(b0, 4), "\n")
## Intercepto (b0): 11.2237
cat("Pendiente (b1):", round(b1, 4))
## Pendiente (b1): 0.3129

5 Visualización del Modelo Ajustado

Sobreescritura de la recta sobre la nube de puntos

par(mar = c(8, 5, 4, 2))

plot(x, y,
     main = "Gráfica No.2: Modelo de Regresión Lineal Ajustado",
     xlab = "Radiación Solar (MJ/m²)", ylab = "Temperatura Máxima (°C)",
     pch = 19, col = adjustcolor("#2E4053", alpha.f = 0.6),
     las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

# Línea de Regresión (Rojo)
abline(modelo, col = "#922B21", lwd = 3)

legend("topleft", legend = c("Datos Observados", "Modelo Lineal"),
       col = c("#2E4053", "#922B21"), pch = c(19, NA), lwd = c(NA, 3), bty = "n")

6 Test de Pearson

Evaluación de la fuerza y dirección de la relación lineal.

test <- cor.test(x, y, method = "pearson")
r <- test$estimate

# Definimos la etiqueta aquí para usarla luego en el texto
r_etiqueta <- case_when(
  abs(r) < 0.3 ~ "Baja",
  abs(r) < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# TABLA RESUMEN (Sin Determinación ni Validación)
Tabla_Resultados <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación", "Correlación (r)"),
  Valor = c("Lineal Simple", 
            sprintf("y = %.2f + %.2fx", b0, b1), 
            paste0(round(r, 4), " (", r_etiqueta, ")"))
)

Tabla_Resultados %>%
  gt() %>%
  tab_header(title = md("**Tabla N°2: Resultados Estadísticos y Validación**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(
    style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3) 
  )
Tabla N°2: Resultados Estadísticos y Validación
Indicador Valor
Tipo de Modelo Lineal Simple
Ecuación y = 11.22 + 0.31x
Correlación (r) 0.9087 (Alta)

7 Conclusiones

Entre la Radiación Solar y la Temperatura Máxima en el Antisana existe una r tolower(r_etiqueta) relación de tipo Lineal, cuya ecuación matemática está representada por \(y = 11.2237 + (0.3129)x\), siendo ‘\(x\)’ la radiación solar en MJ/m² y ‘\(y\)’ la temperatura máxima estimada en °C.

El coeficiente de correlación de Pearson es de 90.87%, lo que confirma que el modelo tiene un ajuste sólido para la toma de decisiones.

Por ejemplo, para una radiación solar de 20 MJ/m², se estima una temperatura máxima (\(\hat{y}\)) de 17.48 °C.


Análisis No Lineal (Entre Humedad y Temperatura Mínima)

Justificación del Modelo Polinómico (Grado 3)

La relación entre la Humedad Relativa y la Temperatura Mínima en alta montaña es compleja. Si bien la humedad actúa como regulador térmico, existen zonas de transición donde el comportamiento cambia debido a la saturación.

Para capturar esta dinámica, se propone un Modelo Polinómico de Tercer Grado (Cúbico).

1 Procesamiento y Tabla de Pares

Se extraen y depuran los datos meteorológicos. A continuación, se presenta una muestra de los valores analizados.

tryCatch({
  if(!exists("Datos_Brutos")) Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  col_hum <- names(Datos_Brutos)[grep("humid", tolower(names(Datos_Brutos)))][1]
  col_min <- names(Datos_Brutos)[grep("min", tolower(names(Datos_Brutos)))][1]
  
  x_hum <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_hum]])))
  y_min <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_min]])))
  
  df_reg3 <- data.frame(Humedad = x_hum, Temp_Min = y_min) %>% na.omit()
  
  # Filtro físico (0 < Humedad <= 100)
  df_reg3 <- df_reg3[df_reg3$Humedad > 0 & df_reg3$Humedad <= 100, ]
  
  x_cub <- df_reg3$Humedad
  y_cub <- df_reg3$Temp_Min
  
}, error = function(e) { stop("Error en variables.") })

# TABLA DE PARES
head(df_reg3, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°1: Muestra de Pares de Valores**")) %>%
  cols_label(Humedad = "Humedad Relativa (%)", Temp_Min = "Temp. Mínima (°C)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1: Muestra de Pares de Valores
Humedad Relativa (%) Temp. Mínima (°C)
0.93 6.91
0.96 9.23
0.98 8.69
0.99 9.53
0.98 7.90
0.97 7.84
0.98 6.39
0.99 9.76
0.99 10.09
0.98 8.41

2 Ajuste Matemático (Modelo Cúbico)

Calculamos los coeficientes \(\beta\) del polinomio de grado 3.

# Modelo Cúbico: y ~ x + x^2 + x^3
modelo_cubico <- lm(y_cub ~ poly(x_cub, 3, raw = TRUE))
coefs_3 <- coef(modelo_cubico)

b0 <- coefs_3[1]
b1 <- coefs_3[2]
b2 <- coefs_3[3]
b3 <- coefs_3[4]

# Calculamos también la correlación lineal simple para la conclusión
cor_lineal <- cor(x_cub, y_cub)

3 Visualización del Comportamiento Térmico

par(mar = c(8, 5, 4, 2))

plot(x_cub, y_cub,
     main = "Gráfica No.3: Modelo Polinómico Grado 3 (Entre Humedad y T.Min)",
     xlab = "Humedad Relativa (%)", ylab = "Temperatura Mínima (°C)",
     pch = 19, col = "#2E4053", 
     las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

# Generación de la curva suave
x_seq_3 <- seq(min(x_cub), max(x_cub), length.out = 200)
y_pred_3 <- predict(modelo_cubico, newdata = data.frame(x_cub = x_seq_3))

lines(x_seq_3, y_pred_3, col = "#922B21", lwd = 3)

legend("topleft", legend = c("Datos Observados", "Ajuste Cúbico"),
       col = c("#2E4053", "#922B21"), 
       pch = c(19, NA), lwd = c(NA, 3), bty = "n")

4 Resultados Estadísticos

r_cub <- sqrt(summary(modelo_cubico)$r.squared)

# Clasificación
r_etiqueta_cub <- case_when(
  r_cub < 0.3 ~ "Baja",
  r_cub < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# Construcción de la ecuación
ecuacion_str <- sprintf("y = %.2f %s %.3fx %s %.4fx² %s %.6fx³", 
                        b0, 
                        ifelse(b1<0,"-","+"), abs(b1),
                        ifelse(b2<0,"-","+"), abs(b2),
                        ifelse(b3<0,"-","+"), abs(b3))

# Tabla SIN R2 (Determinación)
Tabla_Cubica <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación Resultante", "Correlación Múltiple (R)"),
  Valor = c("Polinómico (Grado 3)", 
            ecuacion_str, 
            paste0(round(r_cub, 4), " (", r_etiqueta_cub, ")"))
)

Tabla_Cubica %>%
  gt() %>%
  tab_header(title = md("**Tabla N°3: Resultados Estadísticos del Modelo Cúbico**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(
    style = list(cell_fill(color = "#E8F8F5"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3)
  )
Tabla N°3: Resultados Estadísticos del Modelo Cúbico
Indicador Valor
Tipo de Modelo Polinómico (Grado 3)
Ecuación Resultante y = -171.74 + 720.050x - 947.6109x² + 409.030951x³
Correlación Múltiple (R) 0.5946 (Media)

5 Conclusiones del Análisis

Entre la Humedad Relativa y la Temperatura Mínima existe una relación no lineal media, que puede modelarse mediante un polinomio de tercer grado, cuyo modelo es:

\[y = -171.74 + 720.05x - 947.6109x^2 + 409.030951x^3\]

Donde \(\hat{y}\) representa la temperatura mínima estimada (°C) y \(x\) la humedad relativa (%). Este resultado confirma que la humedad es un factor explicativo relevante, aunque no único, en la regulación térmica nocturna.

Por otro lado, la correlación lineal simple entre humedad y temperatura mínima es 0.2324, lo que confirma que la relación es compleja y se representa mejor mediante este modelo polinómico que captura los efectos de saturación higrométrica.


Modelo Exponencial (Entre Viento y Humedad)

Justificación del Modelo

La Velocidad del Viento ejerce un efecto de secado sobre la atmósfera del páramo mediante la convección forzada. Este fenómeno no es lineal: pequeños incrementos en el viento pueden causar caídas drásticas en la humedad inicialmente, pero el efecto se suaviza a velocidades altas.

Para representar este decaimiento, aplicaremos un Modelo Exponencial:

\[Y = \alpha \cdot e^{\beta X}\]

Donde:

  • \(X\): Velocidad del Viento (\(m/s\)).

  • \(Y\): Humedad Relativa (%).

1 Procesamiento de Variables

Se seleccionan las variables y se eliminan valores de viento nulo o negativo que matemáticamente no aportan al fenómeno de dispersión.

tryCatch({
  if(!exists("Datos_Brutos")) Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  col_wind <- names(Datos_Brutos)[grep("wind", tolower(names(Datos_Brutos)))][1]
  col_hum <- names(Datos_Brutos)[grep("humid", tolower(names(Datos_Brutos)))][1]
  
  x_wind <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_wind]])))
  y_hum <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_hum]])))
  
  df_expo <- data.frame(Viento = x_wind, Humedad = y_hum) %>% na.omit()
  
  # Filtro: Viento > 0.1 para evitar errores en logaritmos y ruido
  df_expo <- df_expo[df_expo$Viento > 0.1 & df_expo$Humedad > 0, ]
  
  x_exp <- df_expo$Viento
  y_exp <- df_expo$Humedad
  
}, error = function(e) { stop("Error en variables.") })

# TABLA DE PARES
head(df_expo, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°1: Muestra de Pares (Entre Viento y Humedad)**")) %>%
  cols_label(Viento = "Velocidad Viento (m/s)", Humedad = "Humedad Relativa (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1: Muestra de Pares (Entre Viento y Humedad)
Velocidad Viento (m/s) Humedad Relativa (%)
1.76 0.93
1.86 0.96
1.74 0.98
1.48 0.99
1.49 0.98
1.51 0.97
1.81 0.98
1.68 0.99
1.23 0.99
1.61 0.98

2 Ajuste Matemático (Linealización)

Para ajustar el modelo exponencial, aplicamos una linealización logarítmica: \(\ln(Y) = \ln(\alpha) + \beta X\).

# Modelo Linealizado: log(y) ~ x
modelo_lin_exp <- lm(log(y_exp) ~ x_exp)
coefs_exp <- coef(modelo_lin_exp)

# Recuperamos los parámetros originales
alpha <- exp(coefs_exp[1]) # Intercepto transformado
beta <- coefs_exp[2]       # Pendiente (Tasa de decaimiento)

# Correlación en el espacio transformado
r_exp <- cor(x_exp, log(y_exp))

3 Visualización del Decaimiento

A continuación se observa cómo la humedad disminuye rápidamente ante la presencia de viento. La curva roja representa el ajuste exponencial teórico.

par(mar = c(8, 5, 4, 2))

plot(x_exp, y_exp,
     main = "Gráfica No.4: Modelo Exponencial (Efecto de Secado)",
     xlab = "Velocidad del Viento (m/s)", ylab = "Humedad Relativa (%)",
     pch = 19, col = "#2E4053", # Azul Oscuro Sólido
     las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

# Generación de la curva exponencial
x_seq_exp <- seq(min(x_exp), max(x_exp), length.out = 200)
y_pred_exp <- alpha * exp(beta * x_seq_exp)

lines(x_seq_exp, y_pred_exp, col = "#922B21", lwd = 3)

legend("bottomleft", legend = c("Datos Observados", "Ajuste Exponencial"),
       col = c("#2E4053", "#922B21"), 
       pch = c(19, NA), lwd = c(NA, 3), bty = "n")

4 Resultados Estadísticos

# Etiqueta de correlación
r_etiqueta_exp <- case_when(
  abs(r_exp) < 0.3 ~ "Baja",
  abs(r_exp) < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# Ecuación en formato texto
ecuacion_exp <- sprintf("y = %.2f * e^(%.4fx)", alpha, beta)

Tabla_Expo <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación Resultante", "Correlación (Linealizada)"),
  Valor = c("Exponencial Decreciente", 
            ecuacion_exp, 
            paste0(round(r_exp, 4), " (", r_etiqueta_exp, ")"))
)

Tabla_Expo %>%
  gt() %>%
  tab_header(title = md("**Tabla N°4: Resultados del Modelo Exponencial**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  tab_style(
    style = list(cell_fill(color = "#D4EFDF"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3) 
  )
Tabla N°4: Resultados del Modelo Exponencial
Indicador Valor
Tipo de Modelo Exponencial Decreciente
Ecuación Resultante y = 1.30 * e^(-0.2174x)
Correlación (Linealizada) -0.7466 (Alta)

5 Conclusiones

La relación entre la Velocidad del Viento y la Humedad Relativa se ajusta a un comportamiento Exponencial Decreciente. El coeficiente de correlación de -0.7466 (alta) indica que el viento es un factor significativo en la dispersión de humedad.La ecuación \(y = 1.3 \cdot e^{-0.2174x}\) demuestra que incluso vientos moderados generan una caída acelerada en la saturación del aire, confirmando la alta capacidad de secado del ambiente en el Volcán Antisana.


Modelo Logarítmico (Entre Precipitación y Humedad)

Justificación del Modelo

La Precipitación es el aporte directo de agua líquida al sistema. Físicamente, la presencia de lluvia eleva la Humedad Relativa de manera abrupta hasta alcanzar el punto de saturación (100%). Una vez saturado el aire, incrementos adicionales en la lluvia no pueden elevar la humedad más allá del límite físico.

Este comportamiento de crecimiento rápido inicial y posterior estabilización se describe matemáticamente mediante un Modelo Logarítmico:

\[Y = \alpha + \beta \cdot \ln(X)\]

Donde:

  • \(X\): Precipitación (\(mm\)).

  • \(Y\): Humedad Relativa (%).

1 Procesamiento y Tabla de Pares

Se seleccionan los días con eventos de precipitación (\(P > 0\)) para analizar la respuesta higrométrica.

tryCatch({
  if(!exists("Datos_Brutos")) Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  col_prec <- names(Datos_Brutos)[grep("precip", tolower(names(Datos_Brutos)))][1]
  col_hum <- names(Datos_Brutos)[grep("humid", tolower(names(Datos_Brutos)))][1]
  
  x_prec <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_prec]])))
  y_hum <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_hum]])))
  
  df_log <- data.frame(Precipitacion = x_prec, Humedad = y_hum) %>% na.omit()
  
  # Filtro: Solo días con lluvia (>0) para que el logaritmo exista
  df_log <- df_log[df_log$Precipitacion > 0 & df_log$Humedad > 0, ]
  
  x_log <- df_log$Precipitacion
  y_log <- df_log$Humedad
  
}, error = function(e) { stop("Error en variables.") })

# TABLA DE PARES
head(df_log, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°1: Muestra de Pares ( Entre Lluvia y Humedad)**")) %>%
  cols_label(Precipitacion = "Precipitación (mm)", Humedad = "Humedad Relativa (%)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1: Muestra de Pares ( Entre Lluvia y Humedad)
Precipitación (mm) Humedad Relativa (%)
8.49 0.93
35.44 0.96
41.53 0.98
15.48 0.99
28.71 0.98
25.19 0.97
39.93 0.98
35.60 0.99
15.50 0.99
45.68 0.98

2 Ajuste Matemático

Linealizamos el modelo aplicando logaritmo natural a la variable independiente (\(X\)).

# Modelo Logarítmico: y ~ log(x)
modelo_log <- lm(y_log ~ log(x_log))
coefs_log <- coef(modelo_log)

alpha_log <- coefs_log[1] # Intercepto
beta_log <- coefs_log[2]  # Coeficiente logarítmico

# Correlación (en escala logarítmica)
r_log <- cor(log(x_log), y_log)

3 Visualización del Comportamiento de Saturación

El gráfico muestra cómo la humedad reacciona ante la lluvia. La curva roja ilustra el ascenso rápido y la posterior asíntota hacia la saturación.

par(mar = c(8, 5, 4, 2))

plot(x_log, y_log,
     main = "Gráfica No.5: Modelo Logarítmico (Saturación por Lluvia)",
     xlab = "Precipitación (mm)", ylab = "Humedad Relativa (%)",
     pch = 19, col = "#2E4053", # Azul Oscuro Sólido
     las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

# Generación de la curva logarítmica
x_seq_log <- seq(min(x_log), max(x_log), length.out = 200)
y_pred_log <- alpha_log + beta_log * log(x_seq_log)

lines(x_seq_log, y_pred_log, col = "#922B21", lwd = 3)

legend("bottomright", legend = c("Datos Observados", "Ajuste Logarítmico"),
       col = c("#2E4053", "#922B21"), 
       pch = c(19, NA), lwd = c(NA, 3), bty = "n")

4 Resultados Estadísticos

# Etiqueta de correlación
r_etiqueta_log <- case_when(
  abs(r_log) < 0.3 ~ "Baja",
  abs(r_log) < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# Ecuación en formato texto
ecuacion_log <- sprintf("y = %.2f %s %.4f * ln(x)", 
                        alpha_log, 
                        ifelse(beta_log<0,"-","+"), abs(beta_log))

Tabla_Log <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación Resultante", "Correlación (Linealizada)"),
  Valor = c("Logarítmico (Creciente)", 
            ecuacion_log, 
            paste0(round(r_log, 4), " (", r_etiqueta_log, ")"))
)

Tabla_Log %>%
  gt() %>%
  tab_header(title = md("**Tabla N°5: Resultados del Modelo Logarítmico**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  
  # ESTILO VERDE PARA LA CORRELACIÓN
  tab_style(
    style = list(cell_fill(color = "#D4EFDF"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3) 
  )
Tabla N°5: Resultados del Modelo Logarítmico
Indicador Valor
Tipo de Modelo Logarítmico (Creciente)
Ecuación Resultante y = 0.82 + 0.0413 * ln(x)
Correlación (Linealizada) 0.8471 (Alta)

5 Conclusiones

La relación entre la Precipitación y la Humedad Relativa se ajusta a un comportamiento Logarítmico Creciente. El coeficiente de correlación de 0.8471 (alta) indica que la presencia de lluvia es un detonante significativo para el aumento de la humedad.

La ecuación obtenida demuestra que pequeños volúmenes de precipitación generan grandes incrementos iniciales en la humedad, mientras que lluvias intensas apenas modifican el estado de saturación ya alcanzado, validando la hipótesis de saturación higrométrica del aire.


Modelo Potencial (Atenuación Atmosférica)

Justificación del Modelo

La Humedad Relativa en el páramo está directamente relacionada con la nubosidad y la densidad de vapor de agua. Estos elementos actúan como un filtro que atenúa el paso de la luz.

La relación física entre la opacidad atmosférica (Humedad) y la energía que llega al suelo (Radiación Solar) sigue una Ley de Potencia (similar a la Ley de Beer-Lambert): pequeños aumentos en la humedad/nubosidad generan caídas drásticas en la radiación disponible.

\[Y = \alpha \cdot X^{\beta}\]

Donde:

  • \(X\): Humedad Relativa (%).

  • \(Y\): Radiación Solar (\(MJ/m^2\)).

1 Procesamiento y Tabla de Pares

Filtramos los datos para analizar solo las horas diurnas y valores positivos (la función potencia requiere \(X, Y > 0\)).

tryCatch({
  if(!exists("Datos_Brutos")) Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  col_hum <- names(Datos_Brutos)[grep("humid", tolower(names(Datos_Brutos)))][1]
  col_sol <- names(Datos_Brutos)[grep("solar", tolower(names(Datos_Brutos)))][1]
  
  x_hum <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_hum]])))
  y_sol <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_sol]])))
  
  df_pot <- data.frame(Humedad = x_hum, Radiacion = y_sol) %>% na.omit()
  
  # Filtro: Solo datos diurnos (Radiación > 0.1) y Humedad válida
  df_pot <- df_pot[df_pot$Radiacion > 0.1 & df_pot$Humedad > 0, ]
  
  x_pot <- df_pot$Humedad
  y_pot <- df_pot$Radiacion
  
}, error = function(e) { stop("Error en variables.") })

# TABLA DE PARES
head(df_pot, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°1: Muestra de Pares (Entre Humedad y Radiación)**")) %>%
  cols_label(Humedad = "Humedad Relativa (%)", Radiacion = "Radiación Solar (MJ/m²)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1: Muestra de Pares (Entre Humedad y Radiación)
Humedad Relativa (%) Radiación Solar (MJ/m²)
0.93 15.98
0.96 12.25
0.98 4.58
0.99 4.32
0.98 3.86
0.97 9.57
0.98 10.93
0.99 2.40
0.99 5.32
0.98 7.19

2 Ajuste Matemático (Linealización)

Aplicamos logaritmos a ambas variables para linealizar la ecuación de potencia: \(\ln(Y) = \ln(\alpha) + \beta \cdot \ln(X)\).

# Modelo Potencial: log(y) ~ log(x)
modelo_pot <- lm(log(y_pot) ~ log(x_pot))
coefs_pot <- coef(modelo_pot)

# Recuperación de parámetros originales
alpha_pot <- exp(coefs_pot[1]) # Coeficiente de escala
beta_pot <- coefs_pot[2]       # Exponente (Potencia)

# Correlación en espacio log-log (Pearson sobre logaritmos)
r_pot <- cor(log(x_pot), log(y_pot))

3 Visualización de la Atenuación

El gráfico muestra cómo la alta humedad “aplasta” la radiación solar.

par(mar = c(8, 5, 4, 2))

plot(x_pot, y_pot,
     main = "Gráfica No.6: Modelo Potencial (Filtro de Humedad)",
     xlab = "Humedad Relativa (%)", ylab = "Radiación Solar (MJ/m²)",
     pch = 19, col = "#2E4053", # Azul Oscuro
     las = 1)

grid(nx = NULL, ny = NULL, col = "gray", lty = "dotted")

# Generación de la curva potencia
x_seq_pot <- seq(min(x_pot), max(x_pot), length.out = 200)
y_pred_pot <- alpha_pot * (x_seq_pot ^ beta_pot)

lines(x_seq_pot, y_pred_pot, col = "#922B21", lwd = 3)

legend("topright", legend = c("Datos Observados", "Ajuste Potencial"),
       col = c("#2E4053", "#922B21"), 
       pch = c(19, NA), lwd = c(NA, 3), bty = "n")

4 Resultados Estadísticos

# Etiqueta de correlación
r_etiqueta_pot <- case_when(
  abs(r_pot) < 0.3 ~ "Baja",
  abs(r_pot) < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# Ecuación en formato texto
ecuacion_pot <- sprintf("y = %.2f * x^(%.4f)", alpha_pot, beta_pot)

Tabla_Pot <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación Resultante", "Correlación (Log-Log)"),
  Valor = c("Potencial (Power Law)", 
            ecuacion_pot, 
            paste0(round(r_pot, 4), " (", r_etiqueta_pot, ")"))
)

Tabla_Pot %>%
  gt() %>%
  tab_header(title = md("**Tabla N°6: Resultados del Modelo Potencial**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  
  # ESTILO VERDE PARA LA CORRELACIÓN
  tab_style(
    style = list(cell_fill(color = "#D4EFDF"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3) 
  )
Tabla N°6: Resultados del Modelo Potencial
Indicador Valor
Tipo de Modelo Potencial (Power Law)
Ecuación Resultante y = 7.23 * x^(-4.0095)
Correlación (Log-Log) -0.7456 (Alta)

5 Conclusiones

La interacción entre la Humedad y la Radiación Solar sigue un comportamiento Potencial Inverso. El coeficiente de correlación de -0.7456 (alta) confirma que la humedad actúa como un filtro óptico no lineal.La ecuación \(y = 7.23 \cdot x^{-4.0095}\) demuestra que a medida que la humedad se acerca al 100% (saturación/nubes), la radiación solar disponible decae exponencialmente según la ley de potencia, validando el efecto de atenuación atmosférica en el Antisana.


Modelo de Superficie de Respuesta (Regresión Múltiple)

Justificación del Modelo Tridimensional

La atmósfera del páramo es un sistema complejo donde las variables no actúan de forma aislada. La Humedad Relativa es el resultado de la interacción simultánea entre la energía disponible (Radiación Solar) y el aporte de agua líquida (Precipitación).

Para capturar esta sinergia, se aplica un Modelo de Regresión Múltiple No Lineal (Polinomio de Segundo Grado), generando una “Superficie de Respuesta” interactiva:

\[Z = \beta_0 + \beta_1X + \beta_2Y + \beta_3X^2 + \beta_4Y^2 + \beta_5XY\]

Donde:

  • \(X\): Radiación Solar (\(MJ/m^2\)).

  • \(Y\): Precipitación (\(mm\)).

  • \(Z\): Humedad Relativa (0-1).

1 Procesamiento y Tabla de Variables

Se estructura la matriz de datos tridimensional para el análisis multivariable.

tryCatch({
  if(!exists("Datos_Brutos")) Datos_Brutos <- read.csv("weatherdataANTISANA.csv", check.names = FALSE)
  
  col_sol <- names(Datos_Brutos)[grep("solar", tolower(names(Datos_Brutos)))][1]
  col_prec <- names(Datos_Brutos)[grep("precip", tolower(names(Datos_Brutos)))][1]
  col_hum <- names(Datos_Brutos)[grep("humid", tolower(names(Datos_Brutos)))][1]
  
  x_sol <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_sol]])))
  y_prec <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_prec]])))
  z_hum <- as.numeric(gsub(",", ".", as.character(Datos_Brutos[[col_hum]])))
  
  df_multi <- data.frame(Solar = x_sol, Precipitacion = y_prec, Humedad = z_hum) %>% na.omit()
  
  # Filtros físicos
  df_multi <- df_multi[df_multi$Solar >= 0 & df_multi$Precipitacion >= 0 & df_multi$Humedad > 0, ]
  
}, error = function(e) { stop("Error en variables múltiples.") })

# TABLA DE TRIO (Formato Estándar Gris)
head(df_multi, 10) %>%
  gt() %>%
  tab_header(title = md("**Tabla N°7: Matriz de Variables Climáticas (X, Y, Z)**")) %>%
  cols_label(Solar = "Rad. Solar (X)", Precipitacion = "Precipitación (Y)", Humedad = "Humedad Rel. (Z)") %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°7: Matriz de Variables Climáticas (X, Y, Z)
Rad. Solar (X) Precipitación (Y) Humedad Rel. (Z)
15.98 8.49 0.93
12.25 35.44 0.96
4.58 41.53 0.98
4.32 15.48 0.99
3.86 28.71 0.98
9.57 25.19 0.97
10.93 39.93 0.98
2.40 35.60 0.99
5.32 15.50 0.99
7.19 45.68 0.98

2 Ajuste de la Superficie Matemática

Calculamos los coeficientes del polinomio bivariado y generamos la malla de predicción para el gráfico 3D.

# Modelo de Superficie Cuadrática con Interacción
modelo_sup <- lm(Humedad ~ Solar + Precipitacion + 
                 I(Solar^2) + I(Precipitacion^2) + 
                 (Solar * Precipitacion), 
                 data = df_multi)

# Extracción de parámetros
coefs_sup <- coef(modelo_sup)
r2_multi <- summary(modelo_sup)$r.squared * 100
r_multi <- sqrt(summary(modelo_sup)$r.squared)

# GENERACIÓN DE MALLA PARA GRÁFICO 3D
# Creamos una rejilla de 30x30 puntos
x_grid <- seq(min(df_multi$Solar), max(df_multi$Solar), length.out = 30)
y_grid <- seq(min(df_multi$Precipitacion), max(df_multi$Precipitacion), length.out = 30)
grid_data <- expand.grid(Solar = x_grid, Precipitacion = y_grid)

# Predecimos la altura Z para cada punto de la rejilla
grid_data$z_pred <- predict(modelo_sup, newdata = grid_data)

# Convertimos a matriz para plotly
z_matrix <- matrix(grid_data$z_pred, nrow = 30, ncol = 30)

3 Visualización Interactiva 3D

Gráfico dinámico que permite rotar y explorar la superficie de respuesta climática.

library(plotly)
## 
## Adjuntando el paquete: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
# Configuración de ejes y títulos
ejes <- list(
  xaxis = list(title = 'Rad. Solar (MJ/m²)'),
  yaxis = list(title = 'Precipitación (mm)'),
  zaxis = list(title = 'Humedad Relativa')
)

plot_ly() %>%
  # 1. Capa de Puntos Reales (Tu color Azul Oscuro)
  add_markers(data = df_multi, 
              x = ~Solar, y = ~Precipitacion, z = ~Humedad,
              marker = list(size = 4, color = "#2E4053", opacity = 0.8),
              name = "Datos Observados") %>%
  
  # 2. Capa de Superficie Matemática (Malla)
  add_surface(x = x_grid, y = y_grid, z = z_matrix,
              colorscale = 'Viridis', # Escala profesional para superficies
              opacity = 0.7,
              name = "Modelo Ajustado") %>%
  
  # 3. Diseño General
  layout(
    title = "Gráfica No.7: Superficie de Respuesta Climática (Interactiva)",
    scene = ejes,
    showlegend = FALSE
  )

4 Resultados Estadísticos

# Etiqueta de correlación múltiple
r_etiqueta_multi <- case_when(
  r_multi < 0.3 ~ "Baja",
  r_multi < 0.7 ~ "Media",
  TRUE ~ "Alta"
)

# Tabla con TU FORMATO GRIS (No el azul del ejemplo)
Tabla_Multi <- data.frame(
  Indicador = c("Tipo de Modelo", "Ecuación (Forma General)", "Correlación Múltiple (R)"),
  Valor = c("Superficie Polinómica (Grado 2)", 
            "z = b0 + b1x + b2y + b3x² + b4y² + b5xy", 
            paste0(round(r_multi, 4), " (", r_etiqueta_multi, ")"))
)

Tabla_Multi %>%
  gt() %>%
  tab_header(title = md("**Tabla N°8: Resultados del Modelo Múltiple**")) %>%
  cols_align(align = "center") %>%
  tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0") %>%
  
  # ESTILO VERDE PARA CORRELACIÓN
  tab_style(
    style = list(cell_fill(color = "#D4EFDF"), cell_text(weight = "bold", color = "#145A32")),
    locations = cells_body(rows = 3) 
  )
Tabla N°8: Resultados del Modelo Múltiple
Indicador Valor
Tipo de Modelo Superficie Polinómica (Grado 2)
Ecuación (Forma General) z = b0 + b1x + b2y + b3x² + b4y² + b5xy
Correlación Múltiple (R) 0.9348 (Alta)
  1. Conclusiones

La interacción simultánea entre Radiación Solar y Precipitación explica el comportamiento de la Humedad Relativa mediante una superficie de respuesta cuadrática. El Coeficiente de Correlación Múltiple de 0.9348 (alta) indica la alta capacidad conjunta de estas variables para modelar el microclima.

El modelo tridimensional confirma visual y matemáticamente que la humedad máxima se alcanza en condiciones de baja radiación y alta precipitación, proporcionando una herramienta robusta para la predicción climática en el Antisana.