library(readxl)
library(dplyr)
library(tidyr)
library(gt)
library(ggplot2)
library(scales)
library(forcats)
library(MASS) # Fundamental para el ajuste de distribuciones (fitdistr)
datos <- read_excel("dataset_mundial_petro.xlsx")
cat("Número de registros:", nrow(datos), "\n")
## Número de registros: 49212
cat("Número de variables:", ncol(datos), "\n")
## Número de variables: 32
La variable Longitude indica la coordenada geográfica de longitud de cada yacimiento. Es una variable cuantitativa continua, cuyos valores van desde coordenadas negativas (Hemisferio Occidental) hasta positivas (Hemisferio Oriental). Se excluyen los valores faltantes (NA) y, por su naturaleza bimodal ligada al hemisferio, se le aplica un tratamiento analítico segmentado.
n_total <- nrow(datos)
Variable <- na.omit(as.numeric(datos$Longitude))
n <- length(Variable)
cat("Registros excluidos por NA:", n_total - n, "\n")
## Registros excluidos por NA: 41675
cat("Número de registros válidos (n):", n, "\n")
## Número de registros válidos (n): 7537
cat("Valor mínimo:", round(min(Variable), 3), "\n")
## Valor mínimo: -152.129
cat("Valor máximo:", round(max(Variable), 3), "\n")
## Valor máximo: 174.361
n_occidental <- sum(Variable <= 0)
n_oriental <- sum(Variable > 0)
cat("Registros en Hemisferio Occidental (<= 0°):", n_occidental,
"(", round(n_occidental / n * 100, 2), "%)\n")
## Registros en Hemisferio Occidental (<= 0°): 5290 ( 70.19 %)
cat("Registros en Hemisferio Oriental (> 0°):", n_oriental,
"(", round(n_oriental / n * 100, 2), "%)\n")
## Registros en Hemisferio Oriental (> 0°): 2247 ( 29.81 %)
Se aplica la Regla de Sturges para determinar el número óptimo de intervalos de clase, ajustando los límites a múltiplos de 10 para facilitar la lectura.
BASE <- 10
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_sug <- floor(1 + 3.322 * log10(n))
Rango_int <- max_int - min_int
Amplitud_int <- ceiling((Rango_int / k_sug) / 10) * 10
if (Amplitud_int == 0) Amplitud_int <- 10
cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_sug + 1)
if (max(cortes_int) < max(Variable)) cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
while (length(cortes_int) > 2 && cortes_int[length(cortes_int) - 1] >= max(Variable)) {
cortes_int <- cortes_int[-length(cortes_int)]
}
k <- length(cortes_int) - 1
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))
conteo <- data.frame(
Li = cortes_int[1:k],
Ls = cortes_int[2:(k + 1)],
MC = (cortes_int[1:k] + cortes_int[2:(k + 1)]) / 2,
ni = ni_int
) %>%
mutate(
hi = round(ni / n, 4),
hi_pct = round(ni / n * 100, 2)
)
cat("Total de intervalos de clase:", k, "\n")
## Total de intervalos de clase: 12
cat("Amplitud de clase:", Amplitud_int, "\n")
## Amplitud de clase: 30
cat("Intervalo más frecuente: [", conteo$Li[which.max(conteo$ni)], ",",
conteo$Ls[which.max(conteo$ni)], ") con", max(conteo$ni), "registros\n")
## Intervalo más frecuente: [ -130 , -100 ) con 2689 registros
fila_total <- tibble(
Li = NA, Ls = NA, MC = NA,
ni = sum(conteo$ni),
hi = sum(conteo$hi),
hi_pct = sum(conteo$hi_pct)
)
tdf_final <- bind_rows(conteo, fila_total)
tdf_final %>%
gt() %>%
tab_header(
title = md("**Tabla N° 1**"),
subtitle = md("Distribución de yacimientos según Longitud Geográfica")
) %>%
cols_label(
Li = "Lím. Inf (°)",
Ls = "Lím. Sup (°)",
MC = "Marca de Clase",
ni = "Frecuencia (ni)",
hi = "Proporción (hi)",
hi_pct = "Porcentaje (hi%)"
) %>%
fmt_number(columns = MC, decimals = 1) %>%
fmt_number(columns = hi, decimals = 4) %>%
fmt_number(columns = hi_pct, decimals = 2) %>%
sub_missing(columns = c(Li, Ls, MC), missing_text = "TOTAL") %>%
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 N° 1 | |||||
| Distribución de yacimientos según Longitud Geográfica | |||||
| Lím. Inf (°) | Lím. Sup (°) | Marca de Clase | Frecuencia (ni) | Proporción (hi) | Porcentaje (hi%) |
|---|---|---|---|---|---|
| -160 | -130 | −145.0 | 37 | 0.0049 | 0.49 |
| -130 | -100 | −115.0 | 2689 | 0.3568 | 35.68 |
| -100 | -70 | −85.0 | 2018 | 0.2677 | 26.77 |
| -70 | -40 | −55.0 | 403 | 0.0535 | 5.35 |
| -40 | -10 | −25.0 | 51 | 0.0068 | 0.68 |
| -10 | 20 | 5.0 | 1130 | 0.1499 | 14.99 |
| 20 | 50 | 35.0 | 431 | 0.0572 | 5.72 |
| 50 | 80 | 65.0 | 384 | 0.0509 | 5.09 |
| 80 | 110 | 95.0 | 183 | 0.0243 | 2.43 |
| 110 | 140 | 125.0 | 178 | 0.0236 | 2.36 |
| 140 | 170 | 155.0 | 26 | 0.0034 | 0.34 |
| 170 | 200 | 185.0 | 7 | 0.0009 | 0.09 |
| TOTAL | TOTAL | TOTAL | 7537 | 0.9999 | 99.99 |
| Autor: Grupo 5 | |||||
colores <- colorRampPalette(c("#2E86C1", "#AED6F1"))(k)
ggplot(conteo, aes(x = factor(MC), y = ni, fill = factor(MC))) +
geom_col(width = 0.85, color = "white") +
geom_text(aes(label = ni), vjust = -0.4, size = 3, fontface = "bold") +
scale_fill_manual(values = colores) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
labs(
title = "Gráfica N°1: Frecuencia Absoluta por Intervalo de Longitud",
x = "Marca de Clase — Longitud (°)",
y = "Frecuencia (ni)",
caption = paste0("n = ", format(n, big.mark = ","), " | Fuente: GOGET")
) +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))
ggplot(conteo, aes(x = factor(MC), y = hi_pct, fill = factor(MC))) +
geom_col(width = 0.85, color = "white") +
geom_text(aes(label = paste0(hi_pct, "%")), vjust = -0.4, size = 3, fontface = "bold") +
scale_fill_manual(values = colores) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
labs(
title = "Gráfica N°2: Frecuencia Relativa (Pi) por Intervalo de Longitud",
x = "Marca de Clase — Longitud (°)",
y = "Frecuencia Relativa (%)",
caption = paste0("n = ", format(n, big.mark = ","), " | Fuente: GOGET")
) +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))
La distribución de la Longitud no responde a un patrón único: los yacimientos del Hemisferio Occidental se concentran de forma simétrica en torno a un valor central (compatible con un modelo Normal), mientras que los del Hemisferio Oriental muestran una fuerte asimetría positiva por la concentración de cuencas desde Medio Oriente hasta Asia central (compatible con un modelo Log-Normal). Por ello se conjetura un modelo híbrido segmentado por hemisferio.
z1 <- Variable[Variable <= 0]
mu1 <- mean(z1, na.rm = TRUE)
sd1 <- sd(z1, na.rm = TRUE)
h1 <- hist(z1, breaks = 15, plot = FALSE)
df_z1 <- data.frame(x = h1$mids, y = (h1$counts / length(z1)) * 100)
cat("Media (mu):", round(mu1, 3), " | Desv. Estándar (sd):", round(sd1, 3), "\n")
## Media (mu): -94.92 | Desv. Estándar (sd): 21.253
ggplot(df_z1, aes(x = x, y = y)) +
geom_bar(stat = "identity", fill = "#AED6F1", color = "white", width = diff(h1$breaks)[1]) +
stat_function(fun = function(x) dnorm(x, mean = mu1, sd = sd1) * 100 * diff(h1$breaks)[1],
color = "#2E4053", linewidth = 1.5) +
labs(title = "Gráfica N°3: Ajuste Normal — Hemisferio Occidental (Longitudes ≤ 0°)",
x = "Longitud (°)", y = "Densidad Porcentual (%)",
caption = "Fuente: GOGET") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))
z2 <- Variable[Variable > 0]
fit2 <- fitdistr(z2, "lognormal")
mu_log2 <- fit2$estimate[1]
sd_log2 <- fit2$estimate[2]
h2 <- hist(z2, breaks = 15, plot = FALSE)
df_z2 <- data.frame(x = h2$mids, y = (h2$counts / length(z2)) * 100)
cat("Parámetro meanlog:", round(mu_log2, 4), " | Parámetro sdlog:", round(sd_log2, 4), "\n")
## Parámetro meanlog: 2.9174 | Parámetro sdlog: 1.4847
ggplot(df_z2, aes(x = x, y = y)) +
geom_bar(stat = "identity", fill = "#2E86C1", color = "white", width = diff(h2$breaks)[1]) +
stat_function(fun = function(x) dlnorm(x, meanlog = mu_log2, sdlog = sd_log2) * 100 * diff(h2$breaks)[1],
color = "#C0392B", linewidth = 1.5) +
labs(title = "Gráfica N°4: Ajuste Log-Normal — Hemisferio Oriental (Longitudes > 0°)",
x = "Longitud (°)", y = "Densidad Porcentual (%)",
caption = "Fuente: GOGET") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))
teorico1 <- dnorm(h1$mids, mu1, sd1)
p1_real <- cor(h1$counts, teorico1) * 100
teorico2 <- dlnorm(h2$mids, mu_log2, sd_log2)
p2_real <- cor(h2$counts, teorico2) * 100
plot(h1$counts, teorico1,
main = "Gráfica N°5: Correlación Modelo Observado y Esperado — Occidental",
xlab = "Frecuencia Observada", ylab = "Densidad Esperada (Normal)",
pch = 19, col = "#2E4053")
abline(lm(teorico1 ~ 0 + h1$counts), col = "red", lwd = 2)
legend("topleft", legend = paste0("r = ", round(p1_real, 2), "%"), bty = "n")
plot(h2$counts, teorico2,
main = "Gráfica N°6: Correlación Modelo Observado y Esperado — Oriental",
xlab = "Frecuencia Observada", ylab = "Densidad Esperada (Log-Normal)",
pch = 19, col = "#2E86C1")
abline(lm(teorico2 ~ 0 + h2$counts), col = "red", lwd = 2)
legend("topleft", legend = paste0("r = ", round(p2_real, 2), "%"), bty = "n")
chi1 <- suppressWarnings(chisq.test(h1$counts, p = teorico1, rescale.p = TRUE)$p.value)
chi2 <- suppressWarnings(chisq.test(h2$counts, p = teorico2, rescale.p = TRUE)$p.value)
cat("Chi-Cuadrado (p-valor) Occidental:", round(chi1, 4), "\n")
## Chi-Cuadrado (p-valor) Occidental: 0
cat("Chi-Cuadrado (p-valor) Oriental:", round(chi2, 4), "\n")
## Chi-Cuadrado (p-valor) Oriental: 0
resumen_ajuste <- data.frame(
Segmento = c("Hemisferio Occidental", "Hemisferio Oriental"),
Modelo = c("Normal", "Log-Normal"),
`Pearson (%)` = round(c(p1_real, p2_real), 2),
`Chi Cuadrado (p-valor)` = round(c(chi1, chi2), 4),
check.names = FALSE
) %>%
mutate(Resultado = ifelse(`Pearson (%)` > 75, "Modelo Aceptado", "Modelo en Revisión"))
resumen_ajuste %>%
gt() %>%
tab_header(
title = md("**Tabla N°2: Resumen del Test de Bondad al Modelo Híbrido**")
) %>%
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",
column_labels.border.top.color = "black",
column_labels.border.bottom.color = "black",
column_labels.border.bottom.width = px(2),
table_body.border.bottom.color = "black"
)
| Tabla N°2: Resumen del Test de Bondad al Modelo Híbrido | ||||
| Segmento | Modelo | Pearson (%) | Chi Cuadrado (p-valor) | Resultado |
|---|---|---|---|---|
| Hemisferio Occidental | Normal | 78.68 | 0 | Modelo Aceptado |
| Hemisferio Oriental | Log-Normal | 92.86 | 0 | Modelo Aceptado |
| Autor: Grupo 5 | ||||
A partir del modelo Log-Normal validado para el Hemisferio Oriental, se calcula la probabilidad teórica de que un yacimiento se ubique en la franja geoestratégica de Medio Oriente (entre los meridianos 40° y 60° Este).
prob_medio_oriente <- (plnorm(60, mu_log2, sd_log2) - plnorm(40, mu_log2, sd_log2)) * 100
cat("Probabilidad de ubicarse entre 40° y 60° de longitud (Medio Oriente):",
round(prob_medio_oriente, 2), "%\n")
## Probabilidad de ubicarse entre 40° y 60° de longitud (Medio Oriente): 8.77 %
pozos_occidental <- n_occidental
cat("Pozos ubicados en el Hemisferio Occidental:", pozos_occidental,
"(", round(pozos_occidental / n * 100, 2), "%)\n")
## Pozos ubicados en el Hemisferio Occidental: 5290 ( 70.19 %)
Por el Teorema del Límite Central (TLC), se calcula el intervalo de confianza al 95% para la media poblacional de la Longitud a nivel mundial (Z = 1.96).
x_bar <- mean(Variable, na.rm = TRUE)
sigma <- sd(Variable, na.rm = TRUE)
z <- qnorm(0.975)
margen <- z * (sigma / sqrt(n))
ic_inf <- x_bar - margen
ic_sup <- x_bar + margen
cat("Media muestral (centro de masa longitudinal):", round(x_bar, 3), "\n")
## Media muestral (centro de masa longitudinal): -54.653
cat("Intervalo de confianza al 95%: (", round(ic_inf, 3), "° ,", round(ic_sup, 3), "° )\n")
## Intervalo de confianza al 95%: ( -56.186 ° , -53.12 ° )
Tras excluir los registros con Longitud faltante, la variable exhibe un comportamiento bimodal ligado al hemisferio: el Hemisferio Occidental (70.19% de los registros) se ajusta a un modelo Normal (μ = -94.92°, σ = 21.25°) con una correlación de Pearson del 78.68%, mientras que el Hemisferio Oriental (29.81% de los registros) se ajusta a un modelo Log-Normal con una correlación de Pearson del 92.86%. Ambos modelos fueron sometidos al test de bondad de ajuste Chi-cuadrado. Bajo el modelo Log-Normal, la probabilidad de que un yacimiento se ubique en la franja de Medio Oriente (40°–60° Este) es del 8.77%. Finalmente, el intervalo de confianza al 95% para la media poblacional de la Longitud se ubica entre -56.186° y -53.12°, lo que valida la conjetura de una hiper-concentración geológica segmentada por hemisferio.