Primero, cargamos las librerías necesarias para la limpieza de datos, el cálculo estadístico y la presentación de tablas.
library(dplyr)
library(janitor)
library(moments)
library(gt)
Cargamos el archivo CSV y procesamos la columna
DATE_SUBMITTE para extraer únicamente el año.
datos <- read.csv(
"C:/Users/Martin/Desktop/Estadistica/CMDB_Data.csv",
header = TRUE,
sep = ";",
dec = ".",
fileEncoding = "UTF-8-BOM",
check.names = FALSE
)
# Limpiar los nombres de las columnas.
df <- clean_names(datos)
# Usar la columna DATE_SUBMITTE, que contiene día, mes y año.
# Después de clean_names(), la columna queda como date_submitte.
if (!"date_submitte" %in% names(df)) {
stop(paste0(
"No se encontró la columna DATE_SUBMITTE. Columnas disponibles: ",
paste(names(df), collapse = ", ")
))
}
fechas_texto <- trimws(as.character(df$date_submitte))
# Convertir la fecha completa a tipo Date.
fecha_submitte <- as.Date(fechas_texto, tryFormats = c(
"%d/%m/%Y",
"%m/%d/%Y",
"%Y-%m-%d",
"%Y/%m/%d",
"%d-%m-%Y",
"%m-%d-%Y"
))
# Extraer solo el año.
anio <- as.numeric(format(fecha_submitte, "%Y"))
PrimerAnio <- na.omit(anio)
if (length(PrimerAnio) == 0) {
stop("No se pudieron extraer años válidos desde DATE_SUBMITTE.")
}
Calculamos las frecuencias absolutas, relativas porcentuales y acumuladas, agregando una fila de totales al final.
TDFPrimerAnio <- table(PrimerAnio)
TablaPrimerAnio <- as.data.frame(TDFPrimerAnio, stringsAsFactors = FALSE)
if (ncol(TablaPrimerAnio) != 2) {
stop("La tabla de frecuencias no tiene el formato esperado. Revisa que PrimerAnio tenga datos válidos.")
}
names(TablaPrimerAnio) <- c("Anio", "Freq")
# Cálculo de frecuencias simples y acumuladas.
ni <- TablaPrimerAnio$Freq
hi_porc <- (ni / sum(ni)) * 100
Ni_asc <- cumsum(ni)
Hi_asc <- cumsum(hi_porc)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_dsc <- rev(cumsum(rev(hi_porc)))
# Crear la tabla principal.
TablaPrimerAnioFinal <- data.frame(
Anio = as.character(TablaPrimerAnio$Anio),
ni = ni,
hi_porc = round(hi_porc, 2),
Ni_asc = Ni_asc,
Hi_asc = round(Hi_asc, 2),
Ni_dsc = Ni_dsc,
Hi_dsc = round(Hi_dsc, 2)
)
# Agregar fila de totales.
Fila_Total <- data.frame(
Anio = "TOTAL",
ni = sum(TablaPrimerAnioFinal$ni),
hi_porc = round(sum(TablaPrimerAnioFinal$hi_porc), 0),
Ni_asc = NA,
Hi_asc = NA,
Ni_dsc = NA,
Hi_dsc = NA
)
TablaFinal_Con_Totales <- rbind(TablaPrimerAnioFinal, Fila_Total)
tabla_frecuencias_gt <- TablaFinal_Con_Totales %>%
gt() %>%
tab_header(
title = md("**Tabla N° 1**"),
subtitle = md("Distribución de frecuencias por año de envío")
) %>%
tab_source_note(
source_note = md("Autores: Grupo 1")
) %>%
cols_label(
Anio = "Año",
ni = "Frecuencia absoluta (ni)",
hi_porc = "Frecuencia relativa (%)",
Ni_asc = "Frecuencia acumulada ascendente",
Hi_asc = "% acumulado ascendente",
Ni_dsc = "Frecuencia acumulada descendente",
Hi_dsc = "% acumulado descendente"
) %>%
fmt_number(columns = c(hi_porc, Hi_asc, Hi_dsc), decimals = 2) %>%
fmt_number(columns = c(ni, Ni_asc, Ni_dsc), decimals = 0) %>%
sub_missing(columns = everything(), missing_text = "") %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(rows = Anio == "TOTAL")
) %>%
tab_options(
table.border.top.color = "black",
table.border.bottom.color = "black",
heading.border.bottom.color = "black",
heading.border.bottom.width = px(2),
column_labels.border.top.color = "black",
column_labels.border.bottom.color = "black",
column_labels.border.bottom.width = px(2),
table_body.hlines.color = "gray",
table_body.border.bottom.color = "black",
row.striping.include_table_body = TRUE
)
tabla_frecuencias_gt
| Tabla N° 1 | ||||||
| Distribución de frecuencias por año de envío | ||||||
| Año | Frecuencia absoluta (ni) | Frecuencia relativa (%) | Frecuencia acumulada ascendente | % acumulado ascendente | Frecuencia acumulada descendente | % acumulado descendente |
|---|---|---|---|---|---|---|
| 2011 | 32 | 2.34 | 32 | 2.34 | 1,366 | 100.00 |
| 2012 | 25 | 1.83 | 57 | 4.17 | 1,334 | 97.66 |
| 2013 | 462 | 33.82 | 519 | 37.99 | 1,309 | 95.83 |
| 2014 | 89 | 6.52 | 608 | 44.51 | 847 | 62.01 |
| 2015 | 162 | 11.86 | 770 | 56.37 | 758 | 55.49 |
| 2017 | 596 | 43.63 | 1,366 | 100.00 | 596 | 43.63 |
| TOTAL | 1,366 | 100.00 | ||||
| Autores: Grupo 1 | ||||||
A continuación se presentan las distribuciones de envíos por año en valores absolutos y porcentuales.
# Límite superior dinámico para la frecuencia absoluta.
limite_max_y <- max(TablaPrimerAnioFinal$ni, na.rm = TRUE) * 1.2
barplot(
TablaPrimerAnioFinal$ni,
main = "Gráfico N° 1: Distribución de cantidad por año",
xlab = "Año",
ylab = "Cantidad",
col = "orange",
names.arg = TablaPrimerAnioFinal$Anio,
ylim = c(0, limite_max_y),
las = 2,
cex.names = 0.8,
cex.axis = 0.8
)
barplot(
TablaPrimerAnioFinal$ni,
main = "Gráfico N° 2: Distribución por año en escala total",
xlab = "Año",
ylab = "Cantidad",
col = "red",
names.arg = TablaPrimerAnioFinal$Anio,
ylim = c(0, max(TablaPrimerAnioFinal$ni, na.rm = TRUE) * 1.2),
las = 2,
cex.names = 0.8,
cex.axis = 0.8
)
# Límite superior dinámico para el porcentaje.
limite_max_y_porc <- max(TablaPrimerAnioFinal$hi_porc, na.rm = TRUE) * 1.2
barplot(
TablaPrimerAnioFinal$hi_porc,
main = "Gráfico N° 3: Distribución porcentual por año",
xlab = "Año",
ylab = "Porcentaje (%)",
col = "skyblue",
names.arg = TablaPrimerAnioFinal$Anio,
ylim = c(0, limite_max_y_porc),
las = 2,
cex.names = 0.8,
cex.axis = 0.8
)
barplot(
TablaPrimerAnioFinal$hi_porc,
main = "Gráfico N° 4: Distribución porcentual en escala 100%",
xlab = "Año",
ylab = "Porcentaje (%)",
col = "blue",
names.arg = TablaPrimerAnioFinal$Anio,
ylim = c(0, 100),
las = 2,
cex.names = 0.8,
cex.axis = 0.8
)
x <- as.numeric(TablaPrimerAnioFinal$Anio)
limite_max_y <- max(TablaPrimerAnioFinal$Ni_asc, na.rm = TRUE)
plot(
x,
TablaPrimerAnioFinal$Ni_asc,
type = "b",
pch = 19,
main = "Gráfico N° 5: Ojivas de frecuencia acumulada",
xlab = "Año",
ylab = "Frecuencia acumulada",
col = "green",
ylim = c(0, limite_max_y),
xaxt = "n"
)
lines(x, TablaPrimerAnioFinal$Ni_dsc, type = "b", pch = 19, col = "blue")
axis(1, at = x, labels = x, las = 2)
legend(
"topleft",
legend = c("Ascendente", "Descendente"),
col = c("green", "blue"),
pch = 19,
bty = "n"
)
plot(
x,
TablaPrimerAnioFinal$Hi_asc,
type = "b",
pch = 19,
main = "Gráfico N° 6: Ojivas porcentuales",
xlab = "Año",
ylab = "% acumulado",
col = "green",
ylim = c(0, 100),
xaxt = "n"
)
lines(x, TablaPrimerAnioFinal$Hi_dsc, type = "b", pch = 19, col = "blue")
axis(1, at = x, labels = x, las = 2)
legend(
"topleft",
legend = c("Ascendente", "Descendente"),
col = c("green", "blue"),
pch = 19,
bty = "n"
)
Resumen estadístico de los datos analizados.
cuartiles <- quantile(PrimerAnio, probs = c(0.25, 0.5, 0.75))
media <- mean(PrimerAnio)
desviacion <- sd(PrimerAnio)
tabla_estadisticas <- data.frame(
"Mínimo" = min(PrimerAnio),
"Máximo" = max(PrimerAnio),
"Rango" = max(PrimerAnio) - min(PrimerAnio),
"Media" = round(media, 2),
"Mediana" = median(PrimerAnio),
"Q1" = cuartiles[1],
"Q3" = cuartiles[3],
"Varianza" = round(var(PrimerAnio), 2),
"Desviación estándar" = round(desviacion, 2),
"Coeficiente de variación (%)" = round(desviacion / media * 100, 2),
"Asimetría" = round(skewness(PrimerAnio), 2),
"Curtosis" = round(kurtosis(PrimerAnio), 2),
check.names = FALSE
)
tabla_estadisticas_gt <- tabla_estadisticas %>%
gt() %>%
tab_header(
title = md("**Tabla N° 2**"),
subtitle = md("Medidas estadísticas de los años de envío")
) %>%
tab_source_note(
source_note = md("Autores: Grupo 1")
) %>%
tab_options(
table.border.top.color = "black",
table.border.bottom.color = "black",
heading.border.bottom.color = "black",
heading.border.bottom.width = px(2),
column_labels.border.top.color = "black",
column_labels.border.bottom.color = "black",
column_labels.border.bottom.width = px(2),
table_body.hlines.color = "gray",
table_body.border.bottom.color = "black",
row.striping.include_table_body = TRUE
)
tabla_estadisticas_gt
| Tabla N° 2 | |||||||||||
| Medidas estadísticas de los años de envío | |||||||||||
| Mínimo | Máximo | Rango | Media | Mediana | Q1 | Q3 | Varianza | Desviación estándar | Coeficiente de variación (%) | Asimetría | Curtosis |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2011 | 2017 | 6 | 2014.98 | 2015 | 2013 | 2017 | 3.71 | 1.92 | 0.1 | -0.15 | 1.45 |
| Autores: Grupo 1 | |||||||||||
Identificación de valores atípicos mediante el método del rango intercuartílico (IQR).
IQR_val <- cuartiles[3] - cuartiles[1]
limite_inferior <- cuartiles[1] - 1.5 * IQR_val
limite_superior <- cuartiles[3] + 1.5 * IQR_val
outliers <- PrimerAnio[PrimerAnio < limite_inferior | PrimerAnio > limite_superior]
num_outliers <- length(outliers)
Tabla_outliers <- data.frame(
"Cantidad de outliers" = num_outliers,
"Valor mínimo atípico" = if (num_outliers > 0) min(outliers) else NA,
"Valor máximo atípico" = if (num_outliers > 0) max(outliers) else NA,
check.names = FALSE
)
tabla_outliers_gt <- Tabla_outliers %>%
gt() %>%
tab_header(
title = md("**Tabla N° 3**"),
subtitle = md("Análisis de valores atípicos")
) %>%
tab_source_note(
source_note = md("Autores: Grupo 1")
) %>%
sub_missing(columns = everything(), missing_text = "No aplica") %>%
tab_options(
table.border.top.color = "black",
table.border.bottom.color = "black",
heading.border.bottom.color = "black",
heading.border.bottom.width = px(2),
column_labels.border.top.color = "black",
column_labels.border.bottom.color = "black",
column_labels.border.bottom.width = px(2),
table_body.hlines.color = "gray",
table_body.border.bottom.color = "black",
row.striping.include_table_body = TRUE
)
tabla_outliers_gt
| Tabla N° 3 | ||
| Análisis de valores atípicos | ||
| Cantidad de outliers | Valor mínimo atípico | Valor máximo atípico |
|---|---|---|
| 0 | No aplica | No aplica |
| Autores: Grupo 1 | ||
Conclusión de la variable
DATE_SUBMITTE
La distribución temporal presenta una concentración marcada en años específicos. El año 2017 registra la mayor frecuencia absoluta, seguido por el año 2013. En conjunto, estos dos años agrupan la mayor parte del volumen total de registros, lo que evidencia que la toma o registro de muestras no se distribuye de manera uniforme a lo largo del tiempo.