FECHA: 27/11/2025
# ==============================================================================
# CONFIGURACIÓN Y PREPARACIÓN DE DATOS
# ==============================================================================
# Carga de Datos (Tu ruta de archivo)
# ¡ADVERTENCIA!: Cambia esta ruta si estás en otro equipo o entorno
TDFAQI<-read.csv("C:/Users/JOSELYN/Desktop/kangle/Datos Cambiados.csv", header = TRUE)
# 1. Preparación de Datos: Convertir a numérico y limpiar NAs
AQI_limpio <- as.numeric(TDFAQI$AQI)
AQI_limpio <- AQI_limpio[!is.na(AQI_limpio)]
# 2. Agrupación: CREACIÓN DE LOS INTERVALOS DE CLASE
numero_intervalos <- 6
breaks_limpios <- pretty(AQI_limpio, n = numero_intervalos)
grupos_AQI <- cut(AQI_limpio,
breaks = breaks_limpios,
include.lowest = TRUE,
right = FALSE)
# *** MODIFICACIÓN CLAVE PARA ELIMINAR NOTACIÓN CIENTÍFICA ***
etiquetas_de_intervalos <- levels(grupos_AQI)
options(scipen = 999) # Desactiva la notación científica
etiquetas_modificadas <- sapply(etiquetas_de_intervalos, function(etiqueta) {
limites <- regmatches(etiqueta, gregexpr("-?\\d+\\.?\\d*(?:[Ee][+-]?\\d+)?", etiqueta))[[1]]
if (length(limites) > 0) {
limites_formateados <- format(as.numeric(limites), scientific = FALSE, trim = TRUE)
nueva_etiqueta <- etiqueta
for (i in 1:length(limites)) {
nueva_etiqueta <- sub(limites[i], limites_formateados[i], nueva_etiqueta, fixed = TRUE)
}
return(nueva_etiqueta)
} else {
return(etiqueta)
}
})
levels(grupos_AQI) <- as.character(etiquetas_modificadas)
options(scipen = 0)
# ***************************************************************
# 3. Cálculo de Frecuencias (ni)
tabla_frecuencia <- as.data.frame(table(grupos_AQI))
# 4. Asignación de Variables
AQI <- tabla_frecuencia$grupos_AQI
ni <- tabla_frecuencia$Freq
# 5. Cálculos Derivados
hi <- ni / sum(ni) * 100
Ni_asc <- cumsum(ni)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_asc <- round(cumsum(hi), 2)
Hi_dsc <- round(rev(cumsum(rev(hi))), 2)
# 6. Crear la Tabla de Distribución de Frecuencias Agrupadas
TDFAQIFin_Agrupada <- data.frame(AQI, ni, hi, Ni_asc, Ni_dsc, Hi_asc, Hi_dsc)
# 1. Calcular los totales
total_ni <- sum(ni)
total_hi <- sum(hi)
# 2. Agregar la fila 'Total'
TDFAQICompleto <- rbind(TDFAQIFin_Agrupada,
data.frame(AQI = "Total",
ni = total_ni,
hi = total_hi,
Ni_asc = NA,
Ni_dsc = NA,
Hi_asc = NA,
Hi_dsc = NA))
print(TDFAQICompleto)
## AQI ni hi Ni_asc Ni_dsc Hi_asc Hi_dsc
## 1 [0,500) 24305 9.780684e+01 24305 24850 97.81 100.00
## 2 [500,1000) 452 1.818913e+00 24757 545 99.63 2.19
## 3 [1000,1500) 77 3.098592e-01 24834 93 99.94 0.37
## 4 [1500,2000) 15 6.036217e-02 24849 16 100.00 0.06
## 5 [2000,2500] 1 4.024145e-03 24850 1 100.00 0.00
## 6 Total 24850 1.000000e+02 NA NA NA NA
# ==============================================================================
# GENERACIÓN DE TABLA GT (Tabla Nro. 1: TDF)
# ==============================================================================
if(!require(gt)) install.packages("gt"); library(gt)
if(!require(dplyr)) install.packages("dplyr"); library(dplyr)
TDFAQICompleto %>%
gt() %>%
# Etiquetas de columna explícitas para evitar errores de caracteres
cols_label(
AQI = "AQI (Intervalos)",
ni = "ni (Frec. Absoluta)",
hi = "hi (%)",
Ni_asc = "Ni (Frec. Acumulada Asc.)",
Ni_dsc = "Ni (Frec. Acumulada Desc.)",
Hi_asc = "Hi (Frec. Acumulada % Asc.)",
Hi_dsc = "Hi (Frec. Acumulada % Desc.)"
) %>%
fmt_number(
columns = c(hi, Hi_asc, Hi_dsc),
decimals = 2
) %>%
tab_header(
title = md("**Tabla Nro. 1**"),
subtitle = md("Tabla de distribución de frecuencias de los niveles de **AQI**")
) %>%
tab_source_note(
source_note = md("Fuente: Datos procesados por el autor a partir de archivo city.day.csv")
) %>%
# Estilos de Bordes (Laterales)
tab_style(
style = cell_borders(sides = "left", color = "black", weight = px(2), style = "solid"),
locations = cells_body()
) %>%
tab_style(
style = cell_borders(sides = "right", color = "black", weight = px(2), style = "solid"),
locations = cells_body()
) %>%
tab_style(
style = cell_borders(sides = "left", color = "black", weight = px(2), style = "solid"),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(sides = "right", color = "black", weight = px(2), style = "solid"),
locations = cells_column_labels()
) %>%
# Opciones de Estilos (Bordes Superiores e Inferiores, Rayado de Filas)
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 |
| Tabla de distribución de frecuencias de los niveles de AQI |
| AQI (Intervalos) |
ni (Frec. Absoluta) |
hi (%) |
Ni (Frec. Acumulada Asc.) |
Ni (Frec. Acumulada Desc.) |
Hi (Frec. Acumulada % Asc.) |
Hi (Frec. Acumulada % Desc.) |
| [0,500) |
24305 |
97.81 |
24305 |
24850 |
97.81 |
100.00 |
| [500,1000) |
452 |
1.82 |
24757 |
545 |
99.63 |
2.19 |
| [1000,1500) |
77 |
0.31 |
24834 |
93 |
99.94 |
0.37 |
| [1500,2000) |
15 |
0.06 |
24849 |
16 |
100.00 |
0.06 |
| [2000,2500] |
1 |
0.00 |
24850 |
1 |
100.00 |
0.00 |
| Total |
24850 |
100.00 |
NA |
NA |
NA |
NA |
| Fuente: Datos procesados por el autor a partir de archivo city.day.csv |
# ==============================================================================
# GRÁFICOS PERSONALIZADOS (ACOPLES PARA AQI)
# ==============================================================================
# Ajuste de márgenes para etiquetas largas
par(mar = c(8, 6, 4, 2))
# Diagrama de barras local (Frecuencia Absoluta: ni)
barplot(TDFAQIFin_Agrupada$ni,
main="Gráfica N°1: Distribución de Frecuencia Absoluta de los niveles de AQI\nen India entre 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Frecuencia Absoluta (Días)",
col = "blue",
ylim = c(0,max(TDFAQIFin_Agrupada$ni)),
names.arg = TDFAQIFin_Agrupada$AQI,
las=2,
cex.names=0.6,
cex.axis = 0.7,
cex.main = 0.9,
mgp = c(5, 1 , 0))
mtext("*Los intervalos tienen límite inferior cerrado y superior abierto",
side = 1, line = 6, adj = 0, cex = 0.7)

# Diagrama de barras local (Frecuencia Relativa: hi)
par(mar = c(8, 6, 4, 2))
barplot(TDFAQIFin_Agrupada$hi,
main="Gráfica N°2: Distribución Porcentual de los niveles de AQI\nen India entre 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Porcentaje (%)",
col = "lightblue",
names.arg = TDFAQIFin_Agrupada$AQI,
las=2,
cex.names=0.6,
cex.axis = 0.9,
cex.main = 0.9,
mgp = c(5, 1, 0))

# Diagrama de barras global (Frecuencia Absoluta: ni)
par(mar = c(8, 6, 4, 2))
barplot(TDFAQIFin_Agrupada$ni,
main="Gráfica N°3: Frecuencia Absoluta GLOBAL de los niveles de AQI\nen India entre 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Frecuencia Absoluta (Días)",
col = "lightgreen",
ylim = c(0, sum(TDFAQIFin_Agrupada$ni)),
names.arg = TDFAQIFin_Agrupada$AQI,
las=2,
cex.names=0.6,
cex.axis = 0.9,
cex.main = 0.9,
mgp = c(5, 1, 0))

# Diagrama de barras global (Frecuencia Relativa: hi)
par(mar = c(8, 6, 4, 2))
barplot(TDFAQIFin_Agrupada$hi,
main="Gráfica N°4: Distribución Porcentual GLOBAL de los niveles de AQI\nen India entre 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Porcentaje (%)",
col = "green",
ylim = c(0,100),
names.arg = TDFAQIFin_Agrupada$AQI,
las=2,
cex.names=0.6,
cex.axis = 0.9,
cex.main = 0.9,
mgp = c(5, 1, 0))

# Diagrama de Caja (Boxplot) - Usa la variable AQI_limpio
par(mar = c(4, 6, 4, 2))
boxplot(AQI_limpio,
horizontal = TRUE,
main = "Gráfica N°5: Distribución de los niveles de AQI\nen India entre 2015-2020",
xlab = "Niveles de AQI",
col = "turquoise",
pch = 1)

# Diagrama de Ojiva Absoluta (Ni_asc y Ni_dsc)
par(mar = c(9, 6, 4, 2))
x_pos <- 1:length(TDFAQIFin_Agrupada$AQI)
plot(x_pos , TDFAQIFin_Agrupada$Ni_dsc,
main = "Gráfica N°6: Ojiva de Frecuencia Absoluta de los niveles de AQI\nen India 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Frecuencia Absoluta Acumulada (Ni)",
col = "orange",
type = "o",
lwd = 3,
xaxt="n",
mgp = c(5, 1, 0),
ylim = c(0, max(TDFAQIFin_Agrupada$Ni_asc)))
lines(x_pos, TDFAQIFin_Agrupada$Ni_asc,
col = "green",
type = "o",
lwd = 3)
axis(side = 1, at = x_pos, labels = TDFAQIFin_Agrupada$AQI,
las = 2, cex.axis = 0.6)
legend("bottomleft",
legend = c("Ojiva Descendente (Ni_dsc)", "Ojiva Ascendente (Ni_asc)"),
col = c("orange", "green"), pch = 1, cex = 0.7, lwd = 3)

# Diagrama de Ojiva Porcentual (Hi_asc y Hi_dsc)
par(mar = c(9, 6, 4, 2))
x_por <- 1:length(TDFAQIFin_Agrupada$AQI)
plot(x_pos, TDFAQIFin_Agrupada$Hi_dsc,
main = "Gráfica N°7: Ojiva de Frecuencia Porcentual de los niveles de AQI\nen India 2015-2020",
xlab = "Intervalos de AQI",
ylab = "Porcentaje Acumulado (%)",
col = "red",
type = "o",
mgp = c(5, 1, 0),
lwd = 2,
xaxt="n",
ylim = c(0, 100))
lines(x_pos, TDFAQIFin_Agrupada$Hi_asc,
col = "blue",
type = "o",
lwd = 3)
axis(side = 1, at = x_pos, labels = TDFAQIFin_Agrupada$AQI,
las = 2, cex.axis = 0.6)
legend("bottomleft",
legend = c("Ojiva Descendente (Hi_dsc)", "Ojiva Ascendente (Hi_asc)"),
col = c("red", "blue"), pch = 1, cex = 0.7, lwd = 3)

# ==============================================================================
# 8. CÁLCULO DE INDICADORES ESTADÍSTICOS (AQI) Y TABLA GT (Tabla Nro. 3)
# ==============================================================================
if(!require(e1071)) install.packages("e1071"); library(e1071)
library(gt)
library(dplyr)
# --- Indicadores de Tendencia Central
Me <- median(AQI_limpio)
X <- mean(AQI_limpio)
Mo <- names(sort(table(AQI_limpio), decreasing = TRUE))[1]
# --- Indicadores de Dispersión
sd_calc <- sd(AQI_limpio)
CV <- (sd_calc / X) * 100
# --- Indicadores de Forma
As <- skewness(AQI_limpio, type = 2)
K <- kurtosis(AQI_limpio, type = 2)
# --- Variables de Resumen para la Tabla
Variable <- "AQI (Nivel de Calidad del Aire)"
Rango <- paste0("[", round(min(AQI_limpio), 2), ", ", round(max(AQI_limpio), 2), "]")
# ************************************************
# CÁLCULO DE VALORES ATÍPICOS EN EL FORMATO DESEADO
# ************************************************
boxplot_stats <- boxplot.stats(AQI_limpio)
outliers <- boxplot_stats$out
if (length(outliers) > 0) {
conteo_outliers <- length(outliers)
min_outlier <- round(min(outliers), 0)
max_outlier <- round(max(outliers), 0)
# Formato: "Conteo,[Min_Outlier,Max_Outlier]"
valoresatipicos_calc <- paste0(conteo_outliers, ",[", min_outlier, ",", max_outlier, "]")
} else {
valoresatipicos_calc <- "Ninguno"
}
# ************************************************
# --- Creación del Data Frame de Indicadores (Tabla Nro. 3)
Tabla_indicadores <- data.frame(
Variable,
Rango,
round(X, 2),
round(Me, 2),
Mo,
round(sd_calc, 2),
round(CV, 2),
round(As, 2),
round(K, 2),
valoresatipicos_calc
)
# Nombres de las columnas
colnames(Tabla_indicadores) <- c("Variable","Rango","Media (X)", "Mediana (Me)", "Moda (Mo)","Desv. Est. (sd)","CV (%)","Asimetría (As)","Curtosis (K)","Valores Atípicos")
# --- Generación de la Tabla GT (Tabla Nro. 3: Indicadores)
Tabla_indicadores %>%
gt() %>%
tab_header(
title = md("*Tabla Nro. 3*"),
subtitle = md("**Indicadores Estadísticos de los Niveles de AQI en India (2015-2020)**")
) %>%
tab_source_note(
source_note = md("Fuente: Datos procesados por el autor a partir de archivo city.day.csv")
) %>%
fmt_number(
columns = c(`Media (X)`, `Mediana (Me)`, `Desv. Est. (sd)`, `CV (%)`, `Asimetría (As)`, `Curtosis (K)`),
decimals = 2
) %>%
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. 3 |
| Indicadores Estadísticos de los Niveles de AQI en India (2015-2020) |
| Variable |
Rango |
Media (X) |
Mediana (Me) |
Moda (Mo) |
Desv. Est. (sd) |
CV (%) |
Asimetría (As) |
Curtosis (K) |
Valores Atípicos |
| AQI (Nivel de Calidad del Aire) |
[13, 2049] |
166.46 |
118.00 |
102 |
140.70 |
84.52 |
3.40 |
21.42 |
1358,[399,2049] |
| Fuente: Datos procesados por el autor a partir de archivo city.day.csv |