0.- Carga de Librerías

library(readxl)
library(dplyr)
library(tidyr)
library(gt)
library(ggplot2)
library(scales)
library(forcats)

1.- Carga de Datos

datos <- read_excel("dataset_mundial_petro.xlsx")
cat("Número de registros:", nrow(datos), "\n")
## Número de registros: 8334
cat("Número de variables:", ncol(datos), "\n")
## Número de variables: 23

2.- Selección de Variable Aleatoria

La variable Status indica el estado operativo de cada yacimiento. Originalmente tiene 9 categorías puntuales; se excluyen los N/S y se consolidan en 5 condiciones generales, siguiendo la secuencia lógica del ciclo de vida de un yacimiento (de más activo a más inactivo/reconvertido).

n_total <- nrow(datos)
datos_status <- datos %>% filter(Status != "N/S")
n <- nrow(datos_status)

cat("Registros excluidos por N/S:", n_total - n, "\n")
## Registros excluidos por N/S: 266
cat("Número de registros válidos:", n, "\n")
## Número de registros válidos: 8068
datos_status <- datos_status %>%
  mutate(Condición = case_when(
    Status %in% c("operating", "in development") ~ "Activos y en Desarrollo",
    Status %in% c("discovered", "exploration")    ~ "En etapa temprana",
    Status %in% c("shut in", "cancelled")         ~ "Suspendidos o Cancelados",
    Status %in% c("decommissioned", "abandoned")  ~ "Clausura Definitiva",
    Status == "UGS"                               ~ "Reconvertido a Almacenamiento",
    TRUE ~ NA_character_
  ))

# Orden lógico (no por frecuencia) para presentación: de más activo a más inactivo
orden_labels <- c(
  "Activos y en Desarrollo", "En etapa temprana", "Suspendidos o Cancelados",
  "Clausura Definitiva", "Reconvertido a Almacenamiento"
)

datos_status$Condición <- factor(datos_status$Condición,
                                  levels = orden_labels, ordered = TRUE)

conteo <- as.data.frame(table(datos_status$Condición)) %>%
  rename(Estado = Var1, ni = Freq) %>%
  mutate(
    hi     = round(ni / n, 4),
    hi_pct = round(ni / n * 100, 2)
  )

k <- nrow(conteo)
cat("Total de categorías:", k, "\n")
## Total de categorías: 5
cat("Categoría más frecuente:", conteo$Estado[which.max(conteo$ni)],
    "con", max(conteo$ni), "registros\n")
## Categoría más frecuente: 1 con 6584 registros
cat("Categoría menos frecuente:", conteo$Estado[which.min(conteo$ni)],
    "con", min(conteo$ni), "registro(s)\n")
## Categoría menos frecuente: 5 con 11 registro(s)

3.- Tabla Distribución de Frecuencia

fila_total <- tibble(
  Estado  = "TOTAL",
  ni      = sum(conteo$ni),
  hi      = sum(conteo$hi),
  hi_pct  = sum(conteo$hi_pct)
)

tdf_final <- bind_rows(conteo %>% mutate(Estado = as.character(Estado)), fila_total)

tdf_final %>%
  gt() %>%
  tab_header(
    title    = md("**Tabla N° 1**"),
    subtitle = md("Distribución de yacimientos según condición operativa")
  ) %>%
  cols_label(
    Estado  = "Condición Operativa",
    ni      = "Frecuencia (ni)",
    hi      = "Proporción (hi)",
    hi_pct  = "Porcentaje (hi%)"
  ) %>%
  fmt_number(columns = hi,     decimals = 4) %>%
  fmt_number(columns = hi_pct, decimals = 2) %>%
  tab_source_note(source_note = "Autor: Grupo 5") %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_options(
    table.border.top.color            = "black",
    table.border.bottom.color         = "black",
    table.border.top.style            = "solid",
    table.border.bottom.style         = "solid",
    column_labels.font.weight         = "bold",
    column_labels.border.top.color    = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    heading.border.bottom.color       = "black",
    heading.border.bottom.width       = px(2),
    table_body.hlines.color           = "grey",
    table_body.border.bottom.color    = "black"
  )
Tabla N° 1
Distribución de yacimientos según condición operativa
Condición Operativa Frecuencia (ni) Proporción (hi) Porcentaje (hi%)
Activos y en Desarrollo 6584 0.8161 81.61
En etapa temprana 397 0.0492 4.92
Suspendidos o Cancelados 992 0.1230 12.30
Clausura Definitiva 84 0.0104 1.04
Reconvertido a Almacenamiento 11 0.0014 0.14
TOTAL 8068 1.0001 100.01
Autor: Grupo 5

4.- Gráfica Distribución de Frecuencia

4.1 Diagrama de Barras — Frecuencia Absoluta

colores <- colorRampPalette(c("#2E86C1", "#AED6F1"))(k)

ggplot(conteo, aes(x = Estado, y = ni, fill = Estado)) +
  geom_col(width = 0.6, color = "white") +
  geom_text(aes(label = ni), vjust = -0.4, size = 3.2, fontface = "bold") +
  scale_x_discrete(limits = orden_labels) +
  scale_fill_manual(values = colores) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title   = "Gráfica N°1: Frecuencia Absoluta por Condición Operativa",
    x       = "Condición Operativa",
    y       = "Frecuencia (ni)",
    caption = paste0("n = ", format(n, big.mark = ","), " | Fuente: GOGET")
  ) +
  theme_minimal() +
  theme(legend.position = "none",
        plot.title = element_text(face = "bold"),
        axis.title = element_text(face = "bold"),
        axis.text.x = element_text(angle = 45, hjust = 1))

4.2 Diagrama de Barras — Frecuencia Relativa (Pi)

ggplot(conteo, aes(x = Estado, y = hi_pct, fill = Estado)) +
  geom_col(width = 0.6, color = "white") +
  geom_text(aes(label = paste0(hi_pct, "%")), vjust = -0.4, size = 3.2, fontface = "bold") +
  scale_x_discrete(limits = orden_labels) +
  scale_fill_manual(values = colores) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title   = "Gráfica N°2: Frecuencia Relativa (Pi) por Condición Operativa",
    x       = "Condición Operativa",
    y       = "Frecuencia Relativa (%)",
    caption = paste0("n = ", format(n, big.mark = ","), " | Fuente: GOGET")
  ) +
  theme_minimal() +
  theme(legend.position = "none",
        plot.title = element_text(face = "bold"),
        axis.title = element_text(face = "bold"),
        axis.text.x = element_text(angle = 45, hjust = 1))


5.- Tratamiento de Datos

Partiendo de la Tabla de Distribución de Frecuencias (TDF) ya construida en la sección anterior — sin reordenar las categorías —, se asigna una posición (ID) a cada condición operativa, insumo necesario para el ajuste del modelo Geométrico.

conteo_modelo <- conteo %>%
  mutate(Estado = as.character(Estado))
conteo_modelo$ID <- 1:nrow(conteo_modelo)

conteo_modelo %>%
  select(ID, Estado, ni, hi) %>%
  gt() %>%
  tab_header(
    title    = md("**Tabla N°3**"),
    subtitle = md("TDF con posición (ID) asignada en su orden original, para el ajuste del modelo Geométrico")
  ) %>%
  cols_label(
    ID     = "Posición (ID)",
    Estado = "Condición Operativa",
    ni     = "Frecuencia (ni)",
    hi     = "Proporción (hi)"
  ) %>%
  fmt_number(columns = hi, decimals = 4) %>%
  tab_source_note(source_note = "Autor: Grupo 5") %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_options(
    table.border.top.color            = "black",
    table.border.bottom.color         = "black",
    column_labels.border.top.color    = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    table_body.border.bottom.color    = "black"
  )
Tabla N°3
TDF con posición (ID) asignada en su orden original, para el ajuste del modelo Geométrico
Posición (ID) Condición Operativa Frecuencia (ni) Proporción (hi)
1 Activos y en Desarrollo 6584 0.8161
2 En etapa temprana 397 0.0492
3 Suspendidos o Cancelados 992 0.1230
4 Clausura Definitiva 84 0.0104
5 Reconvertido a Almacenamiento 11 0.0014
Autor: Grupo 5

6.- Conjetura

Se trabaja por momentos para poder apreciar cómo se ajusta el modelo Geométrico sobre los datos ya tratados en la sección anterior. Se conjetura este modelo porque la frecuencia relativa decrece progresivamente a medida que se avanza por las condiciones operativas (de “Activos y en Desarrollo” hacia “Reconvertido a Almacenamiento”), patrón característico de una distribución Geométrica sobre las posiciones (ID) asignadas.


7.- Parámetros

Para una variable Geométrica, la media teórica es \(E(ID) = 1/p\). Se despeja \(p\) usando la media observada de las posiciones ponderada por \(hi\):

media_observada <- sum(conteo_modelo$ID * conteo_modelo$hi)
p_estimado <- 1 / media_observada

cat("Media observada de posiciones (ID ponderado por hi):", round(media_observada, 4), "\n")
## Media observada de posiciones (ID ponderado por hi): 1.3321
cat("Parámetro estimado p = 1 / media observada =", round(p_estimado, 4), "\n")
## Parámetro estimado p = 1 / media observada = 0.7507

8.- Sobreposición de la Realidad con el Modelo

prob_geom <- p_estimado * (1 - p_estimado)^(conteo_modelo$ID - 1)
prob_geom <- prob_geom / sum(prob_geom)

conteo_modelo$hi_modelo     <- round(prob_geom, 4)
conteo_modelo$hi_modelo_pct <- round(prob_geom * 100, 2)

df_comparativo <- conteo_modelo %>%
  select(Estado, hi_pct, hi_modelo_pct) %>%
  pivot_longer(cols = c(hi_pct, hi_modelo_pct),
               names_to = "Origen", values_to = "Valor") %>%
  mutate(Origen = ifelse(Origen == "hi_pct", "Realidad", "Modelo"))

df_comparativo$Estado <- factor(df_comparativo$Estado, levels = conteo_modelo$Estado)

8.1 Gráfica comparativa 1

grupo1 <- c("Activos y en Desarrollo", "En etapa temprana")

df_grupo1 <- df_comparativo %>% filter(Estado %in% grupo1)

ggplot(df_grupo1, aes(x = Estado, y = Valor, fill = Origen)) +
  geom_bar(stat = "identity", position = "dodge", color = "white") +
  geom_text(aes(label = paste0(round(Valor, 1), "%")),
            position = position_dodge(width = 0.9), vjust = -0.4, size = 3.2) +
  scale_fill_manual(values = c("Modelo" = "skyblue", "Realidad" = "#2E4053")) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  labs(
    title    = "Gráfica N°3: Modelo Geométrico comparado con la Realidad — Activos y en Desarrollo / Etapa Temprana",
    subtitle = paste0("p estimado = ", round(p_estimado, 4)),
    x        = "Condición Operativa",
    y        = "Probabilidad (%)",
    fill     = "Origen"
  )

8.2 Gráfica comparativa 2

grupo2 <- c("Suspendidos o Cancelados", "Clausura Definitiva", "Reconvertido a Almacenamiento")

df_grupo2 <- df_comparativo %>% filter(Estado %in% grupo2)

ggplot(df_grupo2, aes(x = Estado, y = Valor, fill = Origen)) +
  geom_bar(stat = "identity", position = "dodge", color = "white") +
  geom_text(aes(label = paste0(round(Valor, 1), "%")),
            position = position_dodge(width = 0.9), vjust = -0.4, size = 3.2) +
  scale_fill_manual(values = c("Modelo" = "skyblue", "Realidad" = "#2E4053")) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  labs(
    title    = "Gráfica N°4: Modelo Geométrico comparado con la Realidad — Suspendidos/Cancelados, Clausura y Reconversión",
    subtitle = paste0("p estimado = ", round(p_estimado, 4)),
    x        = "Condición Operativa",
    y        = "Probabilidad (%)",
    fill     = "Origen"
  )


9.- Test de Bondad

9.1 Test de Pearson

Fo <- conteo_modelo$hi
Fe <- conteo_modelo$hi_modelo

r_pearson <- cor(Fo, Fe) * 100
cat("Correlación de Pearson (%):", round(r_pearson, 4), "\n")
## Correlación de Pearson (%): 97.1294
plot(Fo, Fe,
     main = "Gráfica N°5: Correlación Modelo Observado y Esperado",
     xlab = "Frecuencia Observada (hi)",
     ylab = "Frecuencia Esperada (hi modelo)",
     pch  = 19,
     col  = "#2E4053")
abline(lm(Fe ~ 0 + Fo), col = "red", lwd = 2)
legend("topleft",
       legend = paste0("r = ", round(r_pearson, 2), "%"),
       bty    = "n")

9.2 Test Chi-Cuadrado

chi2_calc <- sum(((Fo - Fe)^2) / Fe)
gl        <- length(Fo) - 2
chi2_crit <- qchisq(0.95, gl)

cat("Chi-Cuadrado:", round(chi2_calc, 4), "\n")
## Chi-Cuadrado: 0.233
cat("Valor Crítico:", round(chi2_crit, 4), "\n")
## Valor Crítico: 7.8147
cat("¿El modelo geométrico es aceptado?:", chi2_calc < chi2_crit, "\n")
## ¿El modelo geométrico es aceptado?: TRUE

Tabla resumen del test

tabla_test <- data.frame(
  Variable          = "Condición Operativa",
  `Test Pearson (%)`= round(r_pearson, 2),
  `Chi Cuadrado`    = round(chi2_calc, 2),
  `Umbral de Aceptación` = round(chi2_crit, 2),
  Resultado         = ifelse(chi2_calc < chi2_crit, "Modelo Aceptado", "Modelo Rechazado"),
  check.names = FALSE
)

tabla_test %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N°2: Resumen del Test de Bondad al Modelo de Probabilidad**")
  ) %>%
  tab_source_note(source_note = "Autor: Grupo 5") %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_options(
    table.border.top.color            = "black",
    table.border.bottom.color         = "black",
    column_labels.border.top.color    = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    table_body.border.bottom.color    = "black"
  )
Tabla N°2: Resumen del Test de Bondad al Modelo de Probabilidad
Variable Test Pearson (%) Chi Cuadrado Umbral de Aceptación Resultado
Condición Operativa 97.13 0.23 7.81 Modelo Aceptado
Autor: Grupo 5

10.- Cálculo de Probabilidades

prob_activos <- conteo$hi_pct[conteo$Estado == "Activos y en Desarrollo"]
cat("Probabilidad de estar en condición 'Activos y en Desarrollo':",
    prob_activos, "%\n")
## Probabilidad de estar en condición 'Activos y en Desarrollo': 81.61 %
pozos_clausura <- sum(conteo$ni[conteo$Estado %in%
                     c("Clausura Definitiva", "Suspendidos o Cancelados")])
cat("Pozos en clausura definitiva o suspendidos/cancelados:", pozos_clausura, "\n")
## Pozos en clausura definitiva o suspendidos/cancelados: 1076

11.- Intervalo de Confianza

Se calcula el intervalo de confianza al 95% para la proporción de la categoría más frecuente, usando la aproximación normal para proporciones.

idx_max <- which.max(conteo$hi)
p_hat_ic <- conteo$hi[idx_max]
categoria_frecuente <- as.character(conteo$Estado[idx_max])

z      <- qnorm(0.975)
margen <- z * sqrt(p_hat_ic * (1 - p_hat_ic) / n)

ic_inf <- p_hat_ic - margen
ic_sup <- p_hat_ic + margen

cat("Categoría más frecuente:", categoria_frecuente, "\n")
## Categoría más frecuente: Activos y en Desarrollo
cat("Intervalo de confianza al 95%: (",
    round(ic_inf * 100, 2), "% ,", round(ic_sup * 100, 2), "% )\n")
## Intervalo de confianza al 95%: ( 80.76 % , 82.46 % )

12.- Conclusión

El comportamiento de la variable Condición Operativa (Status) se explica con un modelo Geométrico de parámetro p = 0.7507.