library(gt)
library(tidyr)
library(ggplot2)
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
ruta_dataset <- "dataset_geologico_limpio_80.....csv"
if (!file.exists(ruta_dataset)) {
message("Seleccione manualmente el archivo CSV del análisis.")
ruta_dataset <- file.choose()
}
datos <- read.csv(
ruta_dataset,
header = TRUE, sep = ",", dec = ".",
stringsAsFactors = FALSE
)
clasificacion <- trimws(toupper(datos$CLASSIFICATION))
clasificacion <- clasificacion[
!is.na(clasificacion) & clasificacion != ""
]
# Éxito: presencia de SAND.
# No éxito: cualquier otra clasificación sedimentaria.
# Esta codificación no ordena categorías según sus frecuencias.
exito <- ifelse(clasificacion == "SAND", 1, 0)
n <- 10
numero_bloques <- floor(length(exito) / n)
exito_completo <- exito[seq_len(numero_bloques * n)]
conteo_exitos <- rowSums(matrix(exito_completo, ncol = n, byrow = TRUE))
cat("Registros válidos:", length(clasificacion), "\n")
## Registros válidos: 27784
cat("Muestras clasificadas como SAND:", sum(exito), "\n")
## Muestras clasificadas como SAND: 15999
cat("Muestras con otras clasificaciones:", sum(exito == 0), "\n")
## Muestras con otras clasificaciones: 11785
cat("Bloques de 10 muestras:", numero_bloques, "\n")
## Bloques de 10 muestras: 2778
La variable CLASSIFICATION identifica la clasificación
sedimentaria de cada muestra. Para aplicar el modelo binomial se plantea
la siguiente pregunta: ¿cuántas muestras clasificadas como
SAND aparecen en cada bloque de 10
observaciones?
Cada muestra se analiza con respecto a ese evento y puede producir dos resultados:
SAND.CLAY, SILT,
GRAVEL, SILTY CLAY, entre otras.En este contexto, las palabras éxito y no
éxito solo permiten distinguir entre la presencia y la ausencia
de SAND.
valores <- 0:n
ni <- as.numeric(table(factor(conteo_exitos, levels = valores)))
TDF <- data.frame(Exitos = valores, ni = ni) %>%
mutate(
hi = ni / sum(ni) * 100,
Ni_asc = cumsum(ni),
Ni_dsc = rev(cumsum(rev(ni))),
Hi_asc = cumsum(hi),
Hi_dsc = rev(cumsum(rev(hi)))
)
tabla_frecuencias <- bind_rows(
mutate(TDF, Exitos = as.character(Exitos)),
data.frame(
Exitos = "TOTAL", ni = sum(TDF$ni), hi = 100,
Ni_asc = NA, Ni_dsc = NA, Hi_asc = NA, Hi_dsc = NA
)
)
tabla_frecuencias %>%
gt() %>%
tab_header(
title = md("**Tabla N.° 1**"),
subtitle = "Distribución del número de clasificaciones SAND por bloque"
) %>%
fmt_number(columns = c(hi, Hi_asc, Hi_dsc), decimals = 2) %>%
sub_missing(columns = everything(), missing_text = "")
| Tabla N.° 1 | ||||||
| Distribución del número de clasificaciones SAND por bloque | ||||||
| Exitos | ni | hi | Ni_asc | Ni_dsc | Hi_asc | Hi_dsc |
|---|---|---|---|---|---|---|
| 0 | 0 | 0.00 | 0 | 2778 | 0.00 | 100.00 |
| 1 | 12 | 0.43 | 12 | 2778 | 0.43 | 100.00 |
| 2 | 49 | 1.76 | 61 | 2766 | 2.20 | 99.57 |
| 3 | 161 | 5.80 | 222 | 2717 | 7.99 | 97.80 |
| 4 | 366 | 13.17 | 588 | 2556 | 21.17 | 92.01 |
| 5 | 598 | 21.53 | 1186 | 2190 | 42.69 | 78.83 |
| 6 | 680 | 24.48 | 1866 | 1592 | 67.17 | 57.31 |
| 7 | 535 | 19.26 | 2401 | 912 | 86.43 | 32.83 |
| 8 | 283 | 10.19 | 2684 | 377 | 96.62 | 13.57 |
| 9 | 79 | 2.84 | 2763 | 94 | 99.46 | 3.38 |
| 10 | 15 | 0.54 | 2778 | 15 | 100.00 | 0.54 |
| TOTAL | 2778 | 100.00 | ||||
barplot(
TDF$ni,
names.arg = TDF$Exitos,
col = "gray75", border = "gray30", space = 0.15,
main = "Gráfica N.° 1\nClasificaciones SAND por bloque de 10 muestras",
xlab = "Número de éxitos",
ylab = "Frecuencia absoluta"
)
Mediante la gráfica se observa cuántas muestras SAND
aparecen en cada bloque de 10 observaciones. El modelo no intenta
ordenar todas las clasificaciones; únicamente distingue si
SAND está presente o ausente en cada muestra. Debido a que
existe un número fijo de ensayos, dos resultados posibles respecto al
evento y una probabilidad constante de presencia, se plantea como
conjetura un modelo binomial.
p <- mean(exito_completo)
N <- length(conteo_exitos)
cat("Número de ensayos por bloque (n):", n, "\n")
## Número de ensayos por bloque (n): 10
cat("Probabilidad estimada de éxito (p):", round(p, 6), "\n")
## Probabilidad estimada de éxito (p): 0.575846
cat("Número de bloques:", N, "\n")
## Número de bloques: 2778
El parámetro \(n=10\) representa el
número fijo de muestras revisadas en cada bloque. El parámetro \(p\) representa la probabilidad estimada de
encontrar una muestra SAND; por su parte, \(1-p\) representa la probabilidad de
encontrar cualquiera de las demás clasificaciones. Por ello, la variable
analizada es el conteo de muestras SAND dentro de cada
bloque y puede tomar valores puntuales entre 0 y 10.
Fe <- N * dbinom(valores, size = n, prob = p)
comparativa <- TDF %>%
mutate(
Frecuencia_Esperada = Fe,
Diferencia = ni - Frecuencia_Esperada,
Error_Porcentual = abs(Diferencia) /
ifelse(ni == 0, 1, ni) * 100
)
comparativa %>%
gt() %>%
tab_header(
title = md("**Tabla N.° 2**"),
subtitle = "Realidad observada y modelo binomial"
) %>%
fmt_number(
columns = c(Frecuencia_Esperada, Diferencia, Error_Porcentual),
decimals = 4
)
| Tabla N.° 2 | |||||||||
| Realidad observada y modelo binomial | |||||||||
| Exitos | ni | hi | Ni_asc | Ni_dsc | Hi_asc | Hi_dsc | Frecuencia_Esperada | Diferencia | Error_Porcentual |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0.0000000 | 0 | 2778 | 0.0000000 | 100.0000000 | 0.5236 | −0.5236 | 52.3563 |
| 1 | 12 | 0.4319654 | 12 | 2778 | 0.4319654 | 100.0000000 | 7.1081 | 4.8919 | 40.7661 |
| 2 | 49 | 1.7638589 | 61 | 2766 | 2.1958243 | 99.5680346 | 43.4257 | 5.5743 | 11.3762 |
| 3 | 161 | 5.7955364 | 222 | 2717 | 7.9913607 | 97.8041757 | 157.2164 | 3.7836 | 2.3501 |
| 4 | 366 | 13.1749460 | 588 | 2556 | 21.1663067 | 92.0086393 | 373.5240 | −7.5240 | 2.0558 |
| 5 | 598 | 21.5262779 | 1186 | 2190 | 42.6925846 | 78.8336933 | 608.5307 | −10.5307 | 1.7610 |
| 6 | 680 | 24.4780418 | 1866 | 1592 | 67.1706263 | 57.3074154 | 688.4682 | −8.4682 | 1.2453 |
| 7 | 535 | 19.2584593 | 2401 | 912 | 86.4290857 | 32.8293737 | 534.1073 | 0.8927 | 0.1669 |
| 8 | 283 | 10.1871850 | 2684 | 377 | 96.6162707 | 13.5709143 | 271.9208 | 11.0792 | 3.9149 |
| 9 | 79 | 2.8437725 | 2763 | 94 | 99.4600432 | 3.3837293 | 82.0375 | −3.0375 | 3.8450 |
| 10 | 15 | 0.5399568 | 2778 | 15 | 100.0000000 | 0.5399568 | 11.1377 | 3.8623 | 25.7487 |
grafico <- comparativa %>%
transmute(
Exitos,
Realidad = ni,
Modelo = Frecuencia_Esperada
) %>%
pivot_longer(
cols = c(Realidad, Modelo),
names_to = "Distribucion",
values_to = "Frecuencia"
)
ggplot(grafico, aes(factor(Exitos), Frecuencia, fill = Distribucion)) +
geom_col(position = "dodge") +
scale_fill_manual(
values = c("Realidad" = "darkred", "Modelo" = "darkblue"),
breaks = c("Realidad", "Modelo"),
labels = c("Realidad observada", "Modelo binomial")
) +
labs(
title = "Gráfica N.° 2\nComparación entre realidad y modelo",
subtitle = paste("n =", n, "; p =", round(p, 6)),
x = "Número de éxitos",
y = "Frecuencia absoluta",
fill = "Distribución"
) +
theme_classic() +
theme(legend.position = "bottom")
Fo_rel <- comparativa$ni / sum(comparativa$ni)
Fe_rel <- comparativa$Frecuencia_Esperada /
sum(comparativa$Frecuencia_Esperada)
coef_pearson <- cor(Fo_rel, Fe_rel)
Fo_chi <- c(); Fe_chi <- c(); fo_temp <- 0; fe_temp <- 0
for (i in seq_along(Fe)) {
fo_temp <- fo_temp + comparativa$ni[i]
fe_temp <- fe_temp + Fe[i]
if (fe_temp >= 5) {
Fo_chi <- c(Fo_chi, fo_temp)
Fe_chi <- c(Fe_chi, fe_temp)
fo_temp <- 0; fe_temp <- 0
}
}
if (fe_temp > 0) {
ultimo <- length(Fe_chi)
Fo_chi[ultimo] <- Fo_chi[ultimo] + fo_temp
Fe_chi[ultimo] <- Fe_chi[ultimo] + fe_temp
}
Chi2 <- sum((Fo_chi - Fe_chi)^2 / Fe_chi)
gl <- max(length(Fo_chi) - 2, 1)
p_valor <- pchisq(Chi2, gl, lower.tail = FALSE)
decision_pearson <- ifelse(coef_pearson >= 0.70, "APRUEBA", "NO APRUEBA")
decision_chi <- ifelse(p_valor > 0.05, "APRUEBA", "NO APRUEBA")
tabla_tests <- data.frame(
Prueba = c("Correlación de Pearson", "Chi-cuadrado"),
Resultado = c(
paste0("r = ", round(coef_pearson, 4),
" (", round(coef_pearson * 100, 2), " %)"),
paste0("X² = ", round(Chi2, 4),
"; p = ", format.pval(p_valor, digits = 4))
),
Criterio = c("Aprueba si r >= 0.70", "Aprueba si p > 0.05"),
Decision = c(decision_pearson, decision_chi)
)
tabla_tests %>%
gt() %>%
tab_header(
title = md("**Tabla resumen de los tests de aprobación**"),
subtitle = "Evaluación del ajuste al modelo binomial"
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(columns = Decision)
) %>%
tab_source_note(
source_note = md(
"__Pearson evalúa asociación; chi-cuadrado evalúa bondad de ajuste.__"
)
)
| Tabla resumen de los tests de aprobación | |||
| Evaluación del ajuste al modelo binomial | |||
| Prueba | Resultado | Criterio | Decision |
|---|---|---|---|
| Correlación de Pearson | r = 0.9998 (99.98 %) | Aprueba si r >= 0.70 | APRUEBA |
| Chi-cuadrado | X² = 5.6498; p = 0.6864 | Aprueba si p > 0.05 | APRUEBA |
| Pearson evalúa asociación; chi-cuadrado evalúa bondad de ajuste. | |||
x <- round(n * p)
prob_puntual <- dbinom(x, size = n, prob = p)
prob_acumulada <- pbinom(x, size = n, prob = p)
data.frame(
Tipo = c("Puntual", "Acumulada"),
Evento = c(
paste("Exactamente", x, "éxitos"),
paste(x, "éxitos o menos")
),
Probabilidad = c(prob_puntual, prob_acumulada)
) %>%
gt() %>%
fmt_number(columns = Probabilidad, decimals = 6)
| Tipo | Evento | Probabilidad |
|---|---|---|
| Puntual | Exactamente 6 éxitos | 0.247829 |
| Acumulada | 6 éxitos o menos | 0.676313 |
media_binomial <- n * p
desv_binomial <- sqrt(n * p * (1 - p))
z <- c(1, 1.96, 2.576)
limites_inferiores <- pmax(0, media_binomial - z * desv_binomial)
limites_superiores <- pmin(n, media_binomial + z * desv_binomial)
tabla_ic_original <- data.frame(
Nivel = c("68%", "95%", "99%"),
Limite_Inferior = limites_inferiores,
Limite_Superior = limites_superiores
)
tabla_ic_original %>%
gt() %>%
fmt_number(columns = 2:3, decimals = 6) %>%
tab_header(
title = md("**Tabla de intervalos de confianza originales**"),
subtitle = "Límites decimales del número de éxitos"
)
| Tabla de intervalos de confianza originales | ||
| Límites decimales del número de éxitos | ||
| Nivel | Limite_Inferior | Limite_Superior |
|---|---|---|
| 68% | 4.195618 | 7.321301 |
| 95% | 2.695290 | 8.821629 |
| 99% | 1.732579 | 9.784339 |
Debido a que el número de éxitos es una variable discreta, sus intervalos se interpretan mediante valores puntuales. Por ello, los límites decimales se aproximan a los valores puntuales más cercanos.
data.frame(
Nivel = c("68%", "95%", "99%"),
Limite_Inferior = round(limites_inferiores),
Limite_Superior = round(limites_superiores)
) %>%
gt() %>%
fmt_number(columns = 2:3, decimals = 0) %>%
tab_header(
title = md("**Tabla de intervalos de confianza puntuales**"),
subtitle = "Aproximación a valores puntuales"
)
| Tabla de intervalos de confianza puntuales | ||
| Aproximación a valores puntuales | ||
| Nivel | Limite_Inferior | Limite_Superior |
|---|---|---|
| 68% | 4 | 7 |
| 95% | 3 | 9 |
| 99% | 2 | 10 |
El comportamiento del número de muestras clasificadas como
SAND en bloques de 10 observaciones se explica mediante un
modelo binomial con parámetros \(n=10\)
y \(p=0.5758\). Podemos afirmar con un
95 % de confianza que la media aritmética real del número de muestras
SAND por bloque se encuentra entre 5.6992 y 5.8177, con una
desviación estándar teórica de \(\sigma=\sqrt{np(1-p)}=1.5628\)
muestras.