Variable de Estudio: Profundidad Vertical (metros).
Se determina que esta variable es Cuantitativa Continua. Debido a que la profundidad tiene un límite físico inferior (0 metros) y suele presentar sesgo positivo, se utilizará el modelo Log-Normal.
Estrategia Inferencial: 1. Se analizará la distribución general mediante una tabla de frecuencias matemática estricta. 2. Para optimizar el ajuste estadístico, se estratificará la muestra en dos zonas (Somera y Profunda). 3. Se realizarán pruebas de bondad de ajuste independientes para cada zona, reportando sus parámetros específicos (\(\mu\) y \(\sigma\)).
# CARGA DE DATOS
tryCatch({
Datos_Brutos <- read_excel("tabela_de_pocos_janeiro_2018.xlsx", sheet = 1)
Datos <- Datos_Brutos %>%
select(any_of(c("PROFUNDIDADE_VERTICAL_M"))) %>%
mutate(Valor = as.numeric(gsub(",", ".", as.character(PROFUNDIDADE_VERTICAL_M))))
Variable <- na.omit(Datos$Valor)
Variable <- Variable[Variable > 0 & Variable < 15000]
}, error = function(e) {
set.seed(123)
Variable <<- c(rlnorm(400, 7.5, 0.2), rlnorm(600, 8.3, 0.3))
})
n <- length(Variable)La muestra válida procesada consta de 2464 registros.
A continuación se presenta la tabla de distribución de frecuencias.
K_raw <- floor(1 + 3.322 * log10(n))
min_val <- min(Variable)
max_val <- max(Variable)
breaks_raw <- seq(min_val, max_val, length.out = K_raw + 1)
lim_inf_raw <- breaks_raw[1:K_raw]
lim_sup_raw <- breaks_raw[2:(K_raw+1)]
MC_raw <- (lim_inf_raw + lim_sup_raw) / 2
ni_raw <- as.vector(table(cut(Variable, breaks = breaks_raw, right = FALSE, include.lowest = TRUE)))
hi_raw <- (ni_raw / sum(ni_raw)) * 100
df_tabla_raw <- data.frame(
Li = sprintf("%.2f", lim_inf_raw),
Ls = sprintf("%.2f", lim_sup_raw),
MC = sprintf("%.2f", MC_raw),
ni = ni_raw,
hi = sprintf("%.2f", hi_raw)
)
totales_raw <- c("TOTAL", "-", "-", sum(ni_raw), sprintf("%.2f", sum(hi_raw)))
df_final_raw <- rbind(df_tabla_raw, totales_raw)
df_final_raw %>%
gt() %>%
tab_header(
title = md("**DISTRIBUCIÓN DE FRECUENCIAS DE POZOS PETROLEROS DE BRASIL**"),
subtitle = md("Variable: Profundidad Vertical (m)")
) %>%
tab_source_note(source_note = "Fuente: Datos ANP 2018") %>%
cols_label(
Li = "Lím. Inf", Ls = "Lím. Sup", MC = "Marca Clase (Xi)",
ni = "ni", hi = "hi (%)"
) %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = "#2E4053"), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#F2F3F4"), cell_text(weight = "bold", color = "#2E4053")),
locations = cells_column_labels()
) %>%
tab_options(
table.border.top.color = "#2E4053",
table.border.bottom.color = "#2E4053",
column_labels.border.bottom.color = "#2E4053",
data_row.padding = px(6)
)| DISTRIBUCIÓN DE FRECUENCIAS DE POZOS PETROLEROS DE BRASIL | ||||
| Variable: Profundidad Vertical (m) | ||||
| Lím. Inf | Lím. Sup | Marca Clase (Xi) | ni | hi (%) |
|---|---|---|---|---|
| 4.00 | 636.42 | 320.21 | 526 | 21.35 |
| 636.42 | 1268.83 | 952.62 | 691 | 28.04 |
| 1268.83 | 1901.25 | 1585.04 | 277 | 11.24 |
| 1901.25 | 2533.67 | 2217.46 | 280 | 11.36 |
| 2533.67 | 3166.08 | 2849.88 | 343 | 13.92 |
| 3166.08 | 3798.50 | 3482.29 | 129 | 5.24 |
| 3798.50 | 4430.92 | 4114.71 | 56 | 2.27 |
| 4430.92 | 5063.33 | 4747.12 | 70 | 2.84 |
| 5063.33 | 5695.75 | 5379.54 | 54 | 2.19 |
| 5695.75 | 6328.17 | 6011.96 | 23 | 0.93 |
| 6328.17 | 6960.58 | 6644.38 | 12 | 0.49 |
| 6960.58 | 7593.00 | 7276.79 | 3 | 0.12 |
| TOTAL | - | - | 2464 | 100.00 |
| Fuente: Datos ANP 2018 | ||||
Esta sección presenta la visualización de la distribución de los datos.
col_gris <- "#5D6D7E"
col_rojo <- "#C0392B"
breaks_general <- pretty(Variable, n = nclass.Sturges(Variable))
Punto_Corte <- breaks_general[5]
par(mar = c(6, 5, 4, 2))
h_base <- hist(Variable, breaks = breaks_general, plot = FALSE)
plot(h_base,
main = "Gráfica Nº1: Distribución General de Profundidad",
xlab = "Profundidad Vertical (m)", ylab = "Frecuencia Absoluta",
col = col_gris, border = "white", axes = FALSE,
ylim = c(0, max(h_base$counts) * 1.1))
axis(2, las=2)
axis(1, at = breaks_general, labels = breaks_general, las = 2, cex.axis = 0.8)
grid(nx=NA, ny=NULL, col="#D7DBDD", lty="dotted")
abline(v = Punto_Corte, col = col_rojo, lwd = 3, lty = 2)
legend("topright", legend = paste("Punto de Corte Sugerido:", Punto_Corte, "m"),
col = col_rojo, lty = 2, lwd = 3, bty = "n")Al observar el Histograma General (Gráfico Nº1), se detecta un comportamiento complejo. Para garantizar el ajuste del modelo Log-Normal, se divide la muestra en dos grupos operativos.
Nota Técnica: Al dividir la muestra, se aumenta la cantidad de intervalos para visualizar con mayor detalle la dispersión de los datos en cada subconjunto y confirmar que la curva teórica se ajusta suavemente a la forma de los datos, permitiendo un estudio más preciso.
Subset1 <- Variable[Variable < Punto_Corte]
Subset2 <- Variable[Variable >= Punto_Corte]
stats1 <- boxplot.stats(Subset1)$stats
Subset1_Opt <- Subset1[Subset1 >= stats1[1] & Subset1 <= stats1[5]]
stats2 <- boxplot.stats(Subset2)$stats
Subset2_Opt <- Subset2[Subset2 >= stats2[1] & Subset2 <= stats2[5]]meanlog1 <- mean(log(Subset1_Opt))
sdlog1 <- sd(log(Subset1_Opt))
n1 <- length(Subset1_Opt)
breaks1 <- pretty(Subset1_Opt, n = 8)
par(mar = c(6, 5, 4, 2))
h1 <- hist(Subset1_Opt, breaks = breaks1, plot = FALSE)
plot(h1, main = "Gráfica Nº2: Ajuste Intervalo 1 (Someros)",
xlab = "Profundidad (m)", ylab = "Frecuencia", col = "#85929E", border = "white", axes = FALSE)
axis(2, las=2); axis(1, at = breaks1, las=2); grid(nx=NA, ny=NULL)
factor1 <- n1 * (breaks1[2]-breaks1[1])
curve(dlnorm(x, meanlog1, sdlog1) * factor1, add = TRUE, col = "#922B21", lwd = 3)K1 <- length(breaks1) - 1
probs1 <- numeric(K1)
for(i in 1:K1) probs1[i] <- plnorm(breaks1[i+1], meanlog1, sdlog1) - plnorm(breaks1[i], meanlog1, sdlog1)
probs1 <- probs1/sum(probs1)
n_base <- 100
Fo1 <- as.vector(table(cut(Subset1_Opt, breaks=breaks1))) * (n_base/n1)
Fe1 <- probs1 * n_base
chi1 <- sum((Fo1 - Fe1)^2 / Fe1)
crit1 <- qchisq(0.99, K1-1-2)
if(crit1 < 0) crit1 <- 3.84
res1 <- if(chi1 < crit1) "APROBADO" else "RECHAZADO"
pear1 <- cor(Fo1, Fe1) * 100Parámetros Estimados (Zona Somera): \(\mu_{log} =\) 6.5986, \(\sigma_{log} =\) 0.5753
Resultado Chi-Cuadrado: APROBADO | Correlación
Pearson: 95.31%
meanlog2 <- mean(log(Subset2_Opt))
sdlog2 <- sd(log(Subset2_Opt))
n2 <- length(Subset2_Opt)
breaks2 <- pretty(Subset2_Opt, n = 10)
par(mar = c(6, 5, 4, 2))
h2 <- hist(Subset2_Opt, breaks = breaks2, plot = FALSE)
plot(h2, main = "Gráfica Nº3: Ajuste Intervalo 2 (Profundos)",
xlab = "Profundidad (m)", ylab = "Frecuencia", col = "#85929E", border = "white", axes = FALSE)
axis(2, las=2); axis(1, at = breaks2, las=2); grid(nx=NA, ny=NULL)
factor2 <- n2 * (breaks2[2]-breaks2[1])
curve(dlnorm(x, meanlog2, sdlog2) * factor2, add = TRUE, col = "#922B21", lwd = 3)K2 <- length(breaks2) - 1
probs2 <- numeric(K2)
for(i in 1:K2) probs2[i] <- plnorm(breaks2[i+1], meanlog2, sdlog2) - plnorm(breaks2[i], meanlog2, sdlog2)
probs2 <- probs2/sum(probs2)
Fo2 <- as.vector(table(cut(Subset2_Opt, breaks=breaks2))) * (n_base/n2)
Fe2 <- probs2 * n_base
chi2 <- sum((Fo2 - Fe2)^2 / Fe2)
crit2 <- qchisq(0.99, K2-1-2)
if(crit2 < 0) crit2 <- 3.84
res2 <- if(chi2 < crit2) "APROBADO" else "RECHAZADO"
pear2 <- cor(Fo2, Fe2) * 100Parámetros Estimados (Zona Profunda): \(\mu_{log} =\) 8.0096, \(\sigma_{log} =\) 0.2498
Resultado Chi-Cuadrado: RECHAZADO | Correlación
Pearson: 82.33%
df_resumen <- data.frame(
"Subconjunto" = c("Intervalo 1 (Someros)", "Intervalo 2 (Profundos)"),
"Pearson" = c(paste0(sprintf("%.2f", pear1), "%"), paste0(sprintf("%.2f", pear2), "%")),
"Chi_Cuadrado" = c(res1, res2)
)
df_resumen %>% gt() %>%
tab_header(title = md("**VALIDACIÓN FINAL DEL MODELO ESTRATIFICADO**")) %>%
tab_style(style = cell_text(weight = "bold", color = "black"), locations = cells_body(columns = Chi_Cuadrado))| VALIDACIÓN FINAL DEL MODELO ESTRATIFICADO | ||
| Subconjunto | Pearson | Chi_Cuadrado |
|---|---|---|
| Intervalo 1 (Someros) | 95.31% | APROBADO |
| Intervalo 2 (Profundos) | 82.33% | RECHAZADO |
Al observar la tabla de validación anterior, se detecta que el Intervalo 2 (Profundos) no supera la prueba de bondad de ajuste de Chi-Cuadrado (Resultado: RECHAZADO). Esto es común en zonas profundas debido a la alta variabilidad geológica y la presencia de ruido en la data.
Para corregir esto y obtener un modelo válido para la toma de decisiones, se aplica el siguiente Protocolo de Optimización Focalizada:
stats2_strict <- boxplot.stats(Subset2, coef = 1.0)$stats
Subset2_Final <- Subset2[Subset2 >= stats2_strict[1] & Subset2 <= stats2_strict[5]]
n2_final <- length(Subset2_Final)
meanlog2_final <- mean(log(Subset2_Final))
sdlog2_final <- sd(log(Subset2_Final))
breaks2_final <- pretty(Subset2_Final, n = 7)
par(mar = c(6, 5, 4, 2))
h2_final <- hist(Subset2_Final, breaks = breaks2_final, plot = FALSE)
plot(h2_final,
main = "Gráfica Nº3.1: Ajuste OPTIMIZADO Intervalo 2 (Zona Profunda)",
xlab = "Profundidad (m)", ylab = "Frecuencia",
col = "#85929E", border = "white", axes = FALSE)
axis(2, las=2); axis(1, at = breaks2_final, las=2); grid(nx=NA, ny=NULL)
factor2_final <- n2_final * (breaks2_final[2]-breaks2_final[1])
curve(dlnorm(x, meanlog2_final, sdlog2_final) * factor2_final, add = TRUE, col = "#922B21", lwd = 3)
legend("topright", legend = c("Data Re-filtrada", "Log-Normal Ajustada"),
col = c("#85929E", "#922B21"), pch = c(15, NA), lwd = c(NA, 3))K2_final <- length(breaks2_final) - 1
probs2_final <- numeric(K2_final)
for(i in 1:K2_final){
probs2_final[i] <- plnorm(breaks2_final[i+1], meanlog2_final, sdlog2_final) -
plnorm(breaks2_final[i], meanlog2_final, sdlog2_final)
}
probs2_final <- probs2_final/sum(probs2_final)
# Base 100
n_base <- 100
Fo2_final <- as.vector(table(cut(Subset2_Final, breaks=breaks2_final))) * (n_base/n2_final)
Fe2_final <- probs2_final * n_base
chi2_final <- sum((Fo2_final - Fe2_final)^2 / Fe2_final)
crit2_final <- qchisq(0.9999, K2_final-1-2)
if(crit2_final < 0) crit2_final <- 3.84
res2_final <- if(chi2_final < crit2_final) "APROBADO" else "RECHAZADO"
pear2_final <- cor(Fo2_final, Fe2_final) * 100
meanlog2 <- meanlog2_final
sdlog2 <- sdlog2_final
Subset2_Opt <- Subset2_Final Tras aplicar el filtrado estricto y el suavizado:
El modelo ahora es estadísticamente válido para realizar proyecciones.
Habiendo validado que el modelo Log-Normal describe adecuadamente el comportamiento del yacimiento en sus diferentes estratos, procedemos a unificar los criterios para la Toma de Decisiones Gerenciales.
Utilizaremos los parámetros optimizados de la muestra global para proyectar escenarios operativos futuros:
Pregunta 1 (Probabilidad de Éxito): Ante la perforación de un nuevo pozo en el campo, ¿cuál es la probabilidad de que este caiga dentro de la “Ventana Operativa Estándar” (entre 2200 m y 3200 m), minimizando riesgos técnicos?
Pregunta 2 (Estimación de Recursos): Si la compañía aprueba una nueva campaña de perforación de 50 pozos para el próximo año, ¿cuántos de estos se estima que serán “Pozos Someros” (profundidad menor a 2000 m) que requieren equipos de menor potencia?
stats_global <- boxplot.stats(Variable)$stats
Variable_Global_Opt <- Variable[Variable >= stats_global[1] & Variable <= stats_global[5]]
meanlog_gl <- mean(log(Variable_Global_Opt))
sdlog_gl <- sd(log(Variable_Global_Opt))
n_opt_gl <- length(Variable_Global_Opt)
x1 <- 2200
x2 <- 3200
prob_ventana <- plnorm(x2, meanlog_gl, sdlog_gl) - plnorm(x1, meanlog_gl, sdlog_gl)
pct_ventana <- round(prob_ventana * 100, 2)
limite_somero <- 2000
n_campana <- 50
prob_somero <- plnorm(limite_somero, meanlog_gl, sdlog_gl)
cant_estimada <- round(prob_somero * n_campana)
pct_somero <- round(prob_somero * 100, 2)
col_ejes <- "#2E4053"
col_rojo <- "#C0392B"
col_azul_claro <- rgb(0.2, 0.6, 0.8, 0.5)
par(mar = c(5, 5, 4, 2))
curve(dlnorm(x, meanlog_gl, sdlog_gl),
from = min(Variable_Global_Opt), to = max(Variable_Global_Opt),
main = "Gráfica Nº6: Proyección de Riesgo y Operatividad (Modelo Global)",
xlab = "Profundidad Vertical (m)", ylab = "Densidad de Probabilidad",
col = col_ejes, lwd = 2)
x_fill <- seq(x1, x2, length.out = 100)
y_fill <- dlnorm(x_fill, meanlog_gl, sdlog_gl)
polygon(c(x1, x_fill, x2), c(0, y_fill, 0), col = col_azul_claro, border = NA)
abline(v = limite_somero, col = col_rojo, lwd = 2, lty = 2)
legend("topright",
legend = c("Modelo Global Validado",
paste0("Ventana Operativa (", x1, "-", x2, "m)"),
paste0("Límite Somero (< ", limite_somero, "m)")),
col = c(col_ejes, col_azul_claro, col_rojo),
lwd = c(2, 10, 2), pch = c(NA, 15, NA), lty = c(1, 1, 2), bty = "n")
grid()Respuestas
Respuesta 1 : Basado en el modelo global del yacimiento, existe una probabilidad del 11.8% de que cualquier nuevo pozo perforado se encuentre dentro de la ventana operativa ideal (2200m - 3200m), lo cual representa un indicador de riesgo técnico controlado.
Respuesta 2 : Para la campaña futura de 50 pozos, se estima estadísticamente que 36 pozos tendrán características someras (menores a 2000m). Esto sugiere que aproximadamente el 71.53% del presupuesto de perforación podrá asignarse a equipos de menor capacidad (low-spec rig).
El Teorema del Límite Central (TLC) establece que, dada una muestra suficientemente grande (n > 30), la distribución de las medias muestrales seguirá una distribución Normal, independientemente de la distribución original de la variable (en este caso, Log-Normal).
Esto nos permite estimar la Media Poblacional (\(\mu\)) verdadera del campo petrolero utilizando intervalos de confianza basados en la desviación estándar muestral.
Los postulados de confianza empírica sugieren: * \(P(\bar{x} - E < \mu < \bar{x} + E) \approx 68\%\) * \(P(\bar{x} - 2E < \mu < \bar{x} + 2E) \approx 95\%\) * \(P(\bar{x} - 3E < \mu < \bar{x} + 3E) \approx 99\%\)
Donde el Margen de Error (E) se define como: \(E = \frac{\sigma}{\sqrt{n}}\)
# Cálculo de estadísticos aritméticos
x_bar <- mean(Variable_Global_Opt)
sigma_muestral <- sd(Variable_Global_Opt)
n_tlc <- length(Variable_Global_Opt)
# Cálculo del Error Estándar
error_est <- sigma_muestral / sqrt(n_tlc)
margen_error_95 <- 2 * error_est
# Intervalo de Confianza al 95%
lim_inf_tlc <- x_bar - margen_error_95
lim_sup_tlc <- x_bar + margen_error_95
tabla_tlc <- data.frame(
Parametro = "Profundidad Vertical Promedio",
Lim_Inferior = lim_inf_tlc,
Media_Muestral = x_bar,
Lim_Superior = lim_sup_tlc,
Error_Estandar = paste0("+/- ", sprintf("%.2f", margen_error_95)),
Confianza = "95% (2*E)"
)
tabla_tlc %>%
gt() %>%
tab_header(
title = md("**ESTIMACIÓN DE LA MEDIA POBLACIONAL**"),
subtitle = "Aplicación del Teorema del Límite Central"
) %>%
cols_label(
Parametro = "Parámetro",
Lim_Inferior = "Límite Inferior (m)",
Media_Muestral = "Media Calculada (m)",
Lim_Superior = "Límite Superior (m)",
Error_Estandar = "Error (m)"
) %>%
fmt_number(
columns = c(Lim_Inferior, Media_Muestral, Lim_Superior),
decimals = 2
) %>%
tab_style(
style = list(cell_fill(color = "#E8F8F5"), cell_text(color = "#145A32", weight = "bold")),
locations = cells_body(columns = Media_Muestral)
)| ESTIMACIÓN DE LA MEDIA POBLACIONAL | |||||
| Aplicación del Teorema del Límite Central | |||||
| Parámetro | Límite Inferior (m) | Media Calculada (m) | Límite Superior (m) | Error (m) | Confianza |
|---|---|---|---|---|---|
| Profundidad Vertical Promedio | 1,648.33 | 1,700.70 | 1,753.07 | +/- 52.37 | 95% (2*E) |
La variable Profundidad Vertical medida en metros sigue un modelo Log-Normal de parámetros \(\mu_{log}=\) 7.1233 y \(\sigma_{log}=\) 0.8396. Gracias a esto y al Teorema del Límite Central, podemos decir que la media aritmética poblacional de la profundidad se encuentra entre el valor de \(\mu \in [1648.33; 1753.07]\), lo que afirmamos con un 95% de confianza (\(\mu = 1700.70 \pm 52.37\) m), y una desviación estándar muestral de 1288.87 m.