Carga y Limpieza de Datos
# Instalación de librerías
if (!require("ggplot2")) install.packages("ggplot2")
if (!require("scales")) install.packages("scales")
if (!require("e1071")) install.packages("e1071")
if (!require("knitr")) install.packages("knitr")
library(ggplot2)
library(scales)
library(e1071)
library(knitr)
# setwd("C:/Users/ronal/OneDrive/Desktop") # Ajusta según tu necesidad
# Carga de datos
datos <- read.csv("database (1).csv", header = TRUE, sep = ",", dec = ".")
# Extracción y limpieza
All.Costs <- na.omit(datos$All.Costs)
All.Costs <- All.Costs[All.Costs > 0]
Tabla de Distribución de Frecuencias
xmin <- min(All.Costs)
xmax <- max(All.Costs)
R <- xmax - xmin
K <- floor(1 + 3.3 * log10(length(All.Costs)))
A <- R / K
# Límites y Marcas de Clase
Li <- round(seq(from = xmin, to = xmax - A, by = A), 2)
Ls <- round(seq(from = xmin + A, to = xmax, by = A), 2)
MC <- round((Li + Ls) / 2)
# Frecuencias
ni <- numeric(K)
for (i in 1:(K-1)) {
ni[i] <- sum(All.Costs >= Li[i] & All.Costs < Ls[i])
}
ni[K] <- sum(All.Costs >= Li[K] & All.Costs <= xmax)
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 <- data.frame(Li, Ls, MC, ni, hi_porc = round(hi, 2), Ni_asc, Ni_desc,
Hi_asc_porc = round(Hi_asc, 2), Hi_desc_porc = round(Hi_desc, 2))
knitr::kable(TDF, caption = "Tabla No. 1: Tabla de Distribución de Frecuencias de costos totales")
Tabla No. 1: Tabla de Distribución de Frecuencias de costos
totales
| 1 |
70043844 |
35021923 |
2757 |
99.86 |
2757 |
2761 |
99.86 |
100.00 |
| 70043844 |
140087687 |
105065766 |
2 |
0.07 |
2759 |
4 |
99.93 |
0.14 |
| 140087687 |
210131530 |
175109609 |
1 |
0.04 |
2760 |
2 |
99.96 |
0.07 |
| 210131530 |
280175373 |
245153452 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 280175373 |
350219216 |
315197295 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 350219216 |
420263060 |
385241138 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 420263060 |
490306903 |
455284981 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 490306903 |
560350746 |
525328824 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 560350746 |
630394589 |
595372667 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 630394589 |
700438432 |
665416510 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 700438432 |
770482275 |
735460353 |
0 |
0.00 |
2760 |
1 |
99.96 |
0.04 |
| 770482275 |
840526118 |
805504196 |
1 |
0.04 |
2761 |
1 |
100.00 |
0.04 |
Nueva tabla de Frecuencia
### Se seleccionó el primer intervalo de la variable costos totales para el análisis, debido a que en este se concentra la mayorcantidad de datos. Esta elección permite construir la tabla de frecuencia y gráficas más claras y legibles, facilitando la interpretación de la distribución de los datos y evitando distorsiones visuales provocadas por intervalos con baja frecuencia. ###
umbral_90 <- quantile(All.Costs, 0.90)
datos_zoom <- All.Costs[All.Costs <= umbral_90]
n_z <- length(datos_zoom)
xmin_z <- min(datos_zoom)
xmax_z <- max(datos_zoom)
K_z <- floor(1 + 3.322 * log10(n_z))
A_z <- (xmax_z - xmin_z) / K_z
cortes_z <- seq(xmin_z, xmin_z + (K_z * A_z), by = A_z)
Li_z <- cortes_z[1:K_z]
Ls_z <- cortes_z[2:(K_z + 1)]
MC_z <- (Li_z + Ls_z) / 2
ni_z <- numeric(K_z)
for (i in 1:(K_z - 1)) {
ni_z[i] <- sum(datos_zoom >= Li_z[i] & datos_zoom < Ls_z[i])
}
ni_z[K_z] <- sum(datos_zoom >= Li_z[K_z] & datos_zoom <= xmax_z)
hi_z <- (ni_z / n_z) * 100
Ni_asc_z <- cumsum(ni_z)
Ni_desc_z <- rev(cumsum(rev(ni_z)))
Hi_asc_z <- cumsum(hi_z)
Hi_desc_z <- rev(cumsum(rev(hi_z)))
TDF_final_zoom <- data.frame(
Li = round(Li_z, 2), Ls = round(Ls_z, 2), MC = round(MC_z, 2),
ni = ni_z, hi_porc = round(hi_z, 2), Ni_asc = Ni_asc_z,
Ni_desc = Ni_desc_z, Hi_asc_porc = round(Hi_asc_z, 2), Hi_desc_porc = round(Hi_desc_z, 2)
)
kable(TDF_final_zoom, caption = "Tabla No. 2: Tabla de Distribución de Frecuencias")
Tabla No. 2: Tabla de Distribución de Frecuencias
| 1.00 |
43809.25 |
21905.12 |
1695 |
68.21 |
1695 |
2485 |
68.21 |
100.00 |
| 43809.25 |
87617.50 |
65713.38 |
286 |
11.51 |
1981 |
790 |
79.72 |
31.79 |
| 87617.50 |
131425.75 |
109521.62 |
120 |
4.83 |
2101 |
504 |
84.55 |
20.28 |
| 131425.75 |
175234.00 |
153329.88 |
103 |
4.14 |
2204 |
384 |
88.69 |
15.45 |
| 175234.00 |
219042.25 |
197138.12 |
68 |
2.74 |
2272 |
281 |
91.43 |
11.31 |
| 219042.25 |
262850.50 |
240946.38 |
50 |
2.01 |
2322 |
213 |
93.44 |
8.57 |
| 262850.50 |
306658.75 |
284754.62 |
44 |
1.77 |
2366 |
163 |
95.21 |
6.56 |
| 306658.75 |
350467.00 |
328562.88 |
23 |
0.93 |
2389 |
119 |
96.14 |
4.79 |
| 350467.00 |
394275.25 |
372371.12 |
31 |
1.25 |
2420 |
96 |
97.38 |
3.86 |
| 394275.25 |
438083.50 |
416179.38 |
24 |
0.97 |
2444 |
65 |
98.35 |
2.62 |
| 438083.50 |
481891.75 |
459987.62 |
15 |
0.60 |
2459 |
41 |
98.95 |
1.65 |
| 481891.75 |
525700.00 |
503795.88 |
26 |
1.05 |
2485 |
26 |
100.00 |
1.05 |
Graficas de Histogramas
Gráfica No. 1: Histograma de Frecuencia Absoluta
#Gráfica No. 1: Distribución global de costos totales
options(scipen = 999)
hist(datos_zoom,
main = "Gráfica No. 1: Distribución de Costos Totales",
ylab = "Cantidad",
xlab = "Costos Totales",
col = "grey",
breaks = K_z,
ylim = c(0, n_z),
las = 2)

Gráfica No. 2: Histograma Local de Costos Totales
options(scipen = 999)
hist(datos_zoom,
main = "Gráfica No. 2:Costos Totales",
xlab = "Costos Totales",
ylab = "Cantidad",
col = "grey",
breaks = K_z,
las = 2)

Gráfica 3. Porcentaje global de Costos Totales
p_hi_global <- ggplot(TDF, aes(x = MC, y = hi_porc)) +
geom_col(fill = "gray70", color = "black", alpha = 0.7, width = A) +
scale_x_continuous(labels = comma) +
scale_y_continuous(labels = function(x) paste0(x, "%"), limits = c(0, 100)) +
labs(title = "Gráfica N. 3 : Porcentaje de Costos Totales", x = "Costos Totales", y = "Porcentaje (%)") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.line = element_line(color = "black"))
print(p_hi_global)

Gráfica 4. Distribucion de Costos Totales
limite_max <- max(TDF_final_zoom$Ls)
quiebres_x <- seq(0, limite_max + 100000, by = 100000)
p_hi_local <- ggplot(TDF_final_zoom, aes(x = MC, y = hi_porc)) +
geom_col(fill = "steelblue", color = "black", alpha = 0.8, width = A_z) +
scale_x_continuous(breaks = quiebres_x,
labels = comma) +
scale_y_continuous(labels = function(x) paste0(x, "%"),
expand = expansion(mult = c(0, 0.05))) +
labs(title = "Gráfica N. 4: Distribución de los Costos Totales",
subtitle = "Frecuencia relativa agrupada por intervalos de clase",
x = "Costos Totales (USD)",
y = "Porcentaje (%)") +
# Estética profesional
theme_classic() +
theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
panel.grid.major.y = element_line(color = "gray90")) # Añade líneas guía horizontales
print(p_hi_local)

Análisis de Ojivas descententes y ascendentes
Ojivas Ni
# Ojivas Ni
library(ggplot2)
library(scales)
eje_x <- c(TDF_final_zoom$Li[1], TDF_final_zoom$Ls)
ni_asc_alineado <- c(0, TDF_final_zoom$Ni_asc)
ni_desc_ajustado <- c(TDF_final_zoom$Ni_asc[nrow(TDF_final_zoom)], TDF_final_zoom$Ni_desc)
df_ni_final <- data.frame(x = eje_x, y_asc = ni_asc_alineado, y_desc = ni_desc_ajustado)
# 2. Construcción de la Gráfica
ggplot(df_ni_final) +
# Ojiva Ascendente
geom_line(aes(x = x, y = y_asc, color = "Ascendente"), linewidth = 1.2) +
geom_point(aes(x = x, y = y_asc, color = "Ascendente"), size = 3) +
# Ojiva Descendente
geom_line(aes(x = x, y = y_desc, color = "Descendente"), linewidth = 1.2, linetype = "solid") +
geom_point(aes(x = x, y = y_desc, color = "Descendente"), size = 3) +
scale_x_continuous(labels = comma) +
scale_y_continuous(labels = comma) +
scale_color_manual(values = c("Ascendente" = "blue4", "Descendente" = "red3")) +
labs(title = "Gráfica 5: Ojivas de Frecuencia Absoluta",
subtitle = "Comparativa de distribución acumulada ascendente y descendente",
x = "Costos Totales",
y = "Cantidad Acumulada (Ni)",
color = "Tipo de Ojiva") +
theme_bw() +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", size = 14))

Ojivas Hi
library(ggplot2)
library(scales)
hi_asc_alineado <- c(0, TDF_final_zoom$Hi_asc_porc)
hi_desc_alineado <- c(100, TDF_final_zoom$Hi_desc_porc)
df_hi_final <- data.frame(x = eje_x, y_asc = hi_asc_alineado, y_desc = hi_desc_alineado)
# 2. Construcción de la Gráfica
ggplot(df_hi_final) +
# Ojiva Ascendente
geom_line(aes(x = x, y = y_asc, color = "Ascendente"), linewidth = 1.2) +
geom_point(aes(x = x, y = y_asc, color = "Ascendente"), size = 3) +
# Ojiva Descendente
geom_line(aes(x = x, y = y_desc, color = "Descendente"), linewidth = 1.2, linetype = "solid") +
geom_point(aes(x = x, y = y_desc, color = "Descendente"), size = 3) +
scale_x_continuous(labels = comma) +
scale_y_continuous(labels = function(x) paste0(x, "%"), limits = c(0, 100)) +
scale_color_manual(values = c("Ascendente" = "blue4", "Descendente" = "red3")) +
labs(title = "Gráfica 6: Ojivas de Frecuencia Relativa",
subtitle = "Distribución porcentual acumulada",
x = "Costos Totales",
y = "Porcentaje Acumulado (%)",
color = "Tipo de Ojiva") +
theme_bw() +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", size = 14))

Diagrama de Caja (Boxplot)
boxplot(datos_zoom, horizontal = TRUE, col = "gray",
main = "Gráfica No. 7: Distribución de Costos Totales",
xlab = "Costo Total", las = 1, pch = 19, outcol = "black")
axis(1, at = pretty(range(datos_zoom)), labels = format(pretty(range(datos_zoom)), big.mark = ","))

Indicadores Estadísticos
library(knitr)
library(moments)
datos_analisis <- datos_zoom[!is.na(datos_zoom) & datos_zoom > 0]
n <- length(datos_analisis)
min_real <- min(datos_analisis)
max_real <- max(datos_analisis)
k <- ceiling(1 + 3.322 * log10(n))
cortes <- seq(min_real, max_real, length.out = k + 1)
intervalos_f <- cut(datos_analisis,
breaks = cortes,
include.lowest = TRUE,
right = FALSE,
dig.lab = 10)
tab_freq <- as.data.frame(table(intervalos_f))
pos_modal <- which.max(tab_freq$Freq)
moda_raw <- as.character(tab_freq$intervalos_f[pos_modal])
moda_limpia <- gsub("\\[|\\]|\\)", "", moda_raw)
moda_limpia <- gsub(",", " a ", moda_limpia)
media_val <- mean(datos_analisis)
mediana_val <- median(datos_analisis)
S_val <- sd(datos_analisis)
CV_val <- (S_val / media_val) * 100
As_val <- skewness(datos_analisis)
K_val <- kurtosis(datos_analisis)
# 6. Tabla Final
Tabla_Resultados <- data.frame(
Variable = "Costos Totales",
Mínimo = round(min_real, 2),
Máximo = round(max_real, 2),
Media = round(media_val, 2),
Mediana = round(mediana_val, 2),
Moda = moda_limpia, # Empezará en 524
SD = round(S_val, 2),
CV = paste0(round(CV_val, 2), "%"),
As = round(As_val, 2),
K = round(K_val, 2)
)
kable(Tabla_Resultados, format = "markdown", align = "c",
caption = "Tabla 1: Indicadores Estadísticos (Moda anclada al mínimo real).")
Tabla 1: Indicadores Estadísticos (Moda anclada al mínimo
real).
| Costos Totales |
1 |
525700 |
62015.52 |
18757 |
1 a 40439.38462 |
102072.4 |
164.59% |
2.46 |
8.9 |
Tabla de indicadores estadisticos
Tabla_Resultados <- data.frame(
Variable = "Costos Totales",
Mínimo = round(min_real, 2),
Máximo = round(max_real, 2),
Media = round(media_val, 2),
Mediana = round(mediana_val, 2),
Moda = moda_limpia,
SD = round(S_val, 2),
CV = paste0(round(CV_val, 2), "%"),
As = round(As_val, 2),
K = round(K_val, 2)
)
kable(Tabla_Resultados, format = "markdown", align = "c",
caption = "Tabla 1: Indicadores Estadísticos")
Tabla 1: Indicadores Estadísticos
| Costos Totales |
1 |
525700 |
62015.52 |
18757 |
1 a 40439.38462 |
102072.4 |
164.59% |
2.46 |
8.9 |
###IMPORTANTE##
## Se determinó que la moda se encuentra en el intervalo inicial (aproximadamente 1 a más de 40000) debido a la alta concentración de frecuencias en los valores inferiores de la muestra. Aunque el valor mínimo registrado es de $524, la metodología de intervalos de clase agrupa estos registros dentro de una primera categoría de mayor densidad.
Análisis de valores Atípicos
stats_outliers <- boxplot.stats(datos_zoom)$out
num_outliers <- length(stats_outliers)
cat("\nCantidad de valores atípicos detectados:", num_outliers, "\n")
##
## Cantidad de valores atípicos detectados: 354
Conclusiones
“La variable ‘Costos Totales’ fluctúa entre 1 USD hasta 525700 USD, y
sus valores se sitúan al rededor de 62015.52 USD, con una desviación
estándar de 1027204 USD, siendo esta una variable muy heterogénea, cuyos
valores se concentran en el intervalo inicial , lo que evidencia una
asimetría positiva marcada por la presencia de valores atípicos (354
outliers).Por todo esto la variable presenta un comportamiento
impredecible y volátil, lo cual resulta perjudicial.”