library(readr) # lectura del csv
library(dplyr) # manipulación de datos
library(ggplot2) # gráficos
library(gt) # tablas con diseño premium
library(stringr) # manejo de texto
library(DT) # tabla interactiva paginada
cat("Librerías cargadas: readr, dplyr, ggplot2, gt, stringr, DT")Librerías cargadas: readr, dplyr, ggplot2, gt, stringr, DT
## DATASET ##
# Archivo con las variables AVG_PRODUCTION y CUMULATIVE_PRODUCTION.
# IMPORTANTE: ajusta esta ruta a la ubicación real del archivo en tu equipo.
ruta_archivo <- "oil_and_gas_leases_data.csv.csv"
datos <- read_csv(ruta_archivo, show_col_types = FALSE)
# Rellenamiento de celdas faltantes (NA) con la mediana de cada variable numérica de interés
if (any(is.na(datos$AVG_PRODUCTION))) {
datos$AVG_PRODUCTION[is.na(datos$AVG_PRODUCTION)] <- median(datos$AVG_PRODUCTION, na.rm = TRUE)
}
if (any(is.na(datos$CUMULATIVE_PRODUCTION))) {
datos$CUMULATIVE_PRODUCTION[is.na(datos$CUMULATIVE_PRODUCTION)] <- median(datos$CUMULATIVE_PRODUCTION, na.rm = TRUE)
}
# Se descartan pozos con valores no positivos (no tienen sentido físico y
# además impiden aplicar logaritmos si se necesitaran como respaldo)
datos <- datos %>%
filter(AVG_PRODUCTION > 0, CUMULATIVE_PRODUCTION > 0)
## Estructura de los datos
str(datos[, c("AVG_PRODUCTION", "CUMULATIVE_PRODUCTION")])tibble [47,757 × 2] (S3: tbl_df/tbl/data.frame)
$ AVG_PRODUCTION : num [1:47757] 859 5001 1758 377 24322 ...
$ CUMULATIVE_PRODUCTION: num [1:47757] 47225 275063 82624 7544 681006 ...
Según la Tabla de Variables del proyecto, se eligió el siguiente par por ser conceptualmente directamente proporcional: un pozo con mayor producción promedio (ritmo de extracción) tiende a acumular, en total, una mayor cantidad de hidrocarburos.
Se definió la Producción Promedio Anual
(AVG_PRODUCTION, cuantitativa continua, proporción, medida
en barriles/año) como variable independiente / causa
(x), ya que representa el ritmo al que un pozo extrae
hidrocarburos.
La Producción Acumulada
(CUMULATIVE_PRODUCTION, cuantitativa continua, proporción,
medida en barriles) actúa como variable dependiente / efecto
(y), pues refleja la cantidad total de hidrocarburos extraídos
a lo largo de la vida del pozo.
Ambas variables cumplen la condición buscada: al aumentar x, y también aumenta de forma sostenida, lo que se comprueba en las secciones siguientes.
El dataset depurado contiene 47757 pozos, con valores de Producción Promedio (x) muy dispersos y sin repetirse exactamente entre pozos. Trabajar con los 47757 pares crudos genera una nube saturada y ruidosa (se muestra completa en la siguiente sección). Por ello, para el ajuste del modelo se ordenan los pozos según su Producción Promedio y se agrupan en 25 percentiles (grupos de igual cantidad de pozos), calculando la mediana (en vez de la media, para reducir el efecto de pozos atípicos con producciones extremas) de ambas variables dentro de cada grupo. Esto entrega un único par (x̃, ỹ) por percentil.
tabla_xy <- datos %>%
mutate(percentil = ntile(AVG_PRODUCTION, 25)) %>%
group_by(percentil) %>%
summarise(
n_pozos = n(),
x_mediana = median(AVG_PRODUCTION),
y_mediana = median(CUMULATIVE_PRODUCTION),
.groups = "drop"
) %>%
arrange(percentil)
cat("Total de pares (x̃, ỹ) obtenidos, uno por percentil:", nrow(tabla_xy), "\n")Total de pares (x̃, ỹ) obtenidos, uno por percentil: 25
datatable(
tabla_xy,
caption = htmltools::tags$caption(
style = "caption-side: top; text-align: left; font-size: 16px; font-weight: 700; color:#1F2A33;",
"Tabla N°1: Pares (x̃, ỹ) — Mediana de Producción Acumulada por Percentil de Producción Promedio"
),
rownames = FALSE,
class = "display compact stripe hover",
options = list(
pageLength = 10,
dom = "ltip",
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
) %>%
formatRound(columns = c("x_mediana", "y_mediana"), digits = 2)max_x <- max(tabla_xy$x_mediana)
min_x <- min(tabla_xy$x_mediana)
max_y <- max(tabla_xy$y_mediana)
min_y <- min(tabla_xy$y_mediana)
resumen_general <- data.frame(
Variable = c("AVG_PRODUCTION (X)", "CUMULATIVE_PRODUCTION (Y)"),
Minimo = round(c(min_x, min_y), 2),
Maximo = round(c(max_x, max_y), 2),
Rango = round(c(max_x - min_x, max_y - min_y), 2),
Mediana = round(c(median(tabla_xy$x_mediana), median(tabla_xy$y_mediana)), 2)
)
resumen_general %>%
gt() %>%
tab_header(
title = md("**Tabla N°2: Resumen General de las Variables (pares x̃, ỹ)**")
) %>%
tab_source_note(source_note = "Autor: Valeska Araujo") %>%
cols_align(align = "center", everything())| Tabla N°2: Resumen General de las Variables (pares x̃, ỹ) | ||||
| Variable | Minimo | Maximo | Rango | Mediana |
|---|---|---|---|---|
| AVG_PRODUCTION (X) | 68.76 | 34508.29 | 34439.53 | 2581.99 |
| CUMULATIVE_PRODUCTION (Y) | 588.22 | 624961.00 | 624372.78 | 53176.69 |
| Autor: Valeska Araujo | ||||
Se grafican todos los pozos del dataset, sin agrupar ni resumir, para visualizar la nube completa de puntos.
par(mar = c(5, 5, 4, 2))
plot(datos$AVG_PRODUCTION, datos$CUMULATIVE_PRODUCTION,
pch = 16, cex = 0.35,
col = adjustcolor("#2E86AB", alpha.f = 0.15),
xlab = "X (Producción Promedio Anual)", ylab = "Y (Producción Acumulada)",
main = "Gráfica N°1: Nube de Puntos — Todos los Valores",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
box()Con los datos ya resumidos por percentil (mediana), la tendencia ascendente se aprecia con mayor claridad, sin el ruido de los pozos atípicos.
par(mar = c(5, 5, 4, 2))
plot(tabla_xy$x_mediana, tabla_xy$y_mediana, pch = 19, col = "#2E86AB",
xlab = "X̃ (Mediana Producción Promedio Anual)", ylab = "Ỹ (Mediana Producción Acumulada)",
main = "Gráfica N°2: Nube de Puntos — Pares (x̃, ỹ)",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
box()Al observar ambas nubes de puntos, se aprecia una tendencia ascendente y prácticamente recta: a medida que aumenta la Producción Promedio Anual, la Producción Acumulada crece de forma sostenida y proporcional en todo el rango de X, sin cambios bruscos de patrón que obliguen a segmentar el análisis por partes.
Por lo tanto, se conjetura un modelo lineal simple, directamente proporcional: \[y = a + bx\]
con pendiente \(b > 0\) (relación directamente proporcional / ascendente).
El modelo se ajusta sobre los pares (x̃, ỹ) por percentil (Tabla N°1), ya que usar los 47757 pozos crudos sin resumir le da peso excesivo a los pozos atípicos con producciones extremas.
modelo <- lm(y_mediana ~ x_mediana, data = tabla_xy)
a <- coef(modelo)[1]
b <- coef(modelo)[2]
cat("Modelo ajustado: y =", round(a, 2), "+", round(b, 2), "* x\n")Modelo ajustado: y = 2469.65 + 20.27 * x
Call:
lm(formula = y_mediana ~ x_mediana, data = tabla_xy)
Residuals:
Min 1Q Median 3Q Max
-128348 -5288 -4339 -2687 158138
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2469.653 11046.462 0.224 0.825
x_mediana 20.275 1.092 18.564 0.00000000000000244 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 44380 on 23 degrees of freedom
Multiple R-squared: 0.9374, Adjusted R-squared: 0.9347
F-statistic: 344.6 on 1 and 23 DF, p-value: 0.000000000000002438
par(mar = c(5, 5, 4, 2))
plot(tabla_xy$x_mediana, tabla_xy$y_mediana, col = "#2E86AB", pch = 16,
xlab = "X̃ (Mediana Producción Promedio Anual)", ylab = "Ỹ (Mediana Producción Acumulada)",
main = "Gráfica N°3: Sobreponer Modelo con la Realidad — Pares (x̃, ỹ)",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
abline(modelo, col = "#1F2A33", lwd = 3)
legend("topleft", legend = c("Datos (x̃, ỹ)", "Modelo Lineal"),
col = c("#2E86AB", "#1F2A33"), pch = c(16, NA), lwd = c(NA, 3), bty = "n")
box()La recta sigue de cerca la dirección de los puntos, ajustándose casi perfectamente a los pares (x̃, ỹ) y confirmando una relación lineal ascendente.
El coeficiente de correlación de Pearson, calculado mediante
cor(x, y), debe superar 0.7 (en valor
absoluto) para aceptar el modelo lineal, dado que toma valores entre -1
y 1. Se evalúa tanto sobre los pares (x̃, ỹ) usados para ajustar el
modelo, como sobre los pozos crudos (todos los valores), para verificar
consistencia.
r_medianas <- cor.test(tabla_xy$x_mediana, tabla_xy$y_mediana)
r_todos <- cor.test(datos$AVG_PRODUCTION, datos$CUMULATIVE_PRODUCTION)
tabla_pearson <- data.frame(
Conjunto = c("Pares (x̃, ỹ) por percentil", "Todos los valores (pozos crudos)"),
r = round(c(r_medianas$estimate, r_todos$estimate), 4),
R2 = round(c(r_medianas$estimate^2, r_todos$estimate^2), 4),
Supera_0.7 = c(abs(r_medianas$estimate) > 0.7, abs(r_todos$estimate) > 0.7)
)
tabla_pearson %>%
gt() %>%
tab_header(
title = md("**Tabla N°3: Test de Bondad de Ajuste**"),
subtitle = "Umbral |r| > 0.7"
) %>%
tab_source_note(source_note = "Autor: Valeska Araujo") %>%
cols_align(align = "center", everything())| Tabla N°3: Test de Bondad de Ajuste | |||
| Umbral |r| > 0.7 | |||
| Conjunto | r | R2 | Supera_0.7 |
|---|---|---|---|
| Pares (x̃, ỹ) por percentil | 0.9682 | 0.9374 | TRUE |
| Todos los valores (pozos crudos) | 0.5449 | 0.2969 | FALSE |
| Autor: Valeska Araujo | |||
Sobre los pares (x̃, ỹ), \(r =\) 0.968 (\(R^2 =\) 0.937), muy por encima del umbral de 0.7, por lo que el modelo lineal se acepta para describir la tendencia central de la relación. Sobre los pozos crudos el coeficiente es más bajo (0.545), lo cual es esperado: al no resumir por percentil, la dispersión natural de miles de pozos individuales reduce el ajuste lineal, aunque la dirección de la recta (pendiente positiva) sigue siendo consistente con la tendencia observada.
El modelo es válido únicamente dentro del rango de X observado, aproximadamente entre 69 y 34,508 barriles/año de Producción Promedio; no se recomienda extrapolar fuera de ese rango, ya que el comportamiento de pozos con ritmos de producción muy distintos a los observados no está garantizado por los datos.
x_est <- round(median(tabla_xy$x_mediana), 1)
y_est <- a + b * x_est
data.frame(
X_estimado = x_est,
Y_estimado = round(y_est, 1)
) %>%
gt() %>%
tab_header(
title = md("**Tabla N°4: Estimación Puntual de Producción Acumulada**")
) %>%
tab_source_note(source_note = "Autor: Valeska Araujo") %>%
cols_align(align = "center", everything())| Tabla N°4: Estimación Puntual de Producción Acumulada | |
| X_estimado | Y_estimado |
|---|---|
| 2582 | 54818.9 |
| Autor: Valeska Araujo | |
Para un pozo con una producción promedio de 2,582 barriles/año, el modelo estima una producción acumulada de aproximadamente 54,818.9 barriles.