0. Librerías

library(knitr)
library(kableExtra)
library(e1071)

1. Leer Datos

variables <- read.csv("C:/Users/WAN/Downloads/GlobalWeatherRepository.csv")

2. Extracción y Depuración de la Variable

Latitud <- na.omit(variables$latitude)

# Total de datos

n_total <- length(Latitud)

3. Frecuencias

3.1 Max y Min

valor_min <- min(Latitud)
valor_max <- max(Latitud)

rango <- valor_max - valor_min

3.2. Regla de Sturges

K_sturges <- floor(1 + 3.322 * log10(n_total))

cat("Número de clases:", K_sturges, "\n")
## Número de clases: 18
A_sturges <- rango / K_sturges

cat("Amplitud Sturges:", A_sturges, "\n")
## Amplitud Sturges: 5.858333

3.3. Intervalos

Li1 <- seq( valor_min,
  valor_max - A_sturges,
  by = A_sturges
)

Ls1 <- Li1 + A_sturges

3.4. Bucle para las columnas de la tabla

ni1 <- numeric(length(Li1))

for(i in 1:length(Li1)){
  
  if(i == length(Li1)){
    
    ni1[i] <- sum(
      Latitud >= Li1[i] &
        Latitud <= Ls1[i]
    )
    
  } else {
    
    ni1[i] <- sum(
      Latitud >= Li1[i] &
        Latitud < Ls1[i]
    )
  }
}

# Frecuencia relativa
hi1 <- (ni1 / sum(ni1)) * 100

# Acumuladas
Ni_asc1 <- cumsum(ni1)
Hi_asc1 <- cumsum(hi1)

Ni_dsc1 <- rev(cumsum(rev(ni1)))
Hi_dsc1 <- rev(cumsum(rev(hi1)))

# Marca de clase
MC1 <- (Li1 + Ls1)/2

3.5. Tabla con amplitud ajustada

amplitud <- 15

# Intervalos
Li2 <- seq(
  floor(valor_min/15)*15,
  ceiling(valor_max/15)*15 - 15,
  by = 15
)

Ls2 <- Li2 + 15

#Frecuencias

ni2 <- numeric(length(Li2))

for(i in 1:length(Li2)){
  
  if(i == length(Li2)){
    
    ni2[i] <- sum(
      Latitud >= Li2[i] &
        Latitud <= Ls2[i]
    )
    
  } else {
    
    ni2[i] <- sum(
      Latitud >= Li2[i] &
        Latitud < Ls2[i]
    )
  }
}

# Frecuencia relativa
hi2 <- (ni2 / sum(ni2)) * 100

# Acumuladas
Ni_asc2 <- cumsum(ni2)
Hi_asc2 <- cumsum(hi2)

Ni_dsc2 <- rev(cumsum(rev(ni2)))
Hi_dsc2 <- rev(cumsum(rev(hi2)))

# Marca de clase
MC2 <- (Li2 + Ls2)/2

4. Tabla de Distribución de Frecuencias

4.1. Tabla según Regla de Sturges

amplitud <- 15
# Convertir a caracteres para poder mezclar números y texto

Tabla_Sturges <- data.frame(
  
  Lim_inf = round(Li1,2),
  
  Lim_sup = round(Ls1,2),
  
  MC = round(MC1,2),
  
  ni = ni1,
  
  hi = round(hi1,2),
  
  Ni_asc = Ni_asc1,
  
  Hi_asc = round(Hi_asc1,2),
  
  Ni_dsc = Ni_dsc1,
  
  Hi_dsc = round(Hi_dsc1,2)
  
)

Tabla_Sturges2 <- Tabla_Sturges
Tabla_Sturges2[] <- lapply(Tabla_Sturges2, as.character)

# Fila de totales

fila_total <- data.frame(
  Lim_inf = "TOTAL",
  Lim_sup = "",
  MC = "",
  ni = as.character(sum(ni1)),
  hi = as.character(round(sum(hi1), 2)),
  Ni_asc = "",
  Hi_asc = "",
  Ni_dsc = "",
  Hi_dsc = ""
)

# Agregar fila

Tabla_Sturges2 <- rbind(Tabla_Sturges2, fila_total)


kable(
  Tabla_Sturges2,
  align = "c",
  caption = "Tabla N°1:Distribución de frecuencias de la latitud de los registros meteorológicos mundiales mediante la regla de Sturges, período 2024–2026"
) |>
  
  kableExtra::kable_styling(
    full_width = TRUE,
    position = "center",
    bootstrap_options = c(
      "striped",
      "hover",
      "condensed",
      "responsive"
    )
  ) |>
  
  kableExtra::row_spec(
    0,
    bold = TRUE,
    color = "white",
    background = "#2C3E50"
  ) |>
  
  kableExtra::row_spec(
    nrow(Tabla_Sturges2),
    bold = TRUE,
    background = "#EAEDED"
  )|>
footnote(
  general = "Elaborado por Grupo 2. 
    Fuente: Global Weather Repository.",
  general_title = "Nota: Los intervalos obtenidos aplicando la regla de Sturges son poco prácticos para su respectiva explicación por lo que se decidió agruparlos para facilitar su comprensión. ",
  footnote_as_chunk = TRUE,
  title_format = c("italic","bold")
)
Tabla N°1:Distribución de frecuencias de la latitud de los registros meteorológicos mundiales mediante la regla de Sturges, período 2024–2026
Lim_inf Lim_sup MC ni hi Ni_asc Hi_asc Ni_dsc Hi_dsc
-41.3 -35.44 -38.37 728 0.51 728 0.51 141703 100
-35.44 -29.58 -32.51 2905 2.05 3633 2.56 140975 99.49
-29.58 -23.72 -26.65 4095 2.89 7728 5.45 138070 97.44
-23.72 -17.87 -20.8 5087 3.59 12815 9.04 133975 94.55
-17.87 -12.01 -14.94 4356 3.07 17171 12.12 128888 90.96
-12.01 -6.15 -9.08 7269 5.13 24440 17.25 124532 87.88
-6.15 -0.29 -3.22 5814 4.1 30254 21.35 117263 82.75
-0.29 5.57 2.64 7611 5.37 37865 26.72 111449 78.65
5.57 11.43 8.5 13043 9.2 50908 35.93 103838 73.28
11.43 17.28 14.35 20327 14.34 71235 50.27 90795 64.07
17.28 23.14 20.21 6943 4.9 78178 55.17 70468 49.73
23.14 29 26.07 7269 5.13 85447 60.3 63525 44.83
29 34.86 31.93 7276 5.13 92723 65.43 56256 39.7
34.86 40.72 37.79 13773 9.72 106496 75.15 48980 34.57
40.72 46.58 43.65 14029 9.9 120525 85.05 35207 24.85
46.58 52.43 49.5 12440 8.78 132965 93.83 21178 14.95
52.43 58.29 55.36 5091 3.59 138056 97.43 8738 6.17
58.29 64.15 61.22 3647 2.57 141703 100 3647 2.57
TOTAL 141703 100
Nota: Los intervalos obtenidos aplicando la regla de Sturges son poco prácticos para su respectiva explicación por lo que se decidió agruparlos para facilitar su comprensión. Elaborado por Grupo 2.
Fuente: Global Weather Repository.

4.2. Tabla ajustada a amplitu segun RStudio

TDF_Latitud <- data.frame(
  
  Lim_inf = round(Li2,2),
  
  Lim_sup = round(Ls2,2),
  
  MC = round(MC2,2),
  
  ni = ni2,
  
  hi = round(hi2,2),
  
  Ni_asc = Ni_asc2,
  
  Hi_asc = round(Hi_asc2,2),
  
  Ni_dsc = Ni_dsc2,
  
  Hi_dsc = round(Hi_dsc2,2)
  
)

# Convertir todo a texto
TDF_Latitud[] <- lapply(TDF_Latitud, as.character)

# Fila TOTAL
TDF_Total <- data.frame(
  
  Lim_inf = "TOTAL",
  
  Lim_sup = "",
  
  MC = "",
  
  ni = as.character(sum(ni2)),
  
  hi = as.character(round(sum(hi2),2)),
  
  Ni_asc = "",
  
  Hi_asc = "",
  
  Ni_dsc = "",
  
  Hi_dsc = "",
  
  stringsAsFactors = FALSE
  
)

# Agregar fila total
TDF_Latitud <- rbind(TDF_Latitud, TDF_Total)

# Renombrar columnas
colnames(TDF_Latitud) <- c(
  
  "Lim. Inf.",
  
  "Lim. Sup.",
  
  "MC",
  
  "ni",
  
  "hi (%)",
  
  "Ni Asc",
  
  "Hi Asc",
  
  "Ni Dsc",
  
  "Hi Dsc"
  
)

# Mostrar tabla

kable(
  TDF_Latitud,
  align = "c",
  caption = "Tabla N2: Distribución de frecuencias agrupadas de la latitud de los registros meteorológicos mundiales con amplitud de clase de 15°, período 2024–2026"
) |>
  
  kable_styling(
    full_width = TRUE,
    position = "center",
    bootstrap_options = c(
      "striped",
      "hover",
      "condensed",
      "responsive"
    )
  ) |>
  
  row_spec(
    0,
    bold = TRUE,
    color = "white",
    background = "#2C3E50"
  ) |>
  
  row_spec(
    nrow(TDF_Latitud),
    bold = TRUE,
    background = "#EAEDED"
  ) |>
  
  footnote(
    general = "Elaborado por Grupo 2. 
    Fuente: Global Weather Repository.",
    general_title = "Nota: ",
    footnote_as_chunk = TRUE,
    title_format = c("italic","bold")
  )
Tabla N2: Distribución de frecuencias agrupadas de la latitud de los registros meteorológicos mundiales con amplitud de clase de 15°, período 2024–2026
Lim. Inf. Lim. Sup. MC ni hi (%) Ni Asc Hi Asc Ni Dsc Hi Dsc
-45 -30 -37.5 3633 2.56 3633 2.56 141703 100
-30 -15 -22.5 11364 8.02 14997 10.58 138070 97.44
-15 0 -7.5 15981 11.28 30978 21.86 126706 89.42
0 15 7.5 35174 24.82 66152 46.68 110725 78.14
15 30 22.5 20022 14.13 86174 60.81 75551 53.32
30 45 37.5 32172 22.7 118346 83.52 55529 39.19
45 60 52.5 21903 15.46 140249 98.97 23357 16.48
60 75 67.5 1454 1.03 141703 100 1454 1.03
TOTAL 141703 100
Nota: Elaborado por Grupo 2.
Fuente: Global Weather Repository.

5. Gráficos de Distribución de Frecuencias

5.1. Histograma Original (ni)

hist(
  Latitud,
  
  breaks = seq(
    floor(min(Latitud)/15)*15,
    ceiling(max(Latitud)/15)*15,
    by = 15
  ),
  
  main = "Gráfico N°1. Distribución de frecuencias absolutas de 
  la latitud de los registros meteorológicos mundiales agrupados
  en intervalos de 20°, período 2024–2026",
  
  xlab = "Latitud",
  
  ylab = "Frecuencia",
  
  col = "skyblue",
  
  border = "black"
)

5.2. Histograma con relación al todo (ni)

hist(
  Latitud,
  
  breaks = c(Li2, max(Ls2)),
  
  ylim = c(0, n_total),
  
  main = "Gráfico N°2. Histograma y polígono de frecuencias 
  absolutas de la latitud de los registros meteorológicos mundiales, 
  período 2024–2026",
  
  xlab = "Latitud",
  
  ylab = "Frecuencia",
  
  col = "lightgreen",
  
  border = "black"
)

grid()

5.3. Histograma original (hi)

barplot(
  hi2,
  
  names.arg = paste(Li2, Ls2, sep = " a "),
  
  ylim = c(0, max(hi2) * 1.1),
  
  main = "Gráfico N°3. Distribución de frecuencias relativas de la 
  latitud de los registros meteorológicos mundiales agrupados en 
  intervalos de 20°, período 2024–2026",
  
  xlab = "Intervalos de Latitud",
  
  ylab = "Frecuencia Relativa (%)",
  
  col = "skyblue",
  
  las = 2
)

5.4. Histograma con relacion a todo (hi)

barplot(
  hi2,
  
  names.arg = paste(Li2, Ls2, sep = " a "),
  
  ylim = c(0, 100),
  
  main = "Gráfico N°4. Histograma y polígono de frecuencias relativas 
  de la latitud de los registros meteorológicos mundiales, período 
  2024–2026",
  
  xlab = "Intervalos de Latitud",
  
  ylab = "Frecuencia Relativa (%)",
  
  col = "lightgreen",
  
  las = 2
)

5.5. Polígono de frecuencias (ni)

# Histograma agrupado con los mismos intervalos
hist(
  Latitud,
  breaks = c(Li2, max(Ls2)),
  freq = TRUE,
  main = "Gráfico N°5. Polígono de frecuencias absolutas de la latitud de los registros meteorológicos mundiales, período 2024–2026",
  xlab = "Latitud",
  ylab = "Frecuencia (ni)",
  col = "lightblue",
  border = "black"
)

# Polígono cerrado
MC2_c <- c(
  MC2[1] - amplitud/2,
  MC2,
  MC2[length(MC2)] + amplitud/2
)

ni2_c <- c(0, ni2, 0)
MC2_c <- c(Li2[1], MC2, Ls2[length(Ls2)])
ni2_c <- c(0, ni2, 0)

lines(
  MC2_c,
  ni2_c,
  type = "o",
  lwd = 2,
  pch = 16,
  col = "red"
)

grid()

5.6. Polígono de frecuencias (hi)

# Histograma local con hi (%)

bp <- barplot(
  hi2,
  names.arg = paste(Li2, Ls2, sep = "-"),
  col = "lightgreen",
  border = "black",
  ylim = c(0, max(hi2)*1.2),
  main = "Gráfico N°6. Polígono de frecuencias relativas de la latitud de los registros meteorológicos mundiales, período 2024–2026",
  xlab = "Intervalos",
  ylab = "Frecuencia relativa (%)"
)

# Polígono cerrado desde el límite inferior hasta el límite superior

x_pol <- c(
  bp[1] - 1,   # inicio del primer intervalo (-45)
  bp,            # centros de barras
  bp[length(bp)] + 0.5  # final del último intervalo (75)
)

y_pol <- c(
  0,
  hi2,
  0
)

lines(
  x_pol,
  y_pol,
  type = "o",
  col = "red",
  lwd = 2,
  pch = 16
)

grid()

5.7. Ojiva ascendente y descendente (ni)

# Ascendente: inicia en 0
x_asc <- c(Li2[1], MC2)
y_asc <- c(0, Ni_asc2)

# Descendente: termina en 0
x_dsc <- c(MC2, Ls2[length(Ls2)])
y_dsc <- c(Ni_dsc2, 0)

# Crear gráfico vacío
plot(
  x_asc,
  y_asc,
  type = "o",
  pch = 16,
  col = "blue",
  lwd = 2,
  ylim = c(0, n_total),
  xlab = "Latitud",
  ylab = "Frecuencia Acumulada (Ni)",
  main = "Gráfico N°5: Ojivas ascendente y descendente de frecuencias absolutas acumuladas de la latitud de los registros meteorológicos mundiales, período 2024–2026"
)

# Agregar ojiva descendente
lines(
  x_dsc,
  y_dsc,
  type = "o",
  pch = 17,
  col = "red",
  lwd = 2
)

# Cuadrícula
grid()

# Leyenda
legend(
  "right",
  legend = c(
    "Ojiva Ascendente",
    "Ojiva Descendente"
  ),
  col = c("blue", "red"),
  pch = c(16, 17),
  lwd = 2,
  bty = "n"
)

5.8. Ojiva ascentende y descendente (hi)

# Ascendente: inicia en 0%
x_asc <- c(Li2[1], MC2)
y_asc <- c(0, Hi_asc2)

# Descendente: termina en 0%
x_dsc <- c(MC2, Ls2[length(Ls2)])
y_dsc <- c(Hi_dsc2, 0)

# Crear gráfico
plot(
  x_asc,
  y_asc,
  type = "o",
  pch = 16,
  col = "blue",
  lwd = 2,
  ylim = c(0, 100),
  xlab = "Latitud",
  ylab = "Frecuencia Relativa Acumulada (%)",
  main = "Gráfico N°8: Ojivas ascendente y descendente de frecuencias relativas acumuladas de la latitud de los registros meteorológicos mundiales, período 2024–2026"
)

# Agregar ojiva descendente
lines(
  x_dsc,
  y_dsc,
  type = "o",
  pch = 17,
  col = "red",
  lwd = 2
)

# Cuadrícula
grid()

# Leyenda
legend(
  "right",
  legend = c(
    "Ojiva Ascendente (%)",
    "Ojiva Descendente (%)"
  ),
  col = c("blue", "red"),
  pch = c(16, 17),
  lwd = 2,
  bty = "n"
)

5.9. Bloxplot

Q1 <- quantile(Latitud, 0.25)

Q3 <- quantile(Latitud, 0.75)

RIC <- Q3 - Q1

Lim_inf <- Q1 - 1.5 * RIC

Lim_sup <- Q3 + 1.5 * RIC
bp <- boxplot(
  Latitud,
  horizontal = TRUE,
  outline = FALSE,
  main = "Gráfico N°9. Diagrama de caja y bigotes de la variable latitud 
  en registros meteorológicos mundiales, período 2024–2026",
  xlab = "Latitud",
  col = "lightblue"
)

atipicos <- Latitud[
  Latitud < Lim_inf |
    Latitud > Lim_sup
]

points(
  atipicos,
  rep(1, length(atipicos)),
  col = "red",
  pch = 19,
  cex = 0.8
)

abline(v = Lim_inf, col = "blue", lwd = 2, lty = 2)
abline(v = Lim_sup, col = "blue", lwd = 2, lty = 2)

#Outliers

Lim_inf2 <- Q1 - 1.0 * RIC
Lim_sup2 <- Q3 + 1.0 * RIC

atipicos2 <- Latitud[
  Latitud < Lim_inf2 |
    Latitud > Lim_sup2
]

length(atipicos2)
## [1] 3633
legend(
  "topright",
  legend = c(
    "Atípicos",
    "Límites de Tukey"
  ),
  col = c("red", "blue"),
  pch = c(19, NA),
  lty = c(NA, 2),
  lwd = c(NA, 2),
  bty = "n"
)

grid()

6. Indicadores Estadísticos

6.1. Tendencia central

media <- mean(Latitud)

mediana <- median(Latitud)

# Moda aproximada usando la clase modal

tabla_moda <- TDF_Latitud[
  TDF_Latitud$`Lim. Inf.` != "TOTAL",
]

ni_num <- as.numeric(tabla_moda$ni)

max_ni <- max(ni_num)

moda <- as.numeric(
  tabla_moda$MC[
    ni_num == max_ni
  ]
)

6.2. Dispersión

varianza <- var(Latitud)

desv_est <- sd(Latitud)

cv <- (desv_est / media) * 100

6.3. Forma

asimetria <- skewness(Latitud)

curtosis <- kurtosis(Latitud)

6.4. Valores atípicos

Q1 <- quantile(Latitud, 0.25)

Q3 <- quantile(Latitud, 0.75)

RIC <- Q3 - Q1

lim_inf <- Q1 - 1.5 * RIC

lim_sup <- Q3 + 1.5 * RIC

atipicos <- Latitud[
  Latitud < lim_inf |
    Latitud > lim_sup
]

n_atipicos <- length(atipicos)

intervalo_atipicos <- paste0(
  "[",
  round(lim_inf,2),
  "; ",
  round(lim_sup,2),
  "]"
)

# Rango

rango_texto <- paste0(
  "[",
  round(min(Latitud),2),
  "; ",
  round(max(Latitud),2),
  "]"
)

6.5. Tabla de indicadores

tabla_indicadores <- data.frame(
  
  Variable = "Latitud",
  
  Rango = rango_texto,
  
  Media = round(media,2),
  
  Mediana = round(mediana,2),
  
  Moda = round(moda,2),
  
  Varianza = round(varianza,2),
  
  Desv_Est = round(desv_est,2),
  
  CV = round(cv,2),
  
  Asimetria = round(asimetria,2),
  
  Curtosis = round(curtosis,2),
  
  Limite_Atipicos = intervalo_atipicos,
  
  N_Atipicos = n_atipicos
)

# Mostrar tabla

kable(
  tabla_indicadores,
  align = "c",
  caption = "Indicadores estadísticos descriptivos de la variable 
  latitud en registros meteorológicos mundiales, período 2024–2026"
) |>
  kable_styling(
    full_width = FALSE,
    position = "center",
    bootstrap_options = c(
      "striped",
      "hover",
      "condensed",
      "responsive"
    )
  ) |>
  row_spec(
    0,
    bold = TRUE,
    color = "white",
    background = "#2C3E50"
  )|>
  
  footnote(
    general = "Elaborado por Grupo 2. 
    Fuente: Global Weather Repository.",
    general_title = "Nota: ",
    footnote_as_chunk = TRUE,
    title_format = c("italic","bold")
  )
Indicadores estadísticos descriptivos de la variable latitud en registros meteorológicos mundiales, período 2024–2026
Variable Rango Media Mediana Moda Varianza Desv_Est CV Asimetria Curtosis Limite_Atipicos N_Atipicos
Latitud [-41.3; 64.15] 19.22 17.25 7.5 595.98 24.41 127.03 -0.3 -0.74 [-50.47; 94.92] 0
Nota: Elaborado por Grupo 2.
Fuente: Global Weather Repository.

7. Conclusiones

El comportamiento de la variable Latitud sigue la siguiente manera: fluctúa entre -41.30° y 64.15° y sus valores giran en torno a la media aritmética de 19.22°, con una desviación estándar de 24.41°, siendo un conjunto de datos muy heterogéneo, ya que su coeficiente de variación es de 127.03%. El conjunto de valores presenta una distribución platicúrtica (Curtosis = -0.74), lo que indica una menor concentración de datos alrededor del centro en comparación con una distribución normal. Además, muestra una ligera asimetría negativa (Asimetría = -0.30), por lo que los valores tienden a concentrarse hacia la parte alta de la distribución, con una cola más extendida hacia los valores bajos. Finalmente, no se identificaron valores atípicos (N = 0), lo que evidencia que los datos se encuentran dentro de los límites esperados. Por todo lo anterior, la variable Latitud presenta una amplia dispersión geográfica de las ubicaciones registradas, reflejando la diversidad de regiones incluidas en el conjunto de datos meteorológicos analizado.