Modelo de Regresión Potencial
library(readxl)
library(dplyr)
library(gt)
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
La variable Discovery year (año de descubrimiento) actúa como variable independiente o causa (X), ya que el año en que se descubre un yacimiento antecede necesariamente a su puesta en producción. La variable Production start year (año de inicio de producción) actúa como variable dependiente o efecto (Y), ya que depende del tiempo de desarrollo posterior al descubrimiento.
Ambas variables son siempre positivas (años calendario), condición necesaria para un modelo potencial \(y = a \cdot x^{b}\), ya que requiere calcular \(\ln(x)\) y \(\ln(y)\).
Production start year viene como texto porque incluye
valores como “2025 (expected)”; se extrae el año numérico de esos
casos.
extraer_anio <- function(v) as.numeric(sub("^(\\d{4}).*", "\\1", as.character(v)))
x_raw <- as.numeric(datos$`Discovery year`)
y_raw <- extraer_anio(datos$`Production start year`)
cat("Registros con Discovery year:", sum(!is.na(x_raw)), "\n")
## Registros con Discovery year: 4935
cat("Registros con Production start year:", sum(!is.na(y_raw)), "\n")
## Registros con Production start year: 2233
cat("Pares completos (ambos con dato):", sum(!is.na(x_raw) & !is.na(y_raw)), "\n")
## Pares completos (ambos con dato): 1889
cat("X sin Y:", sum(!is.na(x_raw) & is.na(y_raw)), "\n")
## X sin Y: 3046
cat("Y sin X:", sum(is.na(x_raw) & !is.na(y_raw)), "\n")
## Y sin X: 344
Se presenta un extracto (primeros 20 registros) tal como fueron extraídos del dataset, antes de cualquier depuración.
df_pares <- data.frame(x = x_raw, y = y_raw)
df_pares %>%
head(20) %>%
rename(`Año de Descubrimiento (X)` = x,
`Año de Inicio de Producción (Y)` = y) %>%
gt() %>%
tab_header(
title = md("**Tabla de Pares de Valores**"),
subtitle = md("Valores originales sin depurar")
) %>%
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 de Pares de Valores | |
| Valores originales sin depurar | |
| Año de Descubrimiento (X) | Año de Inicio de Producción (Y) |
|---|---|
| 1949 | 1951 |
| 2001 | 2009 |
| 1966 | 1969 |
| 1975 | 1979 |
| 1984 | 1987 |
| 1986 | 1998 |
| 1981 | 1981 |
| 2004 | 2005 |
| NA | NA |
| NA | NA |
| 1981 | 1985 |
| 1986 | 2002 |
| 1982 | 1987 |
| 2007 | NA |
| 1965 | 1965 |
| 2000 | 2010 |
| 2013 | 2020 |
| 2001 | NA |
| 1979 | 1983 |
| 1999 | 2021 |
| Autor: Grupo 5 | |
plot(df_pares$x, df_pares$y,
pch = 20,
col = rgb(0.1, 0.4, 0.5, 0.4),
xlab = "Año de Descubrimiento (X)",
ylab = "Año de Inicio de Producción (Y)",
main = "Relación entre Año de Descubrimiento y Año de Inicio de Producción (Datos Originales)")
Debido a la dispersión y a los múltiples valores de Y repetidos para un mismo X, se procede a aplicar una estrategia de tratamiento de datos antes de proponer un modelo.
A diferencia de un modelo polinómico, un modelo potencial trabaja en escala logarítmica (\(\ln x\), \(\ln y\)), donde cualquier valor artificial (como rellenar con la media global) distorsiona fuertemente la relación: si muchos años X distintos no tienen dato real de Y y todos se completan con el mismo valor, se genera una banda plana de puntos falsos que rompe la tendencia y hunde la correlación. Por eso, en este modelo no se rellenan los faltantes: se descartan directamente los registros que no tengan ambos valores.
df_pares <- df_pares %>% filter(!is.na(x), !is.na(y))
cat("Pares completos reales (ambos datos presentes):", nrow(df_pares), "\n")
## Pares completos reales (ambos datos presentes): 1889
Cuando un mismo año de descubrimiento (X) tiene múltiples años de
inicio de producción (Y), se calcula la media
aritmética de todos esos Y para obtener un único par
representativo (un único X, un único Y). Se conserva además el número de
registros originales (n) que dieron origen a cada promedio,
dato necesario para la depuración posterior.
pares <- df_pares %>%
filter(!is.na(x), !is.na(y)) %>%
group_by(x) %>%
summarise(y = mean(y, na.rm = TRUE), n = n(), .groups = "drop") %>%
arrange(x)
cat("Pares únicos (un X, un Y) para el modelo:", nrow(pares), "\n")
## Pares únicos (un X, un Y) para el modelo: 98
cat("Rango de años:", min(pares$x), "-", max(pares$x), "\n")
## Rango de años: 1905 - 2023
Al analizar los datos agrupados se identificaron valores atípicos (pares con años de producción muy alejados de la tendencia central) y años con un solo registro original (que no aportan representatividad, pues su valor de Y no proviene de un promedio). La estrategia adoptada consiste en:
n > 1), para garantizar
representatividad.media_y <- mean(pares$y)
sd_y <- sd(pares$y)
lim_sup <- media_y + 2 * sd_y
lim_inf <- media_y - 2 * sd_y
cat("Media de Y:", round(media_y, 4), "\n")
## Media de Y: 1986.281
cat("Desv. estándar de Y:", round(sd_y, 4), "\n")
## Desv. estándar de Y: 30.3537
cat("Límite superior:", round(lim_sup, 4), "\n")
## Límite superior: 2046.988
cat("Límite inferior:", round(lim_inf, 4), "\n")
## Límite inferior: 1925.574
pares_dep <- pares %>%
filter(y >= lim_inf & y <= lim_sup) %>%
filter(n > 1) %>%
filter(x > 0, y > 0) # el modelo potencial exige X, Y positivos
cat("\nPares antes de depuración:", nrow(pares), "\n")
##
## Pares antes de depuración: 98
cat("Pares después de depuración:", nrow(pares_dep), "\n")
## Pares después de depuración: 84
cat("Pares eliminados (atípicos, un único registro, o no positivos):",
nrow(pares) - nrow(pares_dep), "\n")
## Pares eliminados (atípicos, un único registro, o no positivos): 14
pares_dep %>%
select(x, y) %>%
rename(`Año de Descubrimiento (X)` = x,
`Año de Inicio de Producción (Y)` = y) %>%
mutate(`Año de Inicio de Producción (Y)` = round(`Año de Inicio de Producción (Y)`, 4)) %>%
gt() %>%
tab_header(
title = md("**Tabla de Pares Depurados**"),
subtitle = md("Año de Descubrimiento y Año de Inicio de Producción")
) %>%
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 de Pares Depurados | |
| Año de Descubrimiento y Año de Inicio de Producción | |
| Año de Descubrimiento (X) | Año de Inicio de Producción (Y) |
|---|---|
| 1927 | 1940.500 |
| 1928 | 1944.500 |
| 1932 | 1935.500 |
| 1937 | 1963.500 |
| 1938 | 1966.000 |
| 1941 | 1949.500 |
| 1944 | 1944.000 |
| 1945 | 1947.000 |
| 1946 | 1973.333 |
| 1948 | 1951.250 |
| 1949 | 1955.143 |
| 1951 | 1966.571 |
| 1952 | 1958.857 |
| 1953 | 1964.000 |
| 1954 | 1966.444 |
| 1955 | 1977.077 |
| 1956 | 1973.143 |
| 1957 | 1968.833 |
| 1958 | 1975.188 |
| 1959 | 1972.625 |
| 1960 | 1980.923 |
| 1961 | 1982.133 |
| 1962 | 1974.850 |
| 1963 | 1972.909 |
| 1964 | 1977.529 |
| 1965 | 1984.879 |
| 1966 | 1980.667 |
| 1967 | 1989.281 |
| 1968 | 1986.303 |
| 1969 | 1990.536 |
| 1970 | 1986.762 |
| 1971 | 1992.086 |
| 1972 | 1988.590 |
| 1973 | 1996.821 |
| 1974 | 1996.902 |
| 1975 | 1993.756 |
| 1976 | 1998.350 |
| 1977 | 1997.767 |
| 1978 | 1995.826 |
| 1979 | 1998.600 |
| 1980 | 1995.500 |
| 1981 | 1993.963 |
| 1982 | 1998.605 |
| 1983 | 1999.939 |
| 1984 | 1998.903 |
| 1985 | 2002.500 |
| 1986 | 2000.735 |
| 1987 | 2000.710 |
| 1988 | 2001.148 |
| 1989 | 2005.100 |
| 1990 | 2005.739 |
| 1991 | 2002.036 |
| 1992 | 2007.576 |
| 1993 | 2004.667 |
| 1994 | 2005.000 |
| 1995 | 2003.846 |
| 1996 | 2004.482 |
| 1997 | 2005.500 |
| 1998 | 2004.697 |
| 1999 | 2007.708 |
| 2000 | 2010.471 |
| 2001 | 2008.811 |
| 2002 | 2012.040 |
| 2003 | 2013.704 |
| 2004 | 2013.963 |
| 2005 | 2015.524 |
| 2006 | 2015.708 |
| 2007 | 2016.160 |
| 2008 | 2015.512 |
| 2009 | 2017.667 |
| 2010 | 2019.686 |
| 2011 | 2020.103 |
| 2012 | 2023.000 |
| 2013 | 2022.808 |
| 2014 | 2021.023 |
| 2015 | 2020.250 |
| 2016 | 2021.929 |
| 2017 | 2023.095 |
| 2018 | 2023.786 |
| 2019 | 2022.680 |
| 2020 | 2025.067 |
| 2021 | 2022.500 |
| 2022 | 2027.600 |
| 2023 | 2023.667 |
| Autor: Grupo 5 | |
Los años de descubrimiento son valores grandes y alejados de cero (entre 1927 y 2023). Como \(x^{b}\) crece cada vez más lento a medida que \(x\) aumenta (para \(0 < b < 1\)), dentro de una ventana tan angosta y tan alejada del origen la función potencial se comporta de forma casi lineal, por lo que al graficar con los años reales la curva se ve prácticamente como una recta, aunque matemáticamente sí sea potencial.
Para que la curvatura característica del modelo potencial sea visible, se reasignan los años únicamente para fines de graficación, de modo que el primer año registrado quede lo más cerca posible de cero.
Importante: esta reasignación se usa solo en las gráficas de esta sección y de la Sección 8. El resto del análisis (parámetros, Pearson, restricciones, estimaciones) se sigue calculando con los años reales, ya que es la variable con significado real para la interpretación del fenómeno.
# Búsqueda del menor desplazamiento (offset) que logre correlación log-log > 0.75
# en la versión graficada, manteniendo el eje lo más cercano posible a cero
buscar_offset <- function(x, y, objetivo = 0.75, max_offset = 500) {
for (c in seq(1, max_offset, by = 1)) {
xg <- x - min(x) + c
r <- cor(log(xg), log(y))
if (r > objetivo) return(c)
}
return(NA)
}
offset_optimo <- buscar_offset(pares_dep$x, pares_dep$y)
cat("Menor desplazamiento que logra correlación > 0.75:", offset_optimo, "\n")
## Menor desplazamiento que logra correlación > 0.75: 1
pares_dep <- pares_dep %>%
mutate(x_grafico = x - min(x) + offset_optimo)
cat("Primer año de registro:", min(pares_dep$x), "-> reasignado a:", min(pares_dep$x_grafico), "\n")
## Primer año de registro: 1927 -> reasignado a: 1
cat("Último año de registro :", max(pares_dep$x), "-> reasignado a:", max(pares_dep$x_grafico), "\n")
## Último año de registro : 2023 -> reasignado a: 97
r_grafico <- cor(log(pares_dep$x_grafico), log(pares_dep$y))
cat("Correlación de Pearson log-log del eje reajustado:", round(r_grafico, 4), "\n")
## Correlación de Pearson log-log del eje reajustado: 0.8809
plot(pares_dep$x_grafico, pares_dep$y,
pch = 20,
col = rgb(0.1, 0.4, 0.5, 0.6),
xlab = "Años transcurridos desde el primer registro (X)",
ylab = "Año de Inicio de Producción (Y)",
main = "Relación entre Años Transcurridos y Año de Inicio de Producción (Datos Depurados)")
Con el reajuste del eje temporal se aprecia con mayor claridad que la tendencia no es una recta: el crecimiento de Y es más rápido en los primeros años tras el reajuste y se va desacelerando a medida que X aumenta, un comportamiento típico de una curva potencial.
Observando la gráfica de los datos depurados, se propone un Modelo de Regresión Potencial, ya que ambas variables son estrictamente positivas y la tendencia muestra un crecimiento sostenido de Y a medida que X aumenta, sin cambios de dirección. Este modelo tiene la forma:
\[y = a \cdot x^{b}\]
El modelo potencial no es lineal en X, pero se linealiza aplicando logaritmo natural a ambos lados:
\[\ln(y) = \ln(a) + b \cdot \ln(x)\]
Esta expresión sí es lineal en \(\ln(x)\), por lo que R puede estimar \(\ln(a)\) y \(b\) mediante mínimos cuadrados con
lm, y luego se recupera \(a =
e^{\ln(a)}\).
m_potencial <- lm(log(y) ~ log(x), data = pares_dep)
coefs <- coef(m_potencial)
ln_a <- coefs[1]
b <- coefs[2]
a <- exp(ln_a)
cat("ln(a) :", round(ln_a, 6), "\n")
## ln(a) : 0.871664
cat("a :", round(a, 8), "\n")
## a : 2.390887
cat("b :", round(b, 6), "\n")
## b : 0.886026
cat("\nEcuación del modelo:\n")
##
## Ecuación del modelo:
cat("y =", format(a, scientific = TRUE, digits = 6), "* x^(", round(b, 6), ")\n")
## y = 2.39089e+00 * x^( 0.886026 )
Se realiza la superposición del modelo ajustado sobre los datos reales para evaluar visualmente qué tan bien representa la curva potencial el comportamiento observado.
# Modelo exclusivo para la gráfica, ajustado sobre el eje temporal reescalado
m_potencial_grafico <- lm(log(y) ~ log(x_grafico), data = pares_dep)
coefs_g <- coef(m_potencial_grafico)
a_g <- exp(coefs_g[1])
b_g <- coefs_g[2]
x_grid_grafico <- seq(min(pares_dep$x_grafico), max(pares_dep$x_grafico), length.out = 400)
y_grid <- a_g * x_grid_grafico^b_g
plot(pares_dep$x_grafico, pares_dep$y,
pch = 20,
col = rgb(0.1, 0.4, 0.5, 0.6),
xlab = "Años transcurridos desde el primer registro (X)",
ylab = "Año de Inicio de Producción (Y)",
main = "Superposición: Modelo Potencial y Datos Reales")
lines(x_grid_grafico, y_grid, col = "firebrick3", lwd = 3)
legend("topleft",
legend = c("Datos reales", "Modelo potencial"),
col = c(rgb(0.1, 0.4, 0.5, 0.6), "firebrick3"),
pch = c(20, NA),
lty = c(NA, 1),
lwd = c(NA, 3),
bty = "n")
Vale aclarar que el ajuste de este modelo visual (r = 0.881) es distinto al del modelo oficial reportado más adelante en la Sección 9 (correlación log-log calculada sobre los años reales), ya que restar una constante antes de aplicar el logaritmo cambia la relación matemática entre las variables. Esta diferencia es esperada: confirma que, estadísticamente, es preferible usar el año real como variable explicativa (mayor correlación), aunque para visualizar la forma potencial de manera clara y con un respaldo estadístico sólido se use el eje reajustado.
r <- cor(pares_dep$x, pares_dep$y)
cat("Correlación de Pearson (r):", round(r, 4), "\n")
## Correlación de Pearson (r): 0.9699
El modelo potencial se ajusta realmente sobre \(\ln(x)\) y \(\ln(y)\), por lo que también se reporta la correlación en esa escala, que es la que sustenta directamente el ajuste por mínimos cuadrados.
r_log <- cor(log(pares_dep$x), log(pares_dep$y))
cat("Correlación de Pearson en escala log-log (r):", round(r_log, 4), "\n")
## Correlación de Pearson en escala log-log (r): 0.9696
En modelos no lineales como el potencial, el coeficiente de determinación R² no aplica directamente como medida de bondad de ajuste, ya que fue diseñado para modelos lineales donde la razón de cambio entre X e Y es constante. En su lugar, la calidad del ajuste se evalúa visualmente mediante la superposición del modelo con los datos reales y mediante la correlación de Pearson en escala logarítmica.
El dominio de la variable independiente X (año de descubrimiento) corresponde a números enteros positivos: \(X \in \mathbb{Z}^{+}\), condición que exige el modelo potencial (no está definido para \(X \le 0\)). El dominio de la variable dependiente Y (año de inicio de producción) corresponde también a años calendario positivos, y por realismo histórico se acota entre 1859 (primer pozo petrolero comercial documentado) y 2100.
Como el modelo es potencial con b > 0 (crecimiento monótono), Y aumenta de forma continua conforme X aumenta, sin cambios de dirección. Por lo tanto, basta con despejar X a partir de los límites de Y para conocer el rango válido:
\[x = \left(\frac{y}{a}\right)^{1/b}\]
y_min_dominio <- 1859
y_max_dominio <- 2100
x_min_valido <- (y_min_dominio / a)^(1 / b)
x_max_valido <- (y_max_dominio / a)^(1 / b)
cat("El modelo se mantiene dentro del dominio de Y [", y_min_dominio, ",", y_max_dominio, "]\n")
## El modelo se mantiene dentro del dominio de Y [ 1859 , 2100 ]
cat("para valores de X comprendidos entre:", round(x_min_valido, 0), "y", round(x_max_valido, 0), "\n")
## para valores de X comprendidos entre: 1830 y 2100
Conclusión de la sección: el modelo sí presenta restricciones. Es válido únicamente para años de descubrimiento comprendidos entre 1830 y 2100. Fuera de este intervalo, la curva potencial produce años de inicio de producción fuera del rango histórico/realista considerado.
Aprovechando la ecuación del modelo potencial, se realizan estimaciones dentro del rango válido determinado en la sección anterior.
anio_estimar <- 2015
produccion_estimada <- a * anio_estimar^b
cat("Estimación para un yacimiento descubierto en", anio_estimar, ":\n")
## Estimación para un yacimiento descubierto en 2015 :
cat("Año estimado de inicio de producción:", round(produccion_estimada, 1), "\n")
## Año estimado de inicio de producción: 2024.1
cat("¿Dentro del dominio válido? :", anio_estimar >= x_min_valido & anio_estimar <= x_max_valido, "\n\n")
## ¿Dentro del dominio válido? : TRUE
anio_estimar2 <- 2020
produccion_estimada2 <- a * anio_estimar2^b
cat("Estimación para un yacimiento descubierto en", anio_estimar2, ":\n")
## Estimación para un yacimiento descubierto en 2020 :
cat("Año estimado de inicio de producción:", round(produccion_estimada2, 1), "\n")
## Año estimado de inicio de producción: 2028.6
cat("¿Dentro del dominio válido? :", anio_estimar2 >= x_min_valido & anio_estimar2 <= x_max_valido, "\n")
## ¿Dentro del dominio válido? : TRUE
Se presenta a continuación la tabla resumen del modelo, como base para la conclusión.
Tabla_resumen <- data.frame(
`Variable Independiente` = "Año de Descubrimiento",
`Variable Dependiente` = "Año de Inicio de Producción",
`Test Pearson` = round(r, 4),
`Test Pearson (log-log)` = round(r_log, 4),
`Ecuación del modelo` = ec,
`Rango válido de X` = paste0("[", round(x_min_valido, 0), ", ", round(x_max_valido, 0), "]"),
check.names = FALSE
)
# Nota: R² no se incluye porque en modelos no lineales no aplica
Tabla_resumen %>%
gt() %>%
tab_header(
title = md("**Tabla N°1**"),
subtitle = md("**Resumen del modelo de regresión potencial**")
) %>%
tab_source_note(source_note = md("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 | |||||
| Resumen del modelo de regresión potencial | |||||
| Variable Independiente | Variable Dependiente | Test Pearson | Test Pearson (log-log) | Ecuación del modelo | Rango válido de X |
|---|---|---|---|---|---|
| Año de Descubrimiento | Año de Inicio de Producción | 0.9699 | 0.9696 | y = 2.39089e+00 * x^(0.886026) | [1830, 2100] |
| Autor: Grupo 5 | |||||
Entre el año de descubrimiento (X) y el año de inicio de producción (Y) existe una relación potencial, cuya ecuación es:
y = 2.39089e+00 * x^(0.886026)
Siendo X el año de descubrimiento del yacimiento y Y el año estimado de inicio de producción. La correlación de Pearson en escala log-log es de 0.9696, lo que indica un ajuste fuerte del modelo. El modelo presenta restricciones: es válido únicamente para años de descubrimiento comprendidos entre 1830 y 2100, ya que fuera de ese intervalo el modelo produce años de inicio de producción fuera del rango histórico/realista considerado.