# Tema: Estadística Multivariable
# Autor: Camila Zambrano
# Fecha: 15/06/2026

0.Carga de librerías

library(gt)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

1. Carga de datos

setwd("~/CAMILA")
datos <- read.csv("Datos Cambiados..csv",
                  header = TRUE,
                  sep = ",",
                  dec = ".",
                  na.strings = "-")

2.- Selección de la variable aleatoria

longitud <- datos$Longitud

3. Tabla de Distribución de Frecuencia

# Tamaño de muestra
n <- length(longitud)

# Valor mínimo y máximo
min_longitud <- min(longitud, na.rm = TRUE)
max_longitud <- max(longitud, na.rm = TRUE)

# Rango
R <- max_longitud - min_longitud

# Número de intervalos (Regla de Sturges)
k_detallado <- ceiling(1 + 3.322 * log10(n))

# Amplitud de clase
A <- R / k_detallado

# Mostrar resultados
cat("Número de intervalos (k):", k_detallado, "\n")
## Número de intervalos (k): 16
# Generación de límites de intervalos
Li <- seq(from = min_longitud, to = max_longitud - A, by = A)
Ls <- c(seq(from = min_longitud + A, to = max_longitud - A, by = A), max_longitud)

# Redondeo
longitud <- round(longitud, 3)
Li <- round(Li, 3)
Ls <- round(Ls, 3)

# Marcas de clase
MC <- (Li + Ls) / 2

# Frecuencias absolutas
ni <- numeric(length(Li))

for(i in 1:length(Li)){
  if(i < length(Li)){
    ni[i] <- sum(longitud >= Li[i] & longitud < Ls[i])
  } else {
    ni[i] <- sum(longitud >= Li[i] & longitud <= Ls[i])
  }
}

# Frecuencias relativas y acumuladas
hi <- (ni / n) * 100
Ni_asc <- cumsum(ni)
Ni_desc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_desc <- rev(cumsum(rev(hi)))

# Intervalos
Intervalo <- paste0("[", round(Li, 2), " - ", round(Ls, 2), ")")

# Último intervalo cerrado
Intervalo[length(Intervalo)] <- paste0(
  "[",
  round(Li[length(Li)], 2),
  " - ",
  round(Ls[length(Ls)], 2),
  "]"
)
# Tabla de distribución de frecuencias
TDF_longitud <- data.frame(
  Intervalo = Intervalo,
  MC = round(MC, 2),
  ni = ni,
  hi = round(hi, 2),
  Ni_ascendente = Ni_asc,
  Ni_descendente = Ni_desc,
  Hi_ascendente = round(Hi_asc, 2),
  Hi_descendente = round(Hi_desc, 2)
)

# Fila de totales
totales <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni),
  hi = round(sum(hi), 2),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)

# Tabla completa
TDF_longitud_completa <- rbind(TDF_longitud, totales)

# Por una gran cantidad de intervalos se realizara una reducción de filas en la
# tabla Nro. 2 creando solo 10 intervalos

# TABLA 2
k_tabla2 <- 9

# Nueva amplitud
A2 <- R / k_tabla2

# Nuevos límites
Li2 <- seq(from = min_longitud, to = max_longitud - A2, by = A2)
Ls2 <- c(seq(from = min_longitud + A2, to = max_longitud - A2, by = A2), max_longitud)

# Redondeo
Li2 <- round(Li2, 3)
Ls2 <- round(Ls2, 3)

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

# Frecuencias absolutas
ni2 <- numeric(length(Li2))

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

# Frecuencias relativas y acumuladas
hi2 <- (ni2 / n) * 100
Ni2_asc <- cumsum(ni2)
Ni2_desc <- rev(cumsum(rev(ni2)))
Hi2_asc <- cumsum(hi2)
Hi2_desc <- rev(cumsum(rev(hi2)))

# Intervalos
Intervalo2 <- paste0("[", round(Li2,2), " - ", round(Ls2,2), ")")

Intervalo2[length(Intervalo2)] <- paste0(
  "[",
  round(Li2[length(Li2)],2),
  " - ",
  round(Ls2[length(Ls2)],2),
  "]"
)

# Tabla 2
TDF_longitud_10 <- data.frame(
  Intervalo = Intervalo2,
  MC = round(MC2,2),
  ni = ni2,
  hi = round(hi2,2),
  Ni_ascendente = Ni2_asc,
  Ni_descendente = Ni2_desc,
  Hi_ascendente = round(Hi2_asc,2),
  Hi_descendente = round(Hi2_desc,2)
)

# Totales
totales2 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni2),
  hi = sum(hi2),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)

TDF_longitud_10_completa <- rbind(TDF_longitud_10, totales2)

# TABLA 2: Distribución de frecuencias de longitud con 10 intervalos

TDF_longitud_10_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencias de la variable Longitud para el análisis
                  estadístico de la calidad del aire en la India."
  ) %>%
  tab_source_note(
    source_note = md("Grupo: 1 <br> Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india ")
  ) %>%
  tab_style(
    style = cell_borders(sides = "left", color = "black", weight = px(2)),
    locations = cells_body()
  ) %>%
  tab_style(
    style = cell_borders(sides = "right", color = "black", weight = px(2)),
    locations = cells_body()
  ) %>%
  tab_style(
    style = cell_borders(sides = "left", color = "black", weight = px(2)),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_borders(sides = "right", color = "black", weight = px(2)),
    locations = cells_column_labels()
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE,
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black"
  )
Tabla Nro. 1
Distribución de frecuencias de la variable Longitud para el análisis estadístico de la calidad del aire en la India.
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[73.01 - 75.09) 74.05 3872 13.11 3872 29531 13.11 100
[75.09 - 77.16) 76.13 5811 19.68 9683 25659 32.79 86.89
[77.16 - 79.24) 78.2 11531 39.05 21214 19848 71.84 67.21
[79.24 - 81.32) 80.28 3121 10.57 24335 8317 82.4 28.16
[81.32 - 83.39) 82.35 2413 8.17 26748 5196 90.58 17.6
[83.39 - 85.47) 84.43 2281 7.72 29029 2783 98.3 9.42
[85.47 - 87.55) 86.51 0 0.00 29029 502 98.3 1.7
[87.55 - 89.62) 88.59 0 0.00 29029 502 98.3 1.7
[89.62 - 91.7] 90.66 502 1.70 29531 502 100 1.7
Totales - 29531 100.00 - - - -
Grupo: 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

4.- Gráfica de Distribución de Frecuencia

bp <- barplot(hi2,
              space = 0,
              names.arg = FALSE,
              xaxt = "n",
              yaxt = "n",
              main = "Gráfica N°1 Distribución de longitud\nen el estudio de la calidad de aire en
              la India 2015-2020",
              xlab = "Longitud (°)",
              ylab = "Porcentaje",
              col = "darkseagreen3",
              border = "black",
              ylim = c(0, 45),
              cex.main = 0.8)
# Eje X
# Etiquetas con intervalos reales redondeados a enteros
Etiquetas <- paste0(
  "[",
  round(Li2,0),
  "-",
  round(Ls2,0),
  ")"
)

# Último intervalo cerrado
Etiquetas[length(Etiquetas)] <- paste0(
  "[",
  round(Li2[length(Li2)],0),
  "-",
  round(Ls2[length(Ls2)],0),
  "]"
)

# Eje X
axis(1,
     at = bp,
     labels = Etiquetas,
     las = 2,
     cex.axis = 0.8)
# Eje Y
axis(2,
     at = seq(0, 45, by = 10),
     labels = seq(0, 45, by = 10),
     las = 1)
grid()

5.- Conjetura

Se observa que la distribución de la variable longitud sigue aproximadamente un modelo de distribución normal. Esto se basa en la observacióndel histograma, tras la primera barra, se aprecia que las frecuencias de las tres barras siguientes consecutivas muestran una forma simétrica y centralizada, característica de la distribución normal.

6.- Parámetros

#Extraemos el intervalo de 75 a 82
longitud1<-longitud[longitud >=75  & longitud<82 ]

# CÁLCULO DE LOS PARÁMETROS DISTRIBUCIÓN NORMAL

# Media (mu)
mu <- mean(longitud1)
mu
## [1] 77.933
# Desviación estándar (sigma)
sigma <- sd(longitud1)
sigma
## [1] 1.639001

7.- Sobreposición de la realidad con el modelo

cortes_limpios <- seq(75, 82, length.out = 4)
Histogramalongitud1 <- hist(longitud1,
                            breaks = cortes_limpios,
                            freq = FALSE,          
                            main = "Gráfica Nº2:Comparación de la realidad con el modelo normal de Longitud \nen el estudio de calidad de aire India 2015-2020", 
                            xlab = "Longitud (°)",
                            ylab = "Densidad probabilidad ",
                            col = "grey", ylim = c(0,0.5),xaxt = "n"
) 

axis(1,
     at = cortes_limpios,
     labels = round(cortes_limpios, 0))

# Secuencia para la curva normal
x <- seq(min(longitud1), max(longitud1), by=0.01)

# Curva normal 
curve(dnorm(x, mu, sigma),type="l",add = T,lwd=4, col = "steelblue")

8.- Test de Bondad

8.1.- Test de Pearson

#Frecuencia observada
Fo<-as.numeric(table(cut(longitud1, breaks = cortes_limpios, include.lowest = TRUE)))
Fo
## [1] 9826 8628 2960
n <- length(longitud1)
# Probabilidad = P(X <= Ls) - P(X <= Li)
p <- diff(pnorm(cortes_limpios, mean = mu, sd = sigma))
# Fe = Probabilidad * n
Fe <- p * n
Fe
## [1]  6862.397 10657.476  2966.679
Correlación<-cor(Fo,Fe)*100
Correlación
## [1] 77.75064

8.2.- Test de Chi-cuadrado

# Fo y Fe en fracción
Fo_fracción<- Fo/n
Fo_fracción
## [1] 0.4588587 0.4029140 0.1382273
Fe_fracción<- p
Fe_fracción
## [1] 0.3204631 0.4976873 0.1385392
x2 <- sum((Fo_fracción - Fe_fracción)^2 / Fe_fracción)
x2
## [1] 0.07781583
k <- length(Fo)
grados_libertad <- k - 1
grados_libertad
## [1] 2
umbral_aceptacion <- qchisq(0.95, df = grados_libertad)
umbral_aceptacion
## [1] 5.991465
x2<umbral_aceptacion
## [1] TRUE

9.- Cálculo de Probabilidades

9.1.- Pregunta de porcentaje

¿Cuál es la probabilidad de encontrar una observación con una longitud comprendida entre 75° y 77° en el estudio de calidad del aire en India durante el período 2015–2020?

(pnorm(85, mu, sigma) - pnorm(80, mu, sigma))*100
## [1] 10.36221

DEMOSTRACIÓN GRÁFICA PARA LONGITUD

# Probabilidad
Probabilidad <- (pnorm(85, mu, sigma) -
                   pnorm(80, mu, sigma)) * 100

# Rango para la curva

x <- seq(min(longitud),
         max(longitud),
         0.01)

plot(x, dnorm(x, mu, sigma),
     col = "skyblue3",
     lwd = 1,
     main = "Gráfica N°2: Cálculo de probabilidades",
     ylab = "Densidad de probabilidad",
     xlab = "Longitud (°)")

# Definir el rango de la sección que quieres pintar

x_section <- seq(80, 85, 0.001)

y_section <- dnorm(x_section, mu, sigma)

# Pintar la sección de la curva

lines(x_section,
      y_section,
      col = "red",
      lwd = 2)

# Pintar el área debajo de la línea roja

polygon(c(x_section, rev(x_section)),
        c(y_section, rep(0, length(y_section))),
        col = rgb(1, 0, 0, 0.6))

# Leyenda

legend("topright",
       legend = c("Modelo Normal",
                  "Área de Probabilidad"),
       col = c("skyblue3",
               "red"),
       lwd = 2,
       cex = 0.7)

# Texto

text(x = 88,
     y = 0.07,
     labels = paste0("Probabilidad = ",
                     round(Probabilidad,2),
                     "%"),
     cex = 0.8,
     font = 2)

9.2.- Pregunta de cantidad

¿Cuántas observaciones del estudio de calidad del aire en India (2015–2020) presentan una longitud comprendida entre 77° y 79°?

Cantidad <- (pnorm(79, mu, sigma) - pnorm(77, mu, sigma)) * n
Cantidad
## [1] 9805.156

10.- Intervalos de confianza

media <-mean(longitud)
sigma<-sd(longitud)
n<-length(longitud)
error<- 2*(sigma/sqrt(n))
#Límites intevalo de cofianza
limite_inferior<- round(media-error,2)
limite_superior<- round(media+error,2)
tabla_intervalo <- data.frame(Intervalo = "P [78.51< µ <78.61] = 95%")

tabla_intervalo %>%
  gt() %>%
  tab_header(
    title = md("*Tabla N°2*"),
    subtitle = md("Intervalos de confianza de la longitud en el estudio de la calidad del aire en la India 2015-2020")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Grupo 1\n Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india")
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE,
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black"
  )
Tabla N°2
Intervalos de confianza de la longitud en el estudio de la calidad del aire en la India 2015-2020
Intervalo
P [78.51< µ <78.61] = 95%
Autor: Grupo 1 Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

11.- Conclusión

La variable aleatoria longitud se explica con un modelo normal, con parámetros μ = 77.84 y σ = 1.40, y podemos afirmar con un 95% de confianza que la media aritmética poblacional se encuentra entre 78.51° y 78.61°, con una desviación estándar de 1.40.