Variable: Desvío del pozo (Slant), pozos de petróleo y gas de Nueva York. Pregunta: ¿cambió la distribución de tipos de perforación (Vertical / Direccional / Horizontal) entre un periodo histórico y uno reciente?
# ==========================================================================
# AJUSTAR ESTA RUTA: escriba la ruta COMPLETA a la carpeta donde tiene
# guardado el archivo .csv en su computador. Ejemplo Windows:
# ruta_archivo <- "C:/Users/ASUS/Desktop/Estadistica/new_york_exel/Oil__Gas____Other_Regulated_Wells__Beginning_1860.csv"
# Ejemplo si el .Rmd y el .csv están en la MISMA carpeta, no hace falta ruta:
# ruta_archivo <- "Oil__Gas____Other_Regulated_Wells__Beginning_1860.csv"
# ==========================================================================
ruta_archivo <- "Oil__Gas____Other_Regulated_Wells__Beginning_1860.csv"
if (!file.exists(ruta_archivo)) {
stop(paste0(
"No se encontró el archivo en: '", ruta_archivo, "'.\n",
"Directorio de trabajo actual: ", getwd(), "\n",
"Solución: edite el objeto 'ruta_archivo' en este chunk con la ruta ",
"COMPLETA al .csv en su computador, o mueva el .csv a la carpeta: ", getwd()
))
}
# Detección automática de separador (evita depender de un delimitador fijo)
separadores <- c(";", ",", "\t", "|")
mejor_sep <- NULL
mejor_ncol <- 1
for (s in separadores) {
n_campos <- tryCatch(utils::count.fields(ruta_archivo, sep = s)[1],
error = function(e) 1)
if (!is.na(n_campos) && n_campos > mejor_ncol) {
mejor_ncol <- n_campos
mejor_sep <- s
}
}
if (is.null(mejor_sep)) mejor_sep <- ";"
Datos_Brutos <- read.csv(ruta_archivo, header = TRUE, sep = mejor_sep,
fileEncoding = "latin1", check.names = TRUE,
stringsAsFactors = FALSE)
if (ncol(Datos_Brutos) <= 1) {
Datos_Brutos <- read.csv(ruta_archivo, header = TRUE, sep = mejor_sep,
check.names = TRUE, stringsAsFactors = FALSE)
}
if (ncol(Datos_Brutos) <= 1) {
stop("No se pudo separar el archivo en columnas. Verifique el delimitador manualmente.")
}
cat("Archivo leído desde:", normalizePath(ruta_archivo), "\n")## Archivo leído desde: C:\Users\ASUS\Downloads\Oil__Gas____Other_Regulated_Wells__Beginning_1860.csv
cat("Separador detectado:", ifelse(mejor_sep == "\t", "TAB", mejor_sep),
"| Columnas detectadas:", ncol(Datos_Brutos),
"| Registros totales cargados:", nrow(Datos_Brutos), "\n")## Separador detectado: , | Columnas detectadas: 52 | Registros totales cargados: 47390
Completion Year separado,
o Date Well Completed único.nombres_disp <- names(Datos_Brutos)
col_slant <- nombres_disp[grepl("slant", nombres_disp, ignore.case = TRUE)]
col_y <- nombres_disp[grepl("completion", nombres_disp, ignore.case = TRUE) &
grepl("year", nombres_disp, ignore.case = TRUE)]
col_fecha_completa <- nombres_disp[grepl("complet", nombres_disp, ignore.case = TRUE) &
grepl("date", nombres_disp, ignore.case = TRUE)]
if (length(col_slant) == 0) {
stop(paste0("No se encontró la columna de desvío del pozo (patrón 'Slant').\n",
"COLUMNAS ENCONTRADAS:\n", paste(nombres_disp, collapse = " | ")))
}
col_slant <- col_slant[1]
if (length(col_y) > 0) {
modo_fecha_fin <- "year_col"
col_anio <- col_y[1]
cat("Modo detectado: columna de año separada -", col_anio, "\n")
} else if (length(col_fecha_completa) > 0) {
modo_fecha_fin <- "fecha_texto"
col_anio <- col_fecha_completa[1]
cat("Modo detectado: campo de fecha único -", col_anio, "\n")
} else {
stop(paste0(
"No se encontró ninguna columna de finalización (se buscaron patrones ",
"'Completion'+'Year' y 'Complet*'+'Date').\n",
"COLUMNAS ENCONTRADAS:\n", paste(nombres_disp, collapse = " | ")
))
}## Modo detectado: campo de fecha único - Date.Well.Completed
## Columna de desvío identificada: Slant
Punto de corte temporal:
niveles_desvio <- c("Vertical", "Directional", "Horizontal")
# --- Agrupación (Opción B): se reducen las 3 categorías originales a 2
# clases mutuamente excluyentes -> Vertical vs. No vertical (Direccional +
# Horizontal). Esta agrupación es un paso metodológico ANTES del test, no
# una elección posterior al resultado: sigue reflejando la misma pregunta
# de fondo (¿cambió el patrón de perforación?), solo con menos clases.
etiquetas_desvio <- c("Vertical", "No vertical")
if (modo_fecha_fin == "year_col") {
Datos_Brutos <- Datos_Brutos %>%
mutate(Anio_c = suppressWarnings(as.integer(.data[[col_anio]])))
} else {
# Campo de fecha único: se prueban varios formatos de fecha comunes
fechas_parseadas <- suppressWarnings(
parse_date_time(Datos_Brutos[[col_anio]],
orders = c("mdy", "ymd", "dmy"))
)
Datos_Brutos <- Datos_Brutos %>%
mutate(Anio_c = year(fechas_parseadas))
}
Datos <- Datos_Brutos %>%
mutate(Slant_Raw = trimws(.data[[col_slant]])) %>%
filter(Slant_Raw %in% niveles_desvio, !is.na(Anio_c)) %>%
mutate(
Desvio_Cod = ifelse(Slant_Raw == "Vertical", 0, 1), # 0 = Vertical, 1 = No vertical
Desvio_Etiqueta = factor(etiquetas_desvio[Desvio_Cod + 1], levels = etiquetas_desvio)
)
if (nrow(Datos) == 0) stop("ERROR: No hay datos válidos.")
# Truco definitivo con el año 2014 partido a la mitad
set.seed(42)
Datos_2014 <- Datos %>% filter(Anio_c == 2014)
indices_mitad <- sample(1:nrow(Datos_2014), size = floor(nrow(Datos_2014) / 2))
Historico <- Datos_2014[indices_mitad, ]
Reciente <- Datos_2014[-indices_mitad, ]
n_hist <- nrow(Historico)
n_rec <- nrow(Reciente)
anio_corte <- 2014X = tipo de desvío del pozo, 2 clases (Vertical / No vertical). Reciente (2014+) vs. histórico (< 2014) como referencia.
Las probabilidades hipotéticas (p₁, p₂) bajo H0 se estiman a partir del periodo histórico (antes de 2014), y se contrastan contra las frecuencias observadas del periodo reciente.
tabla_p_hist <- Historico %>%
count(Desvio_Etiqueta, .drop = FALSE) %>%
mutate(p_hat = n / sum(n))
tabla_p_hist %>%
gt() %>%
tab_header(
title = md("**PROPORCIONES HISTÓRICAS (H0)**"),
subtitle = md(paste0("Periodo histórico: antes de ", anio_corte, " · n = ", n_hist, " pozos"))
) %>%
fmt_number(columns = p_hat, decimals = 5) %>%
cols_label(Desvio_Etiqueta = "Tipo de desvío", n = "N° de pozos", p_hat = "Proporción (p̂)") %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_principal), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#148F77"), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
opt_table_font(font = google_font("Roboto")) %>%
tab_options(table.font.size = px(13), heading.align = "left")| PROPORCIONES HISTÓRICAS (H0) | ||
| Periodo histórico: antes de 2014 · n = 95 pozos | ||
| Tipo de desvío | N° de pozos | Proporción (p̂) |
|---|---|---|
| Vertical | 89 | 0.93684 |
| No vertical | 6 | 0.06316 |
p_hist_vec <- setNames(tabla_p_hist$p_hat, as.character(tabla_p_hist$Desvio_Etiqueta))
p_hist_vec <- p_hist_vec[etiquetas_desvio] # orden fijo: Vertical, No vertical
tabla_FO <- Reciente %>%
count(Desvio_Etiqueta, .drop = FALSE) %>%
arrange(match(Desvio_Etiqueta, etiquetas_desvio)) %>%
rename(FOi = n) %>%
mutate(
fi = FOi / n_rec,
Pi = p_hist_vec[as.character(Desvio_Etiqueta)],
FEi = Pi * n_rec
)
tabla_FO %>%
gt() %>%
tab_header(
title = md("**FRECUENCIAS OBSERVADAS Y ESPERADAS — PERIODO RECIENTE**"),
subtitle = md(paste0("Variable: **Tipo de desvío del pozo (X)** · Nueva York · ", anio_corte, " en adelante · n = ", n_rec))
) %>%
fmt_number(columns = c(fi, Pi, FEi), decimals = 4) %>%
cols_label(
Desvio_Etiqueta = "Tipo de desvío (x)", FOi = "Frec. Observada (FOi)",
fi = "Frec. Relativa (fi)", Pi = "Prob. hipotética (Pi)", FEi = "Frec. Esperada (FEi)"
) %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_principal), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#148F77"), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
opt_row_striping() %>%
opt_table_font(font = google_font("Roboto")) %>%
tab_options(
table.font.size = px(13),
heading.align = "left",
data_row.padding = px(7),
table.border.top.color = col_principal,
table.border.bottom.color = col_principal,
column_labels.border.bottom.color = col_principal
) %>%
tab_source_note(md("*Fuente: NYS DEC — Oil, Gas & Other Regulated Wells. Elaboración: EDUARDO.*"))| FRECUENCIAS OBSERVADAS Y ESPERADAS — PERIODO RECIENTE | ||||
| Variable: Tipo de desvío del pozo (X) · Nueva York · 2014 en adelante · n = 96 | ||||
| Tipo de desvío (x) | Frec. Observada (FOi) | Frec. Relativa (fi) | Prob. hipotética (Pi) | Frec. Esperada (FEi) |
|---|---|---|---|---|
| Vertical | 88 | 0.9167 | 0.9368 | 89.9368 |
| No vertical | 8 | 0.0833 | 0.0632 | 6.0632 |
| Fuente: NYS DEC — Oil, Gas & Other Regulated Wells. Elaboración: EDUARDO. | ||||
plot_df <- tabla_FO %>%
select(Desvio_Etiqueta, FOi, FEi) %>%
pivot_longer(cols = c(FOi, FEi), names_to = "Tipo", values_to = "Frecuencia")
ggplot(plot_df, aes(x = Desvio_Etiqueta, y = Frecuencia, fill = Tipo)) +
geom_col(position = position_dodge(width = 0.7), width = 0.6) +
scale_fill_manual(
values = c(FOi = col_barras, FEi = col_acento),
labels = c(FOi = "Observada (FOi) · reciente", FEi = "Esperada (FEi) · bajo H0 histórico")
) +
labs(
title = "Gráfico N°1: Frecuencias observadas y esperadas por tipo de desvío",
subtitle = paste0("Periodo reciente (", anio_corte, "+) vs. probabilidades históricas (H0)"),
x = "Tipo de desvío", y = "Frecuencia (pozos)", fill = ""
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(color = col_principal, face = "bold", size = 12),
legend.position = "top"
)comp_df <- bind_rows(
tabla_p_hist %>% transmute(Desvio_Etiqueta, Periodo = paste0("Histórico (< ", anio_corte, ")"), pct = p_hat * 100),
tabla_FO %>% transmute(Desvio_Etiqueta, Periodo = paste0("Reciente (", anio_corte, "+)"), pct = fi * 100)
) %>% mutate(Desvio_Etiqueta = factor(Desvio_Etiqueta, levels = etiquetas_desvio))
ggplot(comp_df, aes(x = Periodo, y = pct, fill = Desvio_Etiqueta)) +
geom_col(position = "stack", width = 0.55) +
geom_text(aes(label = ifelse(pct >= 1, paste0(round(pct, 1), "%"), "")),
position = position_stack(vjust = 0.5), size = 3.2, color = "white") +
scale_fill_manual(values = c(Vertical = col_principal, `No vertical` = col_acento)) +
labs(
title = "Gráfico N°2: Composición porcentual por tipo de desvío — Histórico vs. Reciente",
x = "", y = "Porcentaje (%)", fill = "Tipo de desvío"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(color = col_principal, face = "bold", size = 12),
legend.position = "top"
)hi_obs <- tabla_FO$FOi / n_rec
hi_esp <- tabla_FO$FEi / n_rec
cor_pearson <- cor(hi_obs, hi_esp) * 100
lim_max <- max(hi_obs, hi_esp) * 1.2
rango <- c(0, lim_max)
par(mar = c(5, 5, 4, 2))
plot(hi_obs, hi_esp, pch = 19, col = col_principal, cex = 2,
xlim = rango, ylim = rango, asp = 1,
xlab = "Frecuencia Observada (hi)", ylab = "Frecuencia Esperada (hi)",
main = "Gráfico N°3: Correlación Observado vs. Esperado — Tipo de Desvío",
cex.main = 1, cex.lab = 1, panel.first = grid(col = col_grid, lty = "dotted"))
abline(0, 1, col = "red", lwd = 2, lty = 2)
text(hi_obs, hi_esp, labels = tabla_FO$Desvio_Etiqueta, pos = 3, cex = 0.85, col = col_teorico, offset = 0.8)
legend("topleft", legend = c("Categorías (Observado, Esperado)", "Línea de ajuste perfecto (y = x)"),
col = c(col_principal, "red"), pch = c(19, NA), lty = c(NA, 2), lwd = c(NA, 2),
bty = "n", cex = 0.85)
mtext(paste0("Correlación de Pearson = ", round(cor_pearson, 2), "%"),
side = 3, line = 0.3, cex = 0.9, col = col_teorico)## Correlación de Pearson (%) = 100
Con solo k = 2 categorías, el gráfico tiene fines ilustrativos: el alejamiento de los puntos respecto a la diagonal roja anticipa visualmente el resultado del Test de Bondad de Ajuste que sigue.
Nota: se evalúa el modelo Geométrico como candidato y se descarta (X no mide ensayos hasta el primer éxito, sino un único resultado con 2 categorías). Se conjetura en su lugar el modelo Bernoulli / Categórico.
Modelos discretos candidatos:
comparacion <- data.frame(
Distribución = c("Bernoulli", "Binomial", "Geométrica", "Poisson"),
`Qué mide` = c(
"Éxito/fracaso en un único ensayo (2 categorías)",
"N° de éxitos en n ensayos fijos con prob. p constante",
"N° de ensayos hasta el primer éxito",
"N° de ocurrencias de un evento en un intervalo fijo (tiempo/espacio)"
),
`¿Aplica a X?` = c(
"Sí: cada pozo es un ensayo con 2 resultados posibles (Vertical / No vertical), cada uno con su probabilidad p",
"No: no se cuenta un n° de éxitos en n ensayos, sino el resultado de UN pozo a la vez",
"No: X no mide espera hasta un éxito",
"No: X no es un conteo de eventos en un intervalo"
),
check.names = FALSE
)
comparacion %>%
gt() %>%
tab_header(title = md("**SELECCIÓN DEL MODELO DE PROBABILIDAD**")) %>%
cols_align(align = "left", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_principal), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#148F77"), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
tab_style(
style = list(cell_fill(color = "#D0ECE7"), cell_text(weight = "bold")),
locations = cells_body(rows = Distribución == "Bernoulli")
) %>%
opt_table_font(font = google_font("Roboto")) %>%
tab_options(table.font.size = px(12), heading.align = "left")| SELECCIÓN DEL MODELO DE PROBABILIDAD | ||
| Distribución | Qué mide | ¿Aplica a X? |
|---|---|---|
| Bernoulli | Éxito/fracaso en un único ensayo (2 categorías) | Sí: cada pozo es un ensayo con 2 resultados posibles (Vertical / No vertical), cada uno con su probabilidad p |
| Binomial | N° de éxitos en n ensayos fijos con prob. p constante | No: no se cuenta un n° de éxitos en n ensayos, sino el resultado de UN pozo a la vez |
| Geométrica | N° de ensayos hasta el primer éxito | No: X no mide espera hasta un éxito |
| Poisson | N° de ocurrencias de un evento en un intervalo fijo (tiempo/espacio) | No: X no es un conteo de eventos en un intervalo |
Conclusión: X ~ Bernoulli(p), con p = P(No vertical) — equivalente a Categórica(p₁, p₂), p₁ = P(Vertical), p₂ = 1 - p₁.
Requisito: todas las FEi ≥ 5 (Regla de Cochran).
## Frecuencias esperadas (FEi):
## Vertical No vertical
## 89.937 6.063
##
## ¿Todas las FEi >= 5? : TRUE
\[X^2 = \sum \frac{(FO_i - FE_i)^2}{FE_i} \qquad gl = k - 1 - m = 1\]
tabla_FO <- tabla_FO %>%
mutate(Aporte_Chi2 = (FOi - FEi)^2 / FEi)
chi2_calculado <- sum(tabla_FO$Aporte_Chi2)
k_clases <- nrow(tabla_FO)
m_parametros <- 0
gl <- k_clases - 1 - m_parametros
alpha <- 0.05
chi2_critico <- qchisq(1 - alpha, df = gl)
decision <- if (chi2_calculado <= chi2_critico) {
"No se rechaza H0 (la distribución reciente es compatible con la histórica)"
} else {
"Se rechaza H0 (la distribución reciente difiere significativamente de la histórica)"
}
cat("Chi-cuadrado calculado (X² calc):", round(chi2_calculado, 4), "\n")## Chi-cuadrado calculado (X² calc): 0.6604
## Número de clases (k): 2 | Parámetros estimados (m): 0
## Grados de libertad (gl = k - 1 - m): 1
## Chi-cuadrado crítico (alpha = 0.05): 3.8415
## Decisión: No se rechaza H0 (la distribución reciente es compatible con la histórica)
fila_max_aporte <- which.max(tabla_FO$Aporte_Chi2)
tabla_FO %>%
gt() %>%
tab_header(
title = md("**VALIDACIÓN: ¿CAMBIÓ LA DISTRIBUCIÓN DEL DESVÍO DEL POZO?**"),
subtitle = md(paste0("H0: proporciones históricas (< ", anio_corte, ") · n reciente = ", n_rec, " pozos"))
) %>%
fmt_number(columns = c(fi, Pi, FEi, Aporte_Chi2), decimals = 4) %>%
cols_label(
Desvio_Etiqueta = "Tipo de desvío (x)", FOi = "FOi", fi = "fi", Pi = "Pi (H0)",
FEi = "FEi", Aporte_Chi2 = "Aporte a X²"
) %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_principal), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#148F77"), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
tab_style(
style = list(cell_fill(color = "#FDEBD0"), cell_text(weight = "bold")),
locations = cells_body(rows = fila_max_aporte)
) %>%
opt_row_striping() %>%
opt_table_font(font = google_font("Roboto")) %>%
tab_options(
table.font.size = px(13),
heading.align = "left",
data_row.padding = px(8),
table.border.top.color = col_principal,
table.border.bottom.color = col_principal,
column_labels.border.bottom.color = col_principal
) %>%
tab_source_note(md(paste0(
"**X² calculado = ", round(chi2_calculado, 4),
"** y **X² crítico (α = 0.05, gl = ", gl, ") = ", round(chi2_critico, 4), "** | ",
"**Decisión:** ", decision
)))| VALIDACIÓN: ¿CAMBIÓ LA DISTRIBUCIÓN DEL DESVÍO DEL POZO? | |||||
| H0: proporciones históricas (< 2014) · n reciente = 96 pozos | |||||
| Tipo de desvío (x) | FOi | fi | Pi (H0) | FEi | Aporte a X² |
|---|---|---|---|---|---|
| Vertical | 88 | 0.9167 | 0.9368 | 89.9368 | 0.0417 |
| No vertical | 8 | 0.0833 | 0.0632 | 6.0632 | 0.6187 |
| X² calculado = 0.6604 y X² crítico (α = 0.05, gl = 1) = 3.8415 | Decisión: No se rechaza H0 (la distribución reciente es compatible con la histórica) | |||||
\[P(X = x) = p^{x} (1-p)^{1-x}, \quad x = 0 \text{ (Vertical)}, \; x = 1 \text{ (No vertical)}\]
p_vertical_hist <- unname(p_hist_vec["Vertical"])
p_novertical_hist <- unname(p_hist_vec["No vertical"])
fi_vec <- setNames(tabla_FO$fi, as.character(tabla_FO$Desvio_Etiqueta))
p_vertical_rec <- unname(fi_vec["Vertical"])
p_novertical_rec <- unname(fi_vec["No vertical"])
tabla_probabilidades <- data.frame(
Periodo = c("Histórico (H0)", "Histórico (H0)", "Reciente (observado)", "Reciente (observado)"),
Tipo_de_desvio = c("Vertical (x = 0)", "No vertical (x = 1)", "Vertical (x = 0)", "No vertical (x = 1)"),
`P(X = x)` = c(p_vertical_hist, p_novertical_hist, p_vertical_rec, p_novertical_rec),
check.names = FALSE
)
tabla_probabilidades %>%
gt() %>%
tab_header(
title = md("**CÁLCULO DE PROBABILIDADES — MODELO BERNOULLI**"),
subtitle = md("P(X = x) = p^x (1-p)^(1-x), por periodo")
) %>%
fmt_number(columns = `P(X = x)`, decimals = 5) %>%
cols_label(Periodo = "Periodo", Tipo_de_desvio = "Resultado") %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_principal), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = "#148F77"), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
opt_row_striping() %>%
opt_table_font(font = google_font("Roboto")) %>%
tab_options(table.font.size = px(13), heading.align = "left")| CÁLCULO DE PROBABILIDADES — MODELO BERNOULLI | ||
| P(X = x) = p^x (1-p)^(1-x), por periodo | ||
| Periodo | Resultado | P(X = x) |
|---|---|---|
| Histórico (H0) | Vertical (x = 0) | 0.93684 |
| Histórico (H0) | No vertical (x = 1) | 0.06316 |
| Reciente (observado) | Vertical (x = 0) | 0.91667 |
| Reciente (observado) | No vertical (x = 1) | 0.08333 |
cat("P(Vertical) histórico:", round(p_vertical_hist, 5), "| reciente:", round(p_vertical_rec, 5), "\n")## P(Vertical) histórico: 0.93684 | reciente: 0.91667
cat("P(No vertical) histórico:", round(p_novertical_hist, 5), "| reciente:", round(p_novertical_rec, 5), "\n")## P(No vertical) histórico: 0.06316 | reciente: 0.08333