Usar Run All (Code → Run Region → Run All), no
Knit, porque el chunk de carga usa file.choose().
library(readxl)
library(dplyr)
library(knitr)
library(kableExtra)
library(DT)
ruta <- file.choose()
datos <- read_excel(ruta)
datos <- datos %>%
mutate(
YEARS_ACTIVE = as.numeric(YEARS_ACTIVE),
CUMULATIVE_PRODUCTION = as.numeric(CUMULATIVE_PRODUCTION)
) %>%
na.omit()
nrow(datos)
## [1] 22399
Causa (X): YEARS_ACTIVE —
Efecto (Y): CUMULATIVE_PRODUCTION
Justificación:
CUMULATIVE_PRODUCTION como X y YEARS_ACTIVE
como Y) implicaría que el tiempo transcurrido depende de cuánto petróleo
se ha extraído, lo cual no tiene sentido físico.Por estas tres razones, YEARS_ACTIVE se toma como
variable independiente (X) y CUMULATIVE_PRODUCTION como
variable dependiente (Y).
str(datos[, c("YEARS_ACTIVE", "CUMULATIVE_PRODUCTION")])
## tibble [22,399 × 2] (S3: tbl_df/tbl/data.frame)
## $ YEARS_ACTIVE : num [1:22399] 55 55 47 20 28 55 20 48 48 55 ...
## $ CUMULATIVE_PRODUCTION: num [1:22399] 47225 275063 82624 7544 681006 ...
## - attr(*, "na.action")= 'omit' Named int [1:11200] 22400 22401 22402 22403 22404 22405 22406 22407 22408 22409 ...
## ..- attr(*, "names")= chr [1:11200] "22400" "22401" "22402" "22403" ...
summary(datos[, c("YEARS_ACTIVE", "CUMULATIVE_PRODUCTION")])
## YEARS_ACTIVE CUMULATIVE_PRODUCTION
## Min. : 1.00 Min. : 1
## 1st Qu.:11.00 1st Qu.: 13753
## Median :20.00 Median : 54264
## Mean :25.73 Mean :150368
## 3rd Qu.:39.00 3rd Qu.:184136
## Max. :89.00 Max. :985283
estadisticos <- data.frame(
Variable = c("YEARS_ACTIVE", "CUMULATIVE_PRODUCTION"),
Media = c(mean(datos$YEARS_ACTIVE), mean(datos$CUMULATIVE_PRODUCTION)),
Minimo = c(min(datos$YEARS_ACTIVE), min(datos$CUMULATIVE_PRODUCTION)),
Maximo = c(max(datos$YEARS_ACTIVE), max(datos$CUMULATIVE_PRODUCTION)),
Rango = c(max(datos$YEARS_ACTIVE) - min(datos$YEARS_ACTIVE),
max(datos$CUMULATIVE_PRODUCTION) - min(datos$CUMULATIVE_PRODUCTION))
)
kable(estadisticos, digits = 2, format.args = list(big.mark = ","),
col.names = c("Variable", "Media", "Mínimo", "Máximo", "Rango"),
align = "lrrrr") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
| Variable | Media | Mínimo | Máximo | Rango |
|---|---|---|---|---|
| YEARS_ACTIVE | 25.73 | 1 | 89 | 88 |
| CUMULATIVE_PRODUCTION | 150,367.69 | 1 | 985,283 | 985,282 |
condensado <- datos %>%
group_by(YEARS_ACTIVE) %>%
summarise(
n_valores = n(),
valores = paste(CUMULATIVE_PRODUCTION, collapse = ", "),
.groups = "drop"
) %>%
arrange(YEARS_ACTIVE)
condensado_html <- condensado %>%
mutate(
CUMULATIVE_PRODUCTION = paste0(
"<details><summary>", n_valores, " valor(es)</summary>", valores, "</details>"
)
) %>%
select(YEARS_ACTIVE, CUMULATIVE_PRODUCTION)
datatable(condensado_html, escape = FALSE, rownames = FALSE,
colnames = c("Años Activos", "Producción Acumulada (valores)"),
class = "stripe hover compact",
options = list(pageLength = 10))
tabla_mediana <- datos %>%
group_by(YEARS_ACTIVE) %>%
summarise(
CUMULATIVE_PRODUCTION = median(CUMULATIVE_PRODUCTION),
.groups = "drop"
) %>%
arrange(YEARS_ACTIVE)
datatable(tabla_mediana, rownames = FALSE,
colnames = c("Años Activos", "Mediana de Producción Acumulada"),
class = "stripe hover compact",
options = list(pageLength = 10)) %>%
formatRound(columns = "CUMULATIVE_PRODUCTION", digits = 2)
write.csv(condensado[, c("YEARS_ACTIVE", "valores")], "tabla_condensada_por_anios.csv", row.names = FALSE)
write.csv(tabla_mediana, "tabla_mediana_por_anios.csv", row.names = FALSE)
plot(tabla_mediana$YEARS_ACTIVE, tabla_mediana$CUMULATIVE_PRODUCTION,
main = "Producción acumulada en función de los años activos",
xlab = "Años Activos (X)",
ylab = "Mediana de Producción Acumulada (Y)",
col = "#1b2a4a",
pch = 19,
cex = 1.2)
grid(col = "gray88")
La curva crece cerca de cero y se acelera con los años, sin bajar ni aplanarse. Se conjetura un modelo potencial:
\[y = a \cdot x^{b}\]
lm en R)\[\ln(y) = \ln(a) + b \cdot \ln(x)\]
datos_potencial <- tabla_mediana %>%
filter(YEARS_ACTIVE > 0, CUMULATIVE_PRODUCTION > 0)
modelo_log <- lm(log(CUMULATIVE_PRODUCTION) ~ log(YEARS_ACTIVE), data = datos_potencial)
summary(modelo_log)
##
## Call:
## lm(formula = log(CUMULATIVE_PRODUCTION) ~ log(YEARS_ACTIVE),
## data = datos_potencial)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.74877 -0.27278 0.00227 0.23344 1.52871
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.03910 0.16955 41.52 <2e-16 ***
## log(YEARS_ACTIVE) 1.28357 0.04656 27.57 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4029 on 87 degrees of freedom
## Multiple R-squared: 0.8973, Adjusted R-squared: 0.8961
## F-statistic: 760 on 1 and 87 DF, p-value: < 2.2e-16
b <- unname(coef(modelo_log)[2])
a <- unname(exp(coef(modelo_log)[1]))
kable(data.frame(Parámetro = c("a", "b"), Valor = round(c(a, b), 4)),
align = "lr") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
| Parámetro | Valor |
|---|---|
| a | 1140.3630 |
| b | 1.2836 |
plot(datos_potencial$YEARS_ACTIVE, datos_potencial$CUMULATIVE_PRODUCTION,
col = "#5b6b8c",
pch = 19,
cex = 1.2,
main = "Modelo de producción acumulada (mediana) en función de los años activos",
xlab = "Años Activos (X)",
ylab = "Mediana de Producción Acumulada (Y)")
grid(col = "gray88")
curve(a * x^b, add = TRUE, col = "#1b2a4a", lwd = 2)
legend("topleft",
legend = c("Datos reales", paste0("y = ", round(a, 2), " x^", round(b, 2))),
col = c("#5b6b8c", "#1b2a4a"),
pch = c(19, NA),
lty = c(NA, 1),
lwd = c(NA, 2),
bty = "n")
Tal como se aprecia en las imágenes de referencia, la nube de puntos
muestra dos comportamientos distintos: un tramo inicial de crecimiento
lento/plano y un tramo posterior de crecimiento acelerado. Se divide el
gráfico principal en esas dos secciones (corte en
YEARS_ACTIVE = 15) para ajustar un modelo
exponencial (y = a * e^(b*x)) a cada una.
seccion_A <- datos_potencial %>% filter(YEARS_ACTIVE <= 15)
seccion_B <- datos_potencial %>% filter(YEARS_ACTIVE > 15)
nrow(seccion_A)
## [1] 15
nrow(seccion_B)
## [1] 74
\[\ln(y) = \ln(a) + b \cdot x\]
modelo_exp_A <- lm(log(CUMULATIVE_PRODUCTION) ~ YEARS_ACTIVE, data = seccion_A)
b_A <- unname(coef(modelo_exp_A)[2])
a_A <- unname(exp(coef(modelo_exp_A)[1]))
plot(seccion_A$YEARS_ACTIVE, seccion_A$CUMULATIVE_PRODUCTION,
col = "#5b6b8c",
pch = 19,
cex = 1.2,
main = "Sección A: Años Activos ≤ 15 (modelo exponencial)",
xlab = "Años Activos (X)",
ylab = "Mediana de Producción Acumulada (Y)")
grid(col = "gray88")
curve(a_A * exp(b_A * x), add = TRUE, col = "#1b2a4a", lwd = 2)
legend("topleft",
legend = c("Datos reales", paste0("y = ", round(a_A, 2), " * e^(", round(b_A, 4), "x)")),
col = c("#5b6b8c", "#1b2a4a"),
pch = c(19, NA),
lty = c(NA, 1),
lwd = c(NA, 2),
bty = "n")
\[\ln(y) = \ln(a) + b \cdot x\]
modelo_exp_B <- lm(log(CUMULATIVE_PRODUCTION) ~ YEARS_ACTIVE, data = seccion_B)
b_B <- unname(coef(modelo_exp_B)[2])
a_B <- unname(exp(coef(modelo_exp_B)[1]))
plot(seccion_B$YEARS_ACTIVE, seccion_B$CUMULATIVE_PRODUCTION,
col = "#5b6b8c",
pch = 19,
cex = 1.2,
main = "Sección B: Años Activos > 15 (modelo exponencial)",
xlab = "Años Activos (X)",
ylab = "Mediana de Producción Acumulada (Y)")
grid(col = "gray88")
curve(a_B * exp(b_B * x), add = TRUE, col = "#1b2a4a", lwd = 2)
legend("topleft",
legend = c("Datos reales", paste0("y = ", round(a_B, 2), " * e^(", round(b_B, 4), "x)")),
col = c("#5b6b8c", "#1b2a4a"),
pch = c(19, NA),
lty = c(NA, 1),
lwd = c(NA, 2),
bty = "n")
El coeficiente r se calcula con cor(x, y)
sobre los datos originales (años activos vs. mediana de producción). El
R² mostrado corresponde al modelo lineal usado en el
paso 7 (modelo_log, sobre log(x) y
log(y)), de donde salen los parámetros a y
b.
r <- cor(datos_potencial$YEARS_ACTIVE, datos_potencial$CUMULATIVE_PRODUCTION)
r2 <- summary(modelo_log)$r.squared
resultado_test <- ifelse(abs(r) > 0.7, "Aceptado", "Rechazado")
tabla_test <- data.frame(
Test = "Correlación de Pearson (r = cor(x, y))",
`r` = round(r, 4),
`|r|` = round(abs(r), 4),
`R²` = round(r2, 4),
Criterio = "|r| > 0.7",
Resultado = resultado_test,
check.names = FALSE
)
kable(tabla_test, align = "lrrrrc") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
column_spec(6, bold = TRUE,
color = ifelse(resultado_test == "Aceptado", "#1b2a4a", "#6b6b6b"))
| Test | r | |r| | R² | Criterio | Resultado |
|---|---|---|---|---|---|
| Correlación de Pearson (r = cor(x, y)) | 0.8417 | 0.8417 | 0.8973 | |r| > 0.7 | Aceptado |
r_A <- cor(seccion_A$YEARS_ACTIVE, seccion_A$CUMULATIVE_PRODUCTION)
r2_A <- summary(modelo_exp_A)$r.squared
resultado_test_A <- ifelse(abs(r_A) > 0.7, "Aceptado", "Rechazado")
tabla_test_A <- data.frame(
Test = "Correlación de Pearson — Sección A (r = cor(x, y))",
`r` = round(r_A, 4),
`|r|` = round(abs(r_A), 4),
`R²` = round(r2_A, 4),
Criterio = "|r| > 0.7",
Resultado = resultado_test_A,
check.names = FALSE
)
kable(tabla_test_A, align = "lrrrrc") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
column_spec(6, bold = TRUE,
color = ifelse(resultado_test_A == "Aceptado", "#1b2a4a", "#6b6b6b"))
| Test | r | |r| | R² | Criterio | Resultado |
|---|---|---|---|---|---|
| Correlación de Pearson — Sección A (r = cor(x, y)) | 0.9809 | 0.9809 | 0.7691 | |r| > 0.7 | Aceptado |
r_B <- cor(seccion_B$YEARS_ACTIVE, seccion_B$CUMULATIVE_PRODUCTION)
r2_B <- summary(modelo_exp_B)$r.squared
resultado_test_B <- ifelse(abs(r_B) > 0.7, "Aceptado", "Rechazado")
tabla_test_B <- data.frame(
Test = "Correlación de Pearson — Sección B (r = cor(x, y))",
`r` = round(r_B, 4),
`|r|` = round(abs(r_B), 4),
`R²` = round(r2_B, 4),
Criterio = "|r| > 0.7",
Resultado = resultado_test_B,
check.names = FALSE
)
kable(tabla_test_B, align = "lrrrrc") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
column_spec(6, bold = TRUE,
color = ifelse(resultado_test_B == "Aceptado", "#1b2a4a", "#6b6b6b"))
| Test | r | |r| | R² | Criterio | Resultado |
|---|---|---|---|---|---|
| Correlación de Pearson — Sección B (r = cor(x, y)) | 0.8104 | 0.8104 | 0.7479 | |r| > 0.7 | Aceptado |
nuevos_anios <- c(5, 10, 15, 20, 25, 30)
estimaciones <- data.frame(
YEARS_ACTIVE = nuevos_anios,
Produccion_Estimada = a * nuevos_anios^b
)
kable(estimaciones, digits = 2, format.args = list(big.mark = ","),
col.names = c("Años Activos", "Producción Acumulada Estimada"),
align = "lr") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
| Años Activos | Producción Acumulada Estimada |
|---|---|
| 5 | 8,999.50 |
| 10 | 21,908.41 |
| 15 | 36,866.83 |
| 20 | 53,333.88 |
| 25 | 71,022.14 |
| 30 | 89,748.71 |
Entre los años activos y la producción acumulada existe una relación de tipo potencial, cuya ecuación matemática es
\[y = 1140.363 \cdot x^{1.284}\]
siendo y la producción acumulada y x los años activos, y donde el modelo es válido para x > 0 (años activos positivos), rango en el que fue ajustado.
Cuando los años activos son de 45, se espera una producción acumulada de 151,026.5.
La producción acumulada está influenciada en un 89.7% por los años activos, y en un 10.3% por otros factores.
El test de Pearson sobre los datos originales (r = 0.842) fue Aceptado.