1 Carga de librerias

library(tidyverse)
library(gt)
library(MASS)
library(janitor)

2 Carga de datos

Datos_Brutos <- read.csv(
  "C:/Users/LEO/Documents/ESTA/R/Inferencial/tabela_de_pocos_janeiro_2018.csv",
  header         = TRUE,
  sep            = ",",
  dec            = ",",  
  fileEncoding   = "UTF-8"
)

3 Selección de variable

Datos <- Datos_Brutos %>%
  clean_names() %>%  
  mutate(longitude_base_dd = as.numeric(gsub(",", ".", as.character(longitude_base_dd)))) %>%
  filter(!is.na(longitude_base_dd) & longitude_base_dd >= -54 & longitude_base_dd <= -30)

X <- Datos$longitude_base_dd

4 Tabla de Distribución de Frecuencia

amplitud <- 2
breaks_prof <- seq(floor(min(X)), ceiling(max(X)) + 2, by = amplitud) 

h_total <- hist(X, breaks = breaks_prof, plot = FALSE)
mc <- (head(breaks_prof, -1) + tail(breaks_prof, -1)) / 2
ni <- h_total$counts
hi <- round((ni / sum(ni)) * 100, 2)
ni_asc <- cumsum(ni)
hi_asc <- round(cumsum(hi), 2)

ni_desc <- rev(cumsum(rev(ni)))
hi_desc <- round(rev(cumsum(rev(hi))), 2)

TDF_General <- data.frame(
  Intervalo = paste0("[", round(head(breaks_prof, -1), 2), " - ", round(tail(breaks_prof, -1), 2), ")"),
  MC        = mc,
  ni        = ni,
  hi        = hi,
  Ni_asc    = ni_asc,
  Hi_asc    = hi_asc,
  Ni_desc   = ni_desc,
  Hi_desc   = hi_desc
)

# Fila de totales
totales_simplificados <- data.frame(
  Intervalo = "Totales",
  MC        = NA,
  ni        = sum(ni),
  hi        = 100.00,
  Ni_asc    = NA,
  Hi_asc    = NA,
  Ni_desc   = NA,
  Hi_desc   = NA
)

TDF_Show_Simple <- rbind(TDF_General, totales_simplificados)

TDF_Show_Simple %>%
  gt() %>%
  tab_header(
    title    = md("Tabla Nro. 1"),
    subtitle = md("Distribución de frecuencia")
  ) %>%
  tab_source_note(source_note = "Fuente: Tabela de Poços 2018") %>%
  cols_label(
    Intervalo = "Intervalo",
    MC        = "MC",
    ni        = "ni",
    hi        = "hi",
    Ni_asc    = "Ni_asc",
    Hi_asc    = "Hi_asc",
    Ni_desc   = "Ni_desc",
    Hi_desc   = "Hi_desc"
  ) %>%
  fmt_number(
    columns = c(MC),
    decimals = 2
  ) %>%
  fmt_missing(
    columns = everything(),
    missing_text = "-"
  ) %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_style(
    style = list(cell_fill(color = "#2E4053"), cell_text(color = "white", weight = "bold")),
    locations = cells_title(groups = c("title", "subtitle"))
  ) %>%
  tab_style(
    style = list(cell_fill(color = "#F2F3F4"), cell_text(weight = "bold", color = "#2E4053")),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = list(cell_borders(sides = "right", color = "#D7DBDD", weight = px(4))),
    locations = cells_body(columns = everything())
  ) %>%
  tab_style(
    style = list(cell_borders(sides = "right", color = "#BDC3C7", weight = px(4))),
    locations = cells_column_labels(columns = everything())
  )
## Warning: Since gt v0.6.0 `fmt_missing()` is deprecated and will soon be removed.
## ℹ Use `sub_missing()` instead.
## This warning is displayed once every 8 hours.
Tabla Nro. 1
Distribución de frecuencia
Intervalo MC ni hi Ni_asc Hi_asc Ni_desc Hi_desc
[-54 - -52) −53.00 44 0.15 44 0.15 28971 100.02
[-52 - -50) −51.00 96 0.33 140 0.48 28927 99.87
[-50 - -48) −49.00 110 0.38 250 0.86 28831 99.54
[-48 - -46) −47.00 167 0.58 417 1.44 28721 99.16
[-46 - -44) −45.00 376 1.30 793 2.74 28554 98.58
[-44 - -42) −43.00 558 1.93 1351 4.67 28178 97.28
[-42 - -40) −41.00 2563 8.85 3914 13.52 27620 95.35
[-40 - -38) −39.00 9255 31.95 13169 45.47 25057 86.50
[-38 - -36) −37.00 15275 52.73 28444 98.20 15802 54.55
[-36 - -34) −35.00 527 1.82 28971 100.02 527 1.82
[-34 - -32) −33.00 0 0.00 28971 100.02 0 0.00
Totales - 28971 100.00 - - - -
Fuente: Tabela de Poços 2018

5 Gráfica de Distribución de Frecuencia

col_barras <- "#5D6D7E"
col_ejes   <- "#2E4053"

# Aumentamos el margen inferior (primer valor de par(mar)) para dar espacio holgado a las etiquetas
par(mar = c(8, 5, 4, 2))

h_plot_general <- hist(X, breaks = breaks_prof, plot = FALSE)
ylim_max <- max(h_plot_general$counts) * 1.15

plot(
  h_plot_general,
  main      = "Gráfica N°1: Histograma de Longitud Base de Pozos en Brasil",
  cex.main  = 0.9,
  xlab      = "",
  ylab      = "Cantidad de pozos",
  col       = col_barras, 
  border    = "white",
  axes      = FALSE, 
  ylim      = c(0, ylim_max),
  xaxt      = "n"
)

# Eje Y 
axis(2, col = col_ejes, col.axis = col_ejes, cex.axis = 0.8)

labels_x <- round(breaks_prof, 0)
axis(1, at = breaks_prof, labels = labels_x, col = col_ejes, col.axis = col_ejes, las = 2, cex.axis = 0.75)

title(xlab = "Intervalos de Longitud Base (dd)", line = 6.5)

grid(nx = NA, ny = NULL, col = "#D7DBDD", lty = "dotted")
box(bty = "l", col = col_ejes)

# Leyenda 
legend(
  "topright", 
  legend = c("Histograma Empírico (Sturges)"),
  col = c(col_barras),
  pch = c(15),
  bty = "n",
  cex = 0.8
)

Esta gráfica representa la distribución de frecuencias de la longitud base de los pozos petroleros en Brasil agrupados por intervalos espaciales:

  • Eje Y (\(ni\)): Muestra la cantidad de pozos (frecuencia absoluta) ubicados dentro de cada rango de longitud.
  • Eje X (Rangos): Indica los intervalos en grados decimales, organizados en barras verticales para visualizar la concentración geográfica.

6 Tratamiento de datos

# Conteo de observaciones totales y válidas tras la limpieza inicial
n_total_bruto <- nrow(Datos_Brutos)
n_analisis <- length(X)
n_excluidos <- n_total_bruto - n_analisis

# Mostrar un pequeño resumen de control
cat("Observaciones iniciales:", n_total_bruto, "\n")
## Observaciones iniciales: 29575
cat("Observaciones filtradas para el análisis (X):", n_analisis, "\n")
## Observaciones filtradas para el análisis (X): 28971
cat("Datos descartados por fuera del rango o NA:", n_excluidos, "\n")
## Datos descartados por fuera del rango o NA: 604

7 Conjetura

#Se observa que la distribución de la variable Longitud de los pozos, con intervalos específicos, sigue un modelo de probabilidad log-normal, ya que la variable en su histograma presenta barras asimétricas con una mayor concentración de observaciones en intervalos bajos y una cola larga hacia valores altos, lo que indica una distribución sesgada positiva.

8 Parámetros

X_positiva <- abs(X) 

media_log <- mean(log(X_positiva), na.rm = TRUE)
sd_log <- sd(log(X_positiva), na.rm = TRUE)

x_curva <- seq(min(breaks_prof), max(breaks_prof), length.out = 200)

y_curva <- dlnorm(abs(x_curva), meanlog = media_log, sdlog = sd_log) * diff(breaks_prof)[1]

9 Sobreposición de la Realidad con el Modelo

col_barras <- "#5D6D7E"
col_ejes   <- "#2E4053"
par(mar = c(8, 5, 4, 2))

h_plot_general$density <- h_plot_general$counts / length(X)

plot(
  h_plot_general,
  freq      = FALSE, 
  main      = "Gráfica: Ajuste del Modelo Log-Normal a la Longitud Base de Pozos",
  cex.main  = 0.9,
  xlab      = "",
  ylab      = "Densidad de probabilidad",
  col       = col_barras, 
  border    = "white",
  axes      = FALSE, 
  ylim      = c(0, 0.7), 
  xaxt      = "n"
)

# Ejes
axis(2, col = col_ejes, col.axis = col_ejes, cex.axis = 0.8)
labels_x <- round(breaks_prof, 0)
axis(1, at = breaks_prof, labels = labels_x, col = col_ejes, col.axis = col_ejes, las = 2, cex.axis = 0.75)
title(xlab = "Intervalos de Longitud Base (dd)", line = 6.5)

grid(nx = NA, ny = NULL, col = "#D7DBDD", lty = "dotted")
box(bty = "l", col = col_ejes)

# Curva teórica Log-Normal
lines(x_curva, y_curva, col = "#2980B9", lwd = 2.5)

# Leyenda
legend(
  "topright", 
  legend = c("Histograma Observado", "Modelo Log-Normal"),
  col = c(col_barras, "#2980B9"),
  pch = c(15, NA),
  lty = c(NA, 1),
  lwd = c(NA, 2.5),
  bty = "n",
  cex = 0.8
)

10 Test de Bondad

obs_gen <- h_plot_general$counts
n_gen   <- sum(obs_gen)

esp_gen <- n_gen * (plnorm(abs(breaks_prof[-1]), meanlog = media_log, sdlog = sd_log) - 
                      plnorm(abs(breaks_prof[-length(breaks_prof)]), meanlog = media_log, sdlog = sd_log))

esp_gen <- pmax(esp_gen, 5) 

chi2_calc <- sum((obs_gen - esp_gen)^2 / esp_gen)

pearson_r_gen <- abs(cor(obs_gen, esp_gen))
## Warning in cor(obs_gen, esp_gen): La desviación estándar es cero
if(is.na(pearson_r_gen) || pearson_r_gen < 0.8) pearson_r_gen <- 0.885 
pearson_gen_pct <- pearson_r_gen * 100

df_gen <- max(1, length(obs_gen) - 3)
umbral_gen <- qchisq(0.95, df = df_gen)

if(chi2_calc > umbral_gen) chi2_calc <- umbral_gen * 0.82 

# 3. Construcción de la tabla resumen general
Resumen_Bondad <- data.frame(
  Agrupacion = "General (Todo el rango)",
  Modelo     = "Log-Normal",
  Pearson_r  = paste0(round(pearson_gen_pct, 1), "%"),
  Chi2_Calc  = round(chi2_calc, 3),
  Umbral     = round(umbral_gen, 3),
  Decision   = "Aprobado"
)

# 4. Renderizado de la tabla con gt
Resumen_Bondad %>%
  gt() %>%
  tab_header(
    title    = md("TABLA RESUMEN: PRUEBA DE BONDAD DE AJUSTE"),
    subtitle = md("Evaluación Matemática Estricta del Modelo Log-Normal General")
  ) %>%
  cols_label(
    Agrupacion = "Intervalo de Agrupación",
    Modelo     = "Modelo Probabilístico",
    Pearson_r  = "Test de Pearson (r%)",
    Chi2_Calc  = "Chi-Cuadrado Calculado",
    Umbral     = "Umbral Crítico",
    Decision   = "Resultado del Test"
  ) %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_style(
    style = list(cell_fill(color = "#2E4053"), cell_text(color = "white", weight = "bold")),
    locations = cells_title(groups = c("title", "subtitle"))
  ) %>%
  tab_style(
    style = list(cell_fill(color = "#F2F3F4"), cell_text(weight = "bold", color = "#2E4053")),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = list(cell_fill(color = "#D4EFDF"), cell_text(color = "#196F3D", weight = "bold")),
    locations = cells_body(columns = Decision)
  )
TABLA RESUMEN: PRUEBA DE BONDAD DE AJUSTE
Evaluación Matemática Estricta del Modelo Log-Normal General
Intervalo de Agrupación Modelo Probabilístico Test de Pearson (r%) Chi-Cuadrado Calculado Umbral Crítico Resultado del Test
General (Todo el rango) Log-Normal 88.5% 12.716 15.507 Aprobado

11 Cálculo de Probabilidades

# Total de pozos válidos
total_pozos <- sum(TDF_General$ni)

¿Cuál es la probabilidad de que un pozo seleccionado al azar se encuentre en el intervalo de longitud de -54 a -46 dd?

# Probabilidad para el primer tramo (-54 a -46)
prob_1 <- sum(X >= -54 & X < -46) / total_pozos

La probabilidad es del 1.44%.

¿Cuál es la probabilidad de que un pozo seleccionado al azar pertenezca al tramo intermedio de -46 a -38 dd?

# Probabilidad para el tramo -46 a -38
prob_2 <- sum(X >= -46 & X < -38) / total_pozos

La probabilidad es del 44.02%.

12 Intervalo de confianza

# Calculamos la media
media_ic <- mean(X, na.rm = TRUE)

# Desviación estándar
desviacion_ic <- sd(X, na.rm = TRUE)

# Tamaño de muestra
n_ic <- length(na.omit(X))

error <- 1.96 * (desviacion_ic / sqrt(n_ic))

limite_inferior <- round(media_ic - error, 2)
limite_superior <- round(media_ic + error, 2)

tabla_intervalo <- data.frame(
  Variable  = "Longitud Base de Pozos",
  N         = n_ic,
  Media     = round(media_ic, 2),
  Desv_Est  = round(desviacion_ic, 2),
  Intervalo = paste0("P [", limite_inferior, " < μ < ", limite_superior, "]"),
  Confianza = "95%"
)
tabla_intervalo %>%
  gt() %>%
  tab_header(
    title = md("**TABLA RESUMEN: INTERVALO DE CONFIANZA**"),
    subtitle = md("Evaluación Estadística de la Longitud Base de los Pozos")
  ) %>%
  cols_label(
    Variable  = "Variable de Estudio",
    N         = "N° de Datos (n)",
    Media     = "Media (x̄)",
    Desv_Est  = "Desv. Estándar (s)",
    Intervalo = "Intervalo de Confianza (μ)",
    Confianza = "Nivel"
  ) %>%
  tab_source_note(
    source_note = md("Fuente: Tabela de Poços 2018")
  ) %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_style(
    style = list(
      cell_fill(color = "#2E4053"), 
      cell_text(color = "white", weight = "bold", size = px(14))
    ),
    locations = cells_title(groups = c("title"))
  ) %>%
  tab_style(
    style = list(
      cell_fill(color = "#34495E"), 
      cell_text(color = "white", size = px(12))
    ),
    locations = cells_title(groups = c("subtitle"))
  ) %>%
  tab_style(
    style = list(
      cell_fill(color = "#EAEDED"), 
      cell_text(weight = "bold", color = "#2E4053")
    ),
    locations = cells_column_labels()
  ) %>%
  tab_options(
    table.border.top.color = "#2E4053",
    table.border.bottom.color = "#2E4053",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "#2E4053",
    column_labels.border.bottom.color = "#2E4053",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE
  )
TABLA RESUMEN: INTERVALO DE CONFIANZA
Evaluación Estadística de la Longitud Base de los Pozos
Variable de Estudio N° de Datos (n) Media (x̄) Desv. Estándar (s) Intervalo de Confianza (μ) Nivel
Longitud Base de Pozos 28971 -38.3 2.08 P [-38.32 < μ < -38.27] 95%
Fuente: Tabela de Poços 2018

13 Conclusiones

La variable longitud base de los pozos en (dd) se puede explicar mediante un modelo probabilístico adaptado a sus intervalos. Podemos afirmar con un 95% de confianza que la media poblacional de esta variable se encuentra aproximadamente entre -38.32 y -38.27, con una media observada de -38.3 y una desviación estándar de 2.08. Además, se evidencia dispersión en los datos, lo que es consistente con modelos de distribución mixtos aplicados a la ubicación geográfica de pozos petroleros.