1 Introducción y Metodología

El presente informe estadístico analiza la variable Temperatura Mínima registrada en la estación meteorológica del Antisana.

# 1. LIBRERÍAS Y CARGA DE DATOS

library(readxl)
library(dplyr)
library(gt)
library(e1071)

# Carga de datos 
Datos_Brutos <- read.csv("C:\\Users\\User\\Downloads\\datos_clima.antisana.csv", check.names = FALSE)
colnames(Datos_Brutos) <- trimws(colnames(Datos_Brutos))

# Selección y limpieza (Variable: Min Temperature)
Datos <- Datos_Brutos %>%
  select(any_of(c("Date", "Min Temperature"))) %>%
  mutate(Variable_Analisis = as.numeric(gsub(",", ".", as.character(`Min Temperature`))))

Variable <- na.omit(Datos$Variable_Analisis)
Variable <- Variable[Variable > -50 & Variable < 100]

if(length(Variable) == 0) {
  stop("ERROR: No hay datos válidos en la variable seleccionada.")
}

# 2. CÁLCULOS MATEMÁTICOS PARA LA TABLA

N <- length(Variable)

min_val <- min(Variable)
max_val <- max(Variable)
Rango <- max_val - min_val
K <- floor(1 + 3.322 * log10(N)) 
Amplitud <- Rango / K

breaks_table <- seq(min_val, max_val, length.out = K + 1)
breaks_table[length(breaks_table)] <- max_val + 0.0001 

lim_inf_table <- breaks_table[1:K]
lim_sup_table <- breaks_table[2:(K+1)]
MC <- (lim_inf_table + lim_sup_table) / 2

ni <- numeric(K)
for (i in 1:K) {
  if (i < K) {
    ni[i] <- length(Variable[Variable >= lim_inf_table[i] & Variable < lim_sup_table[i]])
  } else {
    ni[i] <- length(Variable[Variable >= lim_inf_table[i] & Variable <= lim_sup_table[i]])
  }
}

hi <- (ni / sum(ni)) * 100 
Ni_asc <- cumsum(ni)
Ni_desc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_desc <- rev(cumsum(rev(hi)))

TDF_Temp <- data.frame(
  Li = round(lim_inf_table, 2), 
  Ls = round(lim_sup_table, 2), 
  MC = round(MC, 2),            
  ni = ni, 
  hi = round(hi, 2),
  Ni_asc = Ni_asc, 
  Ni_desc = Ni_desc, 
  Hi_asc = round(Hi_asc, 2), 
  Hi_desc = round(Hi_desc, 2)
)

2 Distribución de Frecuencias

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

# Totales
totales <- c("TOTAL", "-", "-", sum(ni), round(sum(hi), 2), "-", "-", "-", "-")
TDF_Char <- TDF_Temp %>% mutate(across(everything(), as.character))
TDF_Final <- rbind(TDF_Char, totales)

TDF_Final %>%
  gt() %>%
  tab_header(
    title = md("**DISTRIBUCIÓN DE FRECUENCIAS - ANTISANA**"),
    subtitle = md("Variable: **Temperatura Mínima (°C)**")
  ) %>%
  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 (%)", 
    Ni_asc = "Ni (Asc)", Ni_desc = "Ni (Desc)",
    Hi_asc = "Hi (Asc)", Hi_desc = "Hi (Desc)"
  ) %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_style(
    style = list(cell_fill(color = "#2E4053"), cell_text(color = "white", weight = "bold")),
    locations = cells_title()
  ) %>%
  tab_style(
    style = list(cell_fill(color = "#F2F3F4"), cell_text(weight = "bold", color = "#2E4053")),
    locations = cells_column_labels()
  ) %>%
  tab_options(
    table.border.top.color = "#2E4053",
    table.border.bottom.color = "#2E4053",
    column_labels.border.bottom.color = "#2E4053",
    data_row.padding = px(6)
  )
DISTRIBUCIÓN DE FRECUENCIAS - ANTISANA
Variable: Temperatura Mínima (°C)
Lím. Inf Lím. Sup Marca Clase (Xi) 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 - - - -
Fuente: Datos Meteorológicos Antisana

3 Análisis Gráfico

Esta sección presenta la visualización de la distribución de los datos climáticos.

3.1 Histogramas de Frecuencia

col_gris_azulado <- "#5D6D7E" # Restaurado al color original
col_ejes <- "#2E4053"
h_base <- hist(Variable, breaks = "Sturges", plot = FALSE)

# GRÁFICO 1: Histograma Absoluto (Local)
par(mar = c(8, 5, 4, 2)) 
plot(h_base, 
     main = "Gráfica No.1: Distribución de Temperatura Mínima en Antisana",
     xlab = "Temperatura Mínima (°C)",
     ylab = "Frecuencia Absoluta (Días)",
     col = col_gris_azulado, border = "white", axes = FALSE,
     ylim = c(0, max(h_base$counts) * 1.1)) 

axis(1, at = round(h_base$breaks, 1), labels = format(round(h_base$breaks, 1), scientific = FALSE), las = 2, cex.axis = 0.7)
axis(2)
grid(nx=NA, ny=NULL, col="#D7DBDD", lty="dotted") 

# GRÁFICO 2: Histograma Global
par(mar = c(8, 5, 4, 2))
plot(h_base, 
     main = "Gráfica N°2: Distribución Global de Temperatura Mínima",
     xlab = "Temperatura Mínima (°C)",
     ylab = "Total Días",
     col = col_gris_azulado, border = "white", axes = FALSE, 
     ylim = c(0, sum(h_base$counts))) 

axis(1, at = round(h_base$breaks, 1), labels = format(round(h_base$breaks, 1), scientific = FALSE), las = 2, cex.axis = 0.7)
axis(2)
grid(nx=NA, ny=NULL, col="#D7DBDD", lty="dotted")

3.2 Gráficos Porcentuales

h_porc <- h_base
h_porc$counts <- (h_porc$counts / sum(h_porc$counts)) * 100
h_porc$density <- h_porc$counts 

# GRÁFICO 3: Porcentajes (Local)
par(mar = c(8, 5, 4, 2))
plot(h_porc,
     main = "Gráfica N°3: Distribución Porcentual de Temperatura Mínima",
     xlab = "Temperatura Mínima (°C)",
     ylab = "Porcentaje (%)",
     col = col_gris_azulado, border = "white", axes = FALSE, freq = TRUE,
     ylim = c(0, max(h_porc$counts)*1.2))

axis(1, at = round(h_base$breaks, 1), labels = format(round(h_base$breaks, 1), scientific = FALSE), las = 2, cex.axis = 0.7)
axis(2)
text(x = h_base$mids, y = h_porc$counts, label = paste0(round(h_porc$counts, 1), "%"), pos = 3, cex = 0.6, col = col_ejes)
grid(nx=NA, ny=NULL, col="#D7DBDD", lty="dotted") 

# GRÁFICO 4: Global Porcentual
par(mar = c(8, 5, 4, 2))
plot(h_porc,
     main = "Gráfica No.4: Distribución Porcentual Global (T. Mínima)",
     xlab = "Temperatura Mínima (°C)",
     ylab = "% del Total", 
     col = col_gris_azulado, border = "white", axes = FALSE, freq = TRUE,
     ylim = c(0, 100))

axis(1, at = round(h_base$breaks, 1), labels = format(round(h_base$breaks, 1), scientific = FALSE), las = 2, cex.axis = 0.7)
text(x = h_base$mids, y = h_porc$counts, label = paste0(round(h_porc$counts, 1), "%"), pos = 3, cex = 0.6, col = col_ejes)
axis(2)
abline(h=seq(0,100,20), col="#D7DBDD", lty="dotted")

3.3 Diagrama de Caja y Ojivas

# GRÁFICO 5: Boxplot
par(mar = c(5, 5, 4, 2))
boxplot(Variable, horizontal = TRUE, col = col_gris_azulado, 
        main = "Gráfica No.5: Diagrama de Caja de Temperatura Mínima",
        xlab = "Temperatura Mínima (°C)", outline = TRUE, outpch = 19, outcol = "#C0392B", 
        boxwex = 0.5, frame.plot = FALSE, xaxt = "n") 
eje_x_detallado <- pretty(Variable, n = 20) 
axis(1, at = eje_x_detallado, labels = format(eje_x_detallado, scientific = FALSE), cex.axis=0.7, las=2)
grid(nx=NULL, ny=NA, col="lightgray", lty="dotted")

# GRÁFICO 6: Ojivas
par(mar = c(5, 5, 4, 8), xpd = TRUE) 

x_asc <- c(min(breaks_table), breaks_table[2:length(breaks_table)])
y_asc <- c(0, Ni_asc)


x_desc <- c(min(breaks_table), breaks_table[2:length(breaks_table)])
y_desc <- c(Ni_desc, 0) 

x_range <- range(c(x_asc, x_desc))
y_range <- c(0, max(c(y_asc, y_desc)))
col_azul <- "#2E4053"
col_rojo <- "#C0392B"

plot(x_asc, y_asc, type = "o", col = col_azul, lwd=2, pch=19,
     main = "Gráfica No.6: Ojivas de Temperatura Mínima",
     xlab = "Temperatura Mínima (°C)", ylab = "Frecuencia acumulada",
     xlim = x_range, ylim = y_range, axes = FALSE, frame.plot = FALSE, cex.main=0.95)

axis(1, at = round(breaks_table,1), labels = format(round(breaks_table,1), scientific = FALSE), las=2, cex.axis=0.6)
axis(2, at = pretty(y_asc), labels = format(pretty(y_asc), scientific = FALSE))

lines(x_asc, y_desc, type = "o", col = col_rojo, lwd=2, pch=19)

legend("right", legend = c("Ascendente", "Descendente"),
       col = c(col_azul, col_rojo), lty = 1, pch = 19, cex = 0.7, lwd=2,
       inset = c(-0.15, 0), bty="n")
grid()

4 Resumen Estadístico

# CÁLCULO DE INDICADORES 

media_val <- mean(Variable)
mediana_val <- median(Variable)

freq_max <- max(TDF_Temp$ni)
modas_calc <- TDF_Temp$MC[TDF_Temp$ni == freq_max]
moda_txt <- paste(round(modas_calc, 2), collapse = ", ")

rango_txt <- paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]")
varianza_val <- var(Variable)
sd_val <- sd(Variable)
cv_val <- (sd_val / abs(media_val)) * 100

asimetria_val <- skewness(Variable, type = 2)
curtosis_val <- kurtosis(Variable, type = 2)

vals_atipicos <- boxplot.stats(Variable)$out
num_atipicos <- length(vals_atipicos)

status_atipicos <- if(num_atipicos > 0) {
  min_out <- min(vals_atipicos)
  max_out <- max(vals_atipicos)
  paste0(num_atipicos, " [", round(min_out, 2), "; ", round(max_out, 2), "]")
} else {
  "0 (Sin atípicos)"
}

df_resumen <- data.frame(
  "Variable" = "Temperatura Mínima (°C)",
  "Rango" = rango_txt,
  "Media" = media_val,
  "Mediana" = mediana_val,
  "Moda" = moda_txt,
  "Varianza" = varianza_val,
  "Desv_Std" = sd_val,
  "CV_Porc" = cv_val,
  "Asimetria" = asimetria_val,
  "Curtosis" = curtosis_val,
  "Atipicos" = status_atipicos
)

df_resumen %>%
  gt() %>%
  tab_header(
    title = md("**CONCLUSIONES Y ESTADÍSTICOS**"),
    subtitle = "Resumen de Indicadores - Estación Antisana"
  ) %>%
  tab_source_note(source_note = "Autor: Grupo 3") %>%
  fmt_number(columns = c(Media, Mediana, Varianza, Desv_Std, CV_Porc, Curtosis), decimals = 2) %>%
  fmt_number(columns = c(Asimetria), decimals = 4) %>%
  cols_label(
    Variable = "Variable",
    Rango = "Rango Total",
    Media = "Media (X̄)",
    Mediana = "Mediana (Me)",
    Moda = "Moda (Mo)",
    Varianza = "Varianza (S²)",
    Desv_Std = "Desv. Est. (S)",
    CV_Porc = "C.V. (%)",
    Asimetria = "Asimetría (As)",
    Curtosis = "Curtosis (K)",
    Atipicos = "Outliers [Intervalo]"
  ) %>%
  tab_options(
    column_labels.background.color = "#2E4053",
    table.border.top.color = "black",
    table.border.bottom.color = "#2E4053",
    column_labels.border.bottom.color = "#2E4053",
    data_row.padding = px(8)
  ) %>%
  tab_style(
    style = list(cell_text(weight = "bold", color = "white")),
    locations = cells_column_labels()
  )
CONCLUSIONES Y ESTADÍSTICOS
Resumen de Indicadores - Estación Antisana
Variable Rango Total Media (X̄) Mediana (Me) Moda (Mo) Varianza (S²) Desv. Est. (S) C.V. (%) Asimetría (As) Curtosis (K) Outliers [Intervalo]
Temperatura Mínima (°C) [2.65; 10.85] 8.05 8.00 7.66 1.89 1.37 17.08 −0.4377 0.61 7 [2.65; 4.55]
Autor: Grupo 3

5 Conclusiones

min_txt <- format(min(Variable), scientific = FALSE)
max_txt <- format(max(Variable), scientific = FALSE)

asimetria_val <- skewness(Variable, type = 2)

if (abs(asimetria_val) > 0.5) {
  centro_valor <- format(round(median(Variable), 2), scientific = FALSE)
} else {
  centro_valor <- format(round(mean(Variable), 2), scientific = FALSE)
}

sd_txt <- format(round(sd(Variable), 4), scientific = FALSE)
cv_calc <- (sd(Variable) / abs(mean(Variable))) * 100
tipo_homogeneidad <- if(cv_calc > 30) "heterogénea" else "homogénea"

donde_se_concentra <- if(asimetria_val > 0) "parte media baja" else "parte media alta"

outliers_lista <- boxplot.stats(Variable)$out
num_outliers <- length(outliers_lista)

texto_outliers <- if(num_outliers > 0) {
  paste0("con la presencia de **", num_outliers, " valores atípicos**")
} else {
  "sin valores atípicos significativos"
}


umbral_minima_optima <- 4 

juicio_climatico <- if(median(Variable) < umbral_minima_optima) {
   
  "favorable para el equilibrio del ecosistema, indicando descensos térmicos nocturnos suficientes para promover procesos de recongelamiento superficial y mantenimiento de la cobertura nival"
} else {
   
  "preocupante desde la perspectiva glaciológica, evidenciando un calentamiento nocturno que impide el recongelamiento eficaz, acelerando potencialmente la pérdida de masa del glaciar"
}

cat(paste0(
  "## Análisis Descriptivo y Climático\n\n",
   
  "La variable **Temperatura Mínima** fluctúa entre **", min_txt, "** y **", max_txt, "** grados Celsius, ",
  "y sus valores se encuentran alrededor de **", centro_valor, "** °C. ",
  "Presenta una desviación estándar de **", sd_txt, "**, siendo una variable **", tipo_homogeneidad, "** ",
  "(CV: ", round(cv_calc, 2), "%), ",
  "cuyos valores se concentran en la **", donde_se_concentra, "** de la distribución ",
  texto_outliers, "; ",
   
  "**por todo lo anterior, el comportamiento de las mínimas se considera ", juicio_climatico, ".**"
))

5.1 Análisis Descriptivo y Climático

La variable Temperatura Mínima fluctúa entre 2.65 y 10.85 grados Celsius, y sus valores se encuentran alrededor de 8.05 °C. Presenta una desviación estándar de 1.3741, siendo una variable homogénea (CV: 17.08%), cuyos valores se concentran en la parte media alta de la distribución con la presencia de 7 valores atípicos; por todo lo anterior, el comportamiento de las mínimas se considera preocupante desde la perspectiva glaciológica, evidenciando un calentamiento nocturno que impide el recongelamiento eficaz, acelerando potencialmente la pérdida de masa del glaciar.