library(readr)
library(dplyr)
library(ggplot2)
library(gt)
library(stringr)
library(DT)
library(knitr)
library(kableExtra)
cat("Librerías cargadas: readr, dplyr, ggplot2, gt, stringr, DT, knitr, kableExtra")Librerías cargadas: readr, dplyr, ggplot2, gt, stringr, DT, knitr, kableExtra
ruta_archivo <- file.choose()
datos <- read_csv(ruta_archivo, show_col_types = FALSE)
# Rellenamiento de celdas faltantes con la mediana de cada variable
if (any(is.na(datos$TOWNSHIP))) {
datos$TOWNSHIP[is.na(datos$TOWNSHIP)] <-
median(datos$TOWNSHIP, na.rm = TRUE)
}
if (any(is.na(datos$LATITUDE))) {
datos$LATITUDE[is.na(datos$LATITUDE)] <-
median(datos$LATITUDE, na.rm = TRUE)
}
# Se descartan registros con valores no positivos
datos <- datos %>%
filter(TOWNSHIP > 0, LATITUDE > 0)
str(datos[, c("TOWNSHIP", "LATITUDE")])tibble [47,757 × 2] (S3: tbl_df/tbl/data.frame)
$ TOWNSHIP: num [1:47757] 33 15 29 26 33 17 30 26 23 16 ...
$ LATITUDE: num [1:47757] 37.1 38.8 37.5 37.8 37.1 ...
Variable Dependiente (Y): Latitud Geográfica. Se seleccionó como variable dependiente porque representa la ubicación geográfica absoluta de cada arrendamiento medida en grados decimales. Es el resultado que se desea analizar y explicar a partir de otra variable.
Variable Independiente (X): Township. Se eligió como variable independiente porque representa la posición norte-sur de cada arrendamiento dentro del sistema de agrimensura rectangular (PLSS) de Kansas. En general, a mayor número de Township, mayor es el desplazamiento hacia el sur del arrendamiento — cada unidad equivale aproximadamente a 6 millas — por lo que se espera que esta variable influya directamente sobre la latitud geográfica.
La siguiente tabla contiene todos los 47757 registros del conjunto, mostrando los valores de Township y Latitud de cada arrendamiento.
datatable(
datos %>% select(TOWNSHIP, LATITUDE) %>% rename("Township (X)" = TOWNSHIP, "Latitud (Y)" = LATITUDE),
caption = htmltools::tags$caption(
style = "caption-side: top; text-align: left; font-size: 16px;
font-weight: 700; color:#1F2A33;",
"Tabla N\u00b01: Todos los valores \u2014 Township y Latitud Geogr\u00e1fica"
),
rownames = FALSE,
class = "display compact stripe hover",
options = list(
pageLength = 10,
dom = "ltip",
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
) %>%
formatRound(columns = c("Latitud (Y)"), digits = 4)La nube de puntos visualizada a continuación no permite conjeturar un modelo con claridad, por esta razón se optó por realizar una estrategia para depurar los datos y obtener un gráfico más limpio.
par(mar = c(5, 5, 4, 2))
plot(datos$TOWNSHIP, datos$LATITUDE,
pch = 16, cex = 0.35,
col = adjustcolor("#2E86AB", alpha.f = 0.15),
xlab = "X (Township)",
ylab = "Y (Latitud, grados decimales)",
main = "Nube de puntos (todos los valores, sin agrupar)",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
box()Estrategia:
tabla_xy <- datos %>%
mutate(percentil = ntile(TOWNSHIP, 25)) %>%
group_by(percentil) %>%
summarise(
n_pozos = n(),
x_mediana = median(TOWNSHIP),
y_mediana = median(LATITUDE),
.groups = "drop"
) %>%
arrange(percentil)
cat("Total de pares (x\u0303, y\u0303) obtenidos, uno por percentil:", nrow(tabla_xy), "\n")Total de pares (x̃, ỹ) obtenidos, uno por percentil: 25
datatable(
tabla_xy %>% select(x_mediana, y_mediana) %>%
rename("Township (X)" = x_mediana, "Mediana de Latitud (Y)" = y_mediana),
caption = htmltools::tags$caption(
style = "caption-side: top; text-align: left; font-size: 16px;
font-weight: 700; color:#1F2A33;",
"Tabla N\u00b02: Pares (x\u0303, y\u0303) \u2014 Mediana de Latitud Geogr\u00e1fica por Percentil de Township"
),
rownames = FALSE,
class = "display compact stripe hover",
options = list(
pageLength = 10,
dom = "ltip",
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
) %>%
formatRound(columns = c("Mediana de Latitud (Y)"), digits = 4)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)
data.frame(
Variable = c("TOWNSHIP (X)", "LATITUDE (Y)"),
Minimo = round(c(min_x, min_y), 4),
Maximo = round(c(max_x, max_y), 4),
Rango = round(c(max_x - min_x, max_y - min_y), 4),
Mediana = round(c(median(tabla_xy$x_mediana),
median(tabla_xy$y_mediana)), 4)
) %>%
gt() %>%
tab_header(
title = md("**Tabla N\u00b02: Resumen General de las Variables (pares x\u0303, y\u0303)**")
) %>%
tab_source_note(source_note = "Autor: Leslye Quinchiguango") %>%
cols_align(align = "center", everything())| Tabla N°2: Resumen General de las Variables (pares x̃, ỹ) | ||||
| Variable | Minimo | Maximo | Rango | Mediana |
|---|---|---|---|---|
| TOWNSHIP (X) | 4.0000 | 35.000 | 31.0000 | 25.0000 |
| LATITUDE (Y) | 37.0236 | 39.735 | 2.7114 | 37.8802 |
| Autor: Leslye Quinchiguango | ||||
Con los datos resumidos por Township mediante la mediana, la tendencia logarítmica decreciente se aprecia con mayor claridad.
par(mar = c(5, 5, 4, 2))
plot(tabla_xy$x_mediana, tabla_xy$y_mediana,
pch = 19, col = "#2E86AB",
xlab = "X\u0303 (Township)",
ylab = "Y\u0303 (Mediana Latitud, grados decimales)",
main = "Producci\u00f3n acumulada en funci\u00f3n de los a\u00f1os activos",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
box()La nube de puntos muestra una tendencia decreciente: al aumentar el número de Township la Latitud disminuye progresivamente. Aunque la curvatura no es evidente a simple vista — debido a que el rango de Township en Kansas (1–35) es estrecho — la tasa de descenso es mayor en los primeros townships y se aplana hacia los valores más altos, comportamiento inherente al sistema PLSS por la curvatura de la Tierra. Por lo anterior, se conjetura el modelo:
\[y = a + b \cdot \ln(x)\]
con pendiente \(b < 0\) (relación inversamente proporcional a tasa decreciente).
El modelo se ajusta sobre los pares (x̃, ỹ) por percentil (Tabla N°1). El uso de la mediana por percentil en lugar de los 47757 registros crudos reduce la influencia de coordenadas con errores de georreferenciación y permite capturar la tendencia central de la relación geográfica.
x <- tabla_xy$x_mediana
y <- tabla_xy$y_mediana
modelo <- lm(y ~ log(x))
a <- coef(modelo)[1]
b <- coef(modelo)[2]
cat("Modelo ajustado: y =", round(a, 4), "+", round(b, 4), "* ln(x)\n")Modelo ajustado: y = 42.3318 + -1.4171 * ln(x)
Call:
lm(formula = y ~ log(x))
Residuals:
Min 1Q Median 3Q Max
-0.63229 -0.14343 -0.00274 0.19019 0.27773
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 42.33180 0.27590 153.43 < 0.0000000000000002 ***
log(x) -1.41708 0.08932 -15.87 0.0000000000000702 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.2268 on 23 degrees of freedom
Multiple R-squared: 0.9163, Adjusted R-squared: 0.9126
F-statistic: 251.7 on 1 and 23 DF, p-value: 0.00000000000007021
x_seq <- seq(min(x), max(x), length.out = 500)
pred <- predict(modelo,
newdata = data.frame(x = x_seq),
interval = "confidence",
level = 0.95)
par(mar = c(5, 5, 4, 2))
plot(x, y,
pch = 19, col = "#2E86AB",
xlab = "X\u0303 (Mediana Township)",
ylab = "Y\u0303 (Mediana Latitud, grados decimales)",
main = "Gr\u00e1fica N\u00b03: Sobreponer Modelo con la Realidad \u2014 Pares (x\u0303, y\u0303)",
cex.main = 0.9, frame.plot = FALSE)
grid(nx = NULL, ny = NULL, col = "#D7DBDD", lty = "dotted")
# Banda de confianza al 95%
polygon(c(x_seq, rev(x_seq)),
c(pred[, "lwr"], rev(pred[, "upr"])),
col = rgb(0.5, 0.5, 0.5, 0.2),
border = NA)
# Curva ajustada
lines(x_seq, pred[, "fit"], col = "#E74C3C", lwd = 3)
legend("topright",
legend = c("Datos (x\u0303, y\u0303)",
"Modelo Logar\u00edtmico",
"I.C. 95%"),
col = c("#2E86AB", "#E74C3C", "gray"),
pch = c(16, NA, 15),
lwd = c(NA, 3, NA),
pt.cex = c(1, NA, 2),
bty = "n")
box()La curva logarítmica sigue de cerca la dirección de los puntos, ajustándose a los pares (x̃, ỹ) y confirmando la relación logarítmica decreciente entre el número de Township y la Latitud Geográfica.
El coeficiente de correlación de Pearson, calculado sobre el modelo linealizado \(\ln(x)\), debe superar 0.7 en valor absoluto para aceptar el modelo logarítmico. Se evalúa sobre los pares (x̃, ỹ) por percentil.
r_medianas <- cor.test(log(tabla_xy$x_mediana), tabla_xy$y_mediana)
data.frame(
Conjunto = c("Pares (x\u0303, y\u0303) por percentil"),
r = round(c(r_medianas$estimate), 4),
Supera_0.7 = c(abs(r_medianas$estimate) > 0.7)
) %>%
gt() %>%
tab_header(
title = md("**Tabla N\u00b03: Test de Bondad de Ajuste**"),
subtitle = "Umbral |r| > 0.7"
) %>%
tab_source_note(source_note = "Autor: Leslye Quinchiguango") %>%
cols_align(align = "center", everything())| Tabla N°3: Test de Bondad de Ajuste | ||
| Umbral |r| > 0.7 | ||
| Conjunto | r | Supera_0.7 |
|---|---|---|
| Pares (x̃, ỹ) por percentil | -0.9572 | TRUE |
| Autor: Leslye Quinchiguango | ||
Sobre los pares (x̃, ỹ), \(r =\) -0.957, por encima del umbral de 0.7, por lo que el modelo logarítmico se acepta para describir la tendencia central de la relación entre el Township y la Latitud Geográfica.
El modelo \(y = a + b \cdot \ln(x)\) con \(b < 0\) impone restricciones matemáticas y geográficas que se sintetizan en la siguiente tabla:
x_max_valido <- exp((-90 - a) / b) # Township máximo para y = -90°
tabla_restricciones <- data.frame(
Variable = c("X (TOWNSHIP)", "Y (LATITUDE)"),
Dominio = c("x ∈ ℤ⁺",
"-90° ≤ y ≤ 90°"),
Rango_valido = c("1 \u2264 x \u2264 3.60e+40",
"-90° ≤ y ≤ 90°"),
Rango_invalido = c("0 \u2264 x < 3.60e+40",
"-90° < y < 90°")
)
kable(tabla_restricciones,
col.names = c("Variable", "Dominio", "Rango válido", "Rango inválido"),
align = "lccc", escape = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE, position = "center", font_size = 14) %>%
column_spec(1, bold = TRUE, width = "5cm") %>%
column_spec(2, width = "5cm") %>%
column_spec(3, width = "5cm") %>%
column_spec(4, width = "5cm") %>%
row_spec(0, bold = TRUE, background = "#f2f2f2")| Variable | Dominio | Rango válido | Rango inválido |
|---|---|---|---|
| X (TOWNSHIP) | x ∈ ℤ⁺ | 1 ≤ x ≤ 3.60e+40 | 0 ≤ x < 3.60e+40 |
| Y (LATITUDE) | -90° ≤ y ≤ 90° | -90° ≤ y ≤ 90° | -90° < y < 90° |
La condición \(x > 0\) es matemáticamente necesaria para que \(\ln(x)\) esté definido; como Township toma valores enteros positivos (\(x \geq 1\)), esta condición siempre se cumple. El rango válido de X se extiende hasta \(3.59 \times 10^{40}\), valor a partir del cual la latitud predicha caería por debajo de \(-90°\), superando el límite geográfico terrestre. La latitud Y se mantiene dentro de su dominio \([-90°, 90°]\) para cualquier Township dentro del rango válido.
x_est <- round(median(tabla_xy$x_mediana), 1)
y_est <- a + b * log(x_est)
if (b >= 0) {
ecuacion <- paste0("y = ", round(a, 4), " + ", round(b, 4), " \u00b7 ln(x)")
} else {
ecuacion <- paste0("y = ", round(a, 4), " - ", abs(round(b, 4)), " \u00b7 ln(x)")
}
data.frame(
Ecuacion_del_Modelo = ecuacion,
X_estimado_township = x_est,
Y_estimado_latitud_grados = round(y_est, 4)
) %>%
gt() %>%
tab_header(
title = md("**Tabla N\u00b04: Estimaci\u00f3n Puntual de Latitud Geogr\u00e1fica**")
) %>%
tab_source_note(source_note = "Autor: Leslye Quinchiguango") %>%
cols_align(align = "center", everything())| Tabla N°4: Estimación Puntual de Latitud Geográfica | ||
| Ecuacion_del_Modelo | X_estimado_township | Y_estimado_latitud_grados |
|---|---|---|
| y = 42.3318 - 1.4171 · ln(x) | 25 | 37.7704 |
| Autor: Leslye Quinchiguango | ||
Para un arrendamiento ubicado en el Township 25 (mediana del conjunto analizado), el modelo estima una latitud geográfica de aproximadamente 37.7704° decimales.
Entre el Township (X) y la Latitud Geográfica (Y) existe una relación de tipo logarítmica decreciente cuya ecuación matemática es:
\[y = 42.3318 - 1.4171 · ln(x)\]
Siendo X el número de Township dentro del sistema de agrimensura rectangular PLSS de Kansas, e Y la latitud geográfica del arrendamiento medida en grados decimales. Se evidencia una relación logarítmica negativa de alta intensidad entre las variables, consistente con el desplazamiento progresivo hacia el sur que representa cada unidad adicional de Township dentro del sistema PLSS.
Autor: Leslye Quinchiguango — Análisis Estadístico, Kansas Hydrocarbon Leases Dataset