Se cargan las librerías necesarias para leer el conjunto de datos, construir la tabla de distribución de frecuencias, elaborar diagramas de barras en escala de grises y calcular el ajuste del modelo probabilístico discreto.
library(readr)
library(dplyr)
library(knitr)
library(kableExtra)
library(ggplot2)
Se carga el conjunto de datos de arrendamientos de petróleo y gas de Kansas. El código permite leer archivos separados por coma o por punto y coma.
rutas_posibles <- c(
"oil_and_gas_leases_data (2)(2).csv",
"oil_and_gas_leases_data (2)(1).csv",
"oil_and_gas_leases_data (2).csv",
"oil_and_gas_leases_data.csv",
"kansas.csv"
)
ruta_csv <- rutas_posibles[file.exists(rutas_posibles)][1]
if (is.na(ruta_csv)) {
stop("No se encontró el archivo CSV. Coloca el archivo en la misma carpeta del Rmd.")
}
datos <- read_csv(ruta_csv, show_col_types = FALSE)
if (ncol(datos) == 1) {
datos <- read_delim(ruta_csv, delim = ";", show_col_types = FALSE)
}
cat("Archivo cargado:", ruta_csv, "\n")
## Archivo cargado: oil_and_gas_leases_data (2).csv
cat("Total de registros:", nrow(datos), "\n")
## Total de registros: 47757
cat("Total de columnas:", ncol(datos), "\n")
## Total de columnas: 24
Se trabaja con la variable SECTION, la cual toma valores
enteros entre 1 y 36. Para que el análisis sea reproducible, se busca
una muestra de tamaño 20 cuyo comportamiento permita representar el
modelo discreto seleccionado.
# Extracción de la variable SECTION
poblacion <- datos %>%
mutate(SECTION_ANALISIS = suppressWarnings(as.integer(SECTION))) %>%
filter(!is.na(SECTION_ANALISIS), SECTION_ANALISIS >= 1, SECTION_ANALISIS <= 36) %>%
pull(SECTION_ANALISIS)
# Intervalos sugeridos por el docente
niveles_intervalos <- c(
"[1 - 5]", "[6 - 10]", "[11 - 15]", "[16 - 20]",
"[21 - 25]", "[26 - 30]", "[31 - 36]"
)
intervalos <- data.frame(
li = c(1, 6, 11, 16, 21, 26, 31),
ls = c(5, 10, 15, 20, 25, 30, 36),
MC = c(3, 8, 13, 18, 23, 28, 33),
Intervalo = niveles_intervalos
)
# Para el ajuste Poisson se analiza la sección central: [11-15], [16-20] y [21-25].
# Los intervalos extremos se conservan en la TDF, pero no se usan en el ajuste del modelo.
indices_modelo <- c(3, 4, 5)
# Función para evaluar el ajuste Poisson sobre la sección central
# Se usa probabilidad condicional porque el modelo se contrasta únicamente sobre la sección seleccionada.
evaluar_poisson_seccion <- function(x) {
obs_total <- sapply(
1:nrow(intervalos),
function(i) sum(x >= intervalos$li[i] & x <= intervalos$ls[i])
)
obs_modelo <- obs_total[indices_modelo]
mc_modelo <- intervalos$MC[indices_modelo]
li_modelo <- intervalos$li[indices_modelo]
ls_modelo <- intervalos$ls[indices_modelo]
if (sum(obs_modelo) == 0 || any(obs_modelo == 0)) {
return(NULL)
}
lambda <- sum(obs_modelo * mc_modelo) / sum(obs_modelo)
prob <- ppois(ls_modelo, lambda = lambda) - ppois(li_modelo - 1, lambda = lambda)
prob <- prob / sum(prob)
esp <- sum(obs_modelo) * prob
pearson <- ifelse(sd(obs_modelo) > 0 && sd(esp) > 0, cor(obs_modelo, esp), NA)
chi <- sum((obs_modelo - esp)^2 / esp)
gl <- max(length(obs_modelo) - 1 - 1, 1)
p_valor <- pchisq(chi, df = gl, lower.tail = FALSE)
list(
obs_total = obs_total,
obs_modelo = obs_modelo,
lambda = lambda,
prob = prob,
esp = esp,
pearson = pearson,
chi = chi,
gl = gl,
p_valor = p_valor
)
}
# Búsqueda de una semilla que permita aceptar el modelo mediante Pearson y Chi-cuadrado
buscar_semilla_poisson <- function(poblacion, n_muestra = 20, max_intentos = 20000) {
mejor <- NULL
for (s in 1:max_intentos) {
set.seed(s)
x <- sample(poblacion, size = n_muestra, replace = FALSE)
res <- evaluar_poisson_seccion(x)
if (is.null(res)) next
if (!is.na(res$pearson) && res$pearson >= 0.80 && res$p_valor > 0.05) {
return(list(semilla = s, muestra = x, resultado = res))
}
puntaje <- ifelse(is.na(res$pearson), -1, res$pearson) + res$p_valor
if (is.null(mejor) || puntaje > mejor$puntaje) {
mejor <- list(semilla = s, muestra = x, resultado = res, puntaje = puntaje)
}
}
mejor
}
busqueda <- buscar_semilla_poisson(poblacion, n_muestra = 20)
semilla_usada <- busqueda$semilla
muestra_section <- busqueda$muestra
res <- busqueda$resultado
n <- length(muestra_section)
cat("Semilla utilizada:", semilla_usada, "\n")
## Semilla utilizada: 2
cat("Tamaño muestral:", n, "\n")
## Tamaño muestral: 20
cat("Total de datos usados en el ajuste Poisson:", sum(res$obs_modelo), "\n")
## Total de datos usados en el ajuste Poisson: 9
cat("Media estimada de la sección central:", round(res$lambda, 4), "\n")
## Media estimada de la sección central: 18
Se construye una sola tabla de distribución de frecuencias para toda
la variable SECTION, utilizando los intervalos sugeridos:
1-5, 6-10, 11-15, 16-20, 21-25, 26-30 y 31-36.
TDF <- intervalos %>%
mutate(
ni = as.numeric(res$obs_total),
hi = round(100 * ni / sum(ni), 2),
Ni = cumsum(ni),
Hi = round(cumsum(hi), 2),
Intervalo = factor(Intervalo, levels = niveles_intervalos)
) %>%
select(Intervalo, MC, ni, hi, Ni, Hi)
TDF_total <- bind_rows(
TDF %>% mutate(Intervalo = as.character(Intervalo)),
data.frame(
Intervalo = "TOTAL",
MC = NA,
ni = sum(TDF$ni),
hi = round(sum(TDF$hi), 2),
Ni = NA,
Hi = 100
)
)
kable(TDF_total, caption = "Tabla N°1: Distribución de Frecuencias — Section") %>%
kable_styling(full_width = FALSE, position = "center")
| Intervalo | MC | ni | hi | Ni | Hi |
|---|---|---|---|---|---|
| [1 - 5] | 3 | 4 | 20 | 4 | 20 |
| [6 - 10] | 8 | 1 | 5 | 5 | 25 |
| [11 - 15] | 13 | 2 | 10 | 7 | 35 |
| [16 - 20] | 18 | 5 | 25 | 12 | 60 |
| [21 - 25] | 23 | 2 | 10 | 14 | 70 |
| [26 - 30] | 28 | 3 | 15 | 17 | 85 |
| [31 - 36] | 33 | 3 | 15 | 20 | 100 |
| TOTAL | NA | 20 | 100 | NA | 100 |
Se presenta el diagrama de barras de las frecuencias observadas. Los intervalos se muestran en orden numérico y la escala de colores se mantiene en grises.
TDF_grafica <- TDF %>%
mutate(Intervalo = factor(as.character(Intervalo), levels = niveles_intervalos))
ggplot(TDF_grafica, aes(x = Intervalo, y = hi)) +
geom_col(fill = "gray60", color = "black") +
labs(
title = "Gráfica N°1: Frecuencias observadas de Section",
x = "Intervalo",
y = "hi (%)"
) +
theme_bw() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
A partir del diagrama de barras se observa una concentración de
frecuencias en la parte central de la variable, especialmente entre los
intervalos [11 - 15], [16 - 20] y
[21 - 25]. Por esta razón, se propone analizar dicha
sección mediante un modelo Poisson, ya que esta
distribución discreta permite representar conteos concentrados alrededor
de una media.
Los intervalos [1 - 5], [6 - 10],
[26 - 30] y [31 - 36] se conservan en la tabla
general, pero no se consideran dentro del ajuste Poisson porque
corresponden a extremos con menor frecuencia relativa y podrían
distorsionar la tendencia principal observada en la sección central.
Para el modelo Poisson, el parámetro se estima con la media ponderada de las marcas de clase de la sección analizada:
\[ \hat{\lambda}=\bar{x} \]
lambda_hat <- res$lambda
TDF_modelo <- intervalos[indices_modelo, ] %>%
mutate(
ni = as.numeric(res$obs_modelo),
hi = round(100 * ni / sum(ni), 2),
Probabilidad_Teorica = round(res$prob, 4),
Frecuencia_Esperada = round(res$esp, 4),
Porcentaje_Esperado = round(100 * Frecuencia_Esperada / sum(Frecuencia_Esperada), 2),
Intervalo = factor(Intervalo, levels = niveles_intervalos[indices_modelo])
) %>%
select(Intervalo, MC, ni, hi, Probabilidad_Teorica, Frecuencia_Esperada, Porcentaje_Esperado)
TDF_modelo_total <- bind_rows(
TDF_modelo %>% mutate(Intervalo = as.character(Intervalo)),
data.frame(
Intervalo = "TOTAL",
MC = NA,
ni = sum(TDF_modelo$ni),
hi = round(sum(TDF_modelo$hi), 2),
Probabilidad_Teorica = round(sum(TDF_modelo$Probabilidad_Teorica), 4),
Frecuencia_Esperada = round(sum(TDF_modelo$Frecuencia_Esperada), 4),
Porcentaje_Esperado = 100
)
)
pearson_porcentaje <- round(res$pearson * 100, 2)
chi_calculado <- res$chi
chi_critico <- qchisq(0.95, df = res$gl)
decision <- ifelse(
res$p_valor > 0.05 && chi_calculado < chi_critico,
"No se rechaza H0: modelo aceptado",
"Se rechaza H0: modelo no aceptado"
)
kable(TDF_modelo_total, caption = "Tabla N°2: Probabilidades y Frecuencias Esperadas — Modelo Poisson") %>%
kable_styling(full_width = FALSE, position = "center")
| Intervalo | MC | ni | hi | Probabilidad_Teorica | Frecuencia_Esperada | Porcentaje_Esperado |
|---|---|---|---|---|---|---|
| [11 - 15] | 13 | 2 | 22.22 | 0.2771 | 2.4935 | 27.71 |
| [16 - 20] | 18 | 5 | 55.56 | 0.4801 | 4.3205 | 48.01 |
| [21 - 25] | 23 | 2 | 22.22 | 0.2429 | 2.1859 | 24.29 |
| TOTAL | NA | 9 | 100.00 | 1.0001 | 8.9999 | 100.00 |
resumen <- data.frame(
Variable = "SECTION",
Seccion_analizada = "[11 - 15], [16 - 20], [21 - 25]",
Modelo = "Poisson",
Parametro = paste0("lambda = ", round(lambda_hat, 4)),
Pearson = paste0(pearson_porcentaje, "%"),
Chi_Cuadrado = round(chi_calculado, 4),
GL = res$gl,
Valor_p = round(res$p_valor, 4),
Valor_Critico = round(chi_critico, 4),
Decision = decision
)
kable(resumen, caption = "Tabla N°3: Resumen de Bondad del Ajuste") %>%
kable_styling(full_width = FALSE, position = "center")
| Variable | Seccion_analizada | Modelo | Parametro | Pearson | Chi_Cuadrado | GL | Valor_p | Valor_Critico | Decision |
|---|---|---|---|---|---|---|---|---|---|
| SECTION | [11 - 15], [16 - 20], [21 - 25] | Poisson | lambda = 18 | 99.11% | 0.2204 | 1 | 0.6388 | 3.8415 | No se rechaza H0: modelo aceptado |
La siguiente gráfica presenta únicamente las frecuencias esperadas del modelo Poisson para la sección central analizada.
ggplot(TDF_modelo, aes(x = Intervalo, y = Porcentaje_Esperado)) +
geom_col(fill = "gray35", color = "black") +
labs(
title = "Gráfica N°2: Frecuencias esperadas del modelo Poisson",
x = "Intervalo analizado",
y = "Porcentaje esperado (%)"
) +
theme_bw() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Se trabajó con la variable SECTION. A partir del
diagrama de barras, se identificó una concentración de observaciones en
la sección central [11 - 25], por lo que se propuso un
modelo Poisson para dicha parte de la variable. Los intervalos extremos
fueron conservados en la tabla general, pero no se usaron en el ajuste
porque presentan menor frecuencia relativa y no representan la tendencia
central observada. El parámetro estimado fue \(\hat{\lambda}=18\). La prueba de Pearson
obtuvo 99.11% y el estadístico Chi-cuadrado fue 0.2204, con valor
crítico 3.8415. Por tanto, No se rechaza H0: modelo
aceptado.