Proposed Depth, ft (profundidad propuesta en el
permiso).Measured Depth, ft (profundidad medida real del pozo).library(dplyr)
library(gt)
# El archivo CSV debe estar en la misma carpeta que este .Rmd
# (en este caso: C:/Users/ASUS/Desktop/dally)
lineas <- readLines("Oil__Gas____Other_Regulated_Wells__Beginning_1860 (1).csv",
encoding = "latin1", warn = FALSE)
Encoding(lineas) <- "latin1"
lineas <- iconv(lineas, from = "latin1", to = "UTF-8")
datos <- read.csv(text = lineas, sep = ",", header = TRUE,
stringsAsFactors = FALSE)
cat("Número de registros:", nrow(datos), "\n")
## Número de registros: 47396
cat("Número de variables:", ncol(datos), "\n")
## Número de variables: 52
if (ncol(datos) < 5) {
cat("ADVERTENCIA: se detectaron muy pocas columnas (", ncol(datos), "). ",
"El separador probablemente es incorrecto para este archivo.\n",
sep = "", file = stderr())
}
datos %>%
head(5) %>%
gt() %>%
tab_header(
title = md("**Extracto del Dataset**"),
subtitle = md("Primeras 5 filas, todas las columnas del dataset original")
) %>%
tab_source_note(source_note = "Autor: Grupo 1") %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
tab_style(
style = list(cell_fill(color = col_fila_alt)),
locations = cells_body(rows = seq(1, 5, 2))
) %>%
tab_style(
style = cell_borders(sides = "all", color = col_borde, weight = px(1)),
locations = list(cells_body(), cells_column_labels())
) %>%
opt_table_outline(style = "solid", width = px(3), color = col_borde) %>%
tab_options(
table.border.top.color = col_borde,
table.border.bottom.color = col_borde,
table.border.top.style = "solid",
table.border.bottom.style = "solid",
column_labels.border.top.color = col_borde,
column_labels.border.bottom.color = col_borde,
column_labels.border.bottom.width = px(2),
heading.border.bottom.color = col_borde,
heading.border.bottom.width = px(2),
table.font.size = px(12),
data_row.padding = px(6),
column_labels.background.color = col_encabezado,
container.overflow.x = TRUE,
table.width = pct(100)
)
| Extracto del Dataset | |||||||||||||||||||||||||||||||||||||||||||||||||||
| Primeras 5 filas, todas las columnas del dataset original | |||||||||||||||||||||||||||||||||||||||||||||||||||
| API.Well.Number | County.Code | API.Hole.Number | Sidetrack | Completion | Well.Name | Company.Name | Operator.Number | Well.Type | Map.Symbol | Well.Status | Status.Date | Permit.Application.Date | Permit.Issued.Date | Date.Spudded | Date.of.Total.Depth | Date.Well.Completed | Date.Well.Plugged | Date.Well.Confidentiality.Ends | Confidentiality.Code | Town | Quad | Quad.Section | Producing.Field | Producing.Formation | Financial.Security | Slant | County | Region | State.Lease | Proposed.Depth..ft | Surface.Longitude | Surface.Latitude | Bottom.Hole.Longitude | Bottom.Hole.Latitude | True.Vertical.Depth..ft | Measured.Depth..ft | Kickoff..ft | Drilled.Depth..ft | Elevation..ft | Original.Well.Type | Permit.Fee | Objective.Formation | Depth.Fee | Spacing | Spacing.Acres | Integration | Hearing.Date | Date.Last.Modified | DEC.Database.Link | Location.1 | Georeference |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 31003670100000 | 3 | 67010 | 0 | 0 | Voided Permit | 9998 | NL | O | VP | Pre-1989 Well (N/A) | False | Vertical | Statewide | 9 | NA | 0 | NA | NA | NA | NA | 0 | 0 | 0 | 0 | NA | NL | 0 | 0 | NA | 06/28/1995 12:00:00 AM | http://extapps.dec.ny.gov/cfmx/extapps/GasOil/search/wells/index.cfm?api=31003670100000 | ||||||||||||||||||||
| 31003672540000 | 3 | 67254 | 0 | 0 | Voided Permit | 9998 | NL | O | VP | Pre-1989 Well (N/A) | A | False | Vertical | Statewide | 9 | NA | 0 | NA | NA | NA | NA | 0 | 0 | 0 | 0 | NA | NL | 0 | 0 | NA | 07/05/1995 12:00:00 AM | http://extapps.dec.ny.gov/cfmx/extapps/GasOil/search/wells/index.cfm?api=31003672540000 | |||||||||||||||||||
| 31003673010000 | 3 | 67301 | 0 | 0 | 9998 | NL | O | UN | Pre-1989 Well (N/A) | False | Vertical | Statewide | 9 | NA | 0 | NA | NA | NA | NA | 0 | 0 | 0 | 0 | NA | NL | 0 | 0 | NA | 12/20/2019 03:27:41 PM | http://extapps.dec.ny.gov/cfmx/extapps/GasOil/search/wells/index.cfm?api=31003673010000 | |||||||||||||||||||||
| 31003686440000 | 3 | 68644 | 0 | 0 | Voided Permit | 9998 | NL | O | VP | Pre-1989 Well (N/A) | A | False | Vertical | Statewide | 9 | NA | 0 | NA | NA | NA | NA | 0 | 0 | 0 | 0 | NA | NL | 0 | 0 | NA | 08/15/1995 12:00:00 AM | http://extapps.dec.ny.gov/cfmx/extapps/GasOil/search/wells/index.cfm?api=31003686440000 | |||||||||||||||||||
| 31003694660000 | 3 | 69466 | 0 | 0 | Bradford 48 | Bradley Producing Company | 9673 | OD | OWP | PA | Pre-1989 Well (N/A) | Clarksville | Bolivar | B | False | Vertical | Allegany | 9 | NA | 0 | -78.19359 | 42.08821 | -78.19359 | 42.08821 | 0 | 0 | 0 | 0 | NA | NL | 0 | 0 | NA | 03/01/2000 12:00:00 AM | http://extapps.dec.ny.gov/cfmx/extapps/GasOil/search/wells/index.cfm?api=31003694660000 | (42.08821, -78.19359) | POINT (-78.19359 42.08821) | ||||||||||||||
| Autor: Grupo 1 | |||||||||||||||||||||||||||||||||||||||||||||||||||
# Detección automática de columnas (los nombres pueden variar entre el CSV
# de muestra y el CSV local: puntos extra, mayúsculas/minúsculas, etc.)
col_x <- names(datos)[grepl("proposed", names(datos), ignore.case = TRUE) &
grepl("depth", names(datos), ignore.case = TRUE)][1]
col_y <- names(datos)[grepl("measured", names(datos), ignore.case = TRUE) &
grepl("depth", names(datos), ignore.case = TRUE)][1]
col_x_todas <- names(datos)[grepl("proposed", names(datos), ignore.case = TRUE) &
grepl("depth", names(datos), ignore.case = TRUE)]
col_y_todas <- names(datos)[grepl("measured", names(datos), ignore.case = TRUE) &
grepl("depth", names(datos), ignore.case = TRUE)]
cat("TODAS las columnas que matchean X:", paste(col_x_todas, collapse = ", "), "\n", file = stderr())
cat("TODAS las columnas que matchean Y:", paste(col_y_todas, collapse = ", "), "\n", file = stderr())
cat("Columna detectada para X (Proposed Depth):", col_x, "\n")
## Columna detectada para X (Proposed Depth): Proposed.Depth..ft
cat("Columna detectada para Y (Measured Depth):", col_y, "\n")
## Columna detectada para Y (Measured Depth): Measured.Depth..ft
cat("Columna detectada para X (Proposed Depth): ", col_x, "\n", file = stderr())
cat("Columna detectada para Y (Measured Depth): ", col_y, "\n", file = stderr())
if (is.na(col_x) || is.na(col_y)) {
stop("No se encontraron las columnas de Proposed Depth / Measured Depth. ",
"Nombres disponibles: ", paste(names(datos), collapse = ", "))
}
x_raw <- suppressWarnings(as.numeric(as.character(datos[[col_x]])))
y_raw <- suppressWarnings(as.numeric(as.character(datos[[col_y]])))
cat("Registros con Proposed Depth: ", sum(!is.na(x_raw) & x_raw > 0), "\n", file = stderr())
cat("Registros con Measured Depth: ", sum(!is.na(y_raw) & y_raw > 0), "\n", file = stderr())
# --- Diagnóstico: valores crudos (antes de convertir a numérico) ---
# Se escribe directo a stderr() (no message/cat normal) porque el chunk
# global tiene message = FALSE, que silenciaba por completo la salida
# de diagnóstico anterior.
cat("\nMuestra de valores CRUDOS en ", col_x, ":\n", file = stderr())
cat(paste(capture.output(print(head(datos[[col_x]], 10))), collapse = "\n"), "\n", file = stderr())
cat("\nMuestra de valores CRUDOS en ", col_y, ":\n", file = stderr())
cat(paste(capture.output(print(head(datos[[col_y]], 10))), collapse = "\n"), "\n", file = stderr())
cat("\nClase de la columna X: ", class(datos[[col_x]]), "\n", file = stderr())
cat("Clase de la columna Y: ", class(datos[[col_y]]), "\n", file = stderr())
cat("Numero de columnas totales en datos: ", ncol(datos), "\n", file = stderr())
cat("Todos los nombres de columnas:\n", file = stderr())
cat(paste(names(datos), collapse = " | "), "\n", file = stderr())
if (sum(!is.na(x_raw) & x_raw > 0) == 0 || sum(!is.na(y_raw) & y_raw > 0) == 0) {
stop("La conversion a numerico dejo 0 valores validos. Revisa el mensaje ",
"de consola arriba (antes de este error) con la muestra de valores ",
"crudos: es probable que contengan texto (ej. '1500 ft'), separador ",
"de miles ('12,450'), o coma decimal ('1500,5') que as.numeric() no ",
"puede interpretar directamente.")
}
tabla_pares_gt <- pares %>%
head(15) %>%
rename(`Proposed Depth, ft (X)` = x,
`Measured Depth, ft (Y)` = y) %>%
mutate(`Measured Depth, ft (Y)` = round(`Measured Depth, ft (Y)`, 2))
tabla_pares_gt %>%
gt() %>%
tab_header(
title = md("**Tabla de Pares de Valores**"),
subtitle = md("Proposed Depth y Measured Depth (primeras 15 filas de un total de datos agrupados)")
) %>%
tab_source_note(source_note = "Autor: Grupo 1") %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
tab_style(
style = list(cell_fill(color = col_fila_alt)),
locations = cells_body(rows = seq(1, nrow(tabla_pares_gt), 2))
) %>%
opt_table_outline(style = "solid", width = px(3), color = col_borde) %>%
tab_options(
table.border.top.color = col_borde,
table.border.bottom.color = col_borde,
table.border.top.style = "solid",
table.border.bottom.style = "solid",
column_labels.border.top.color = col_borde,
column_labels.border.bottom.color = col_borde,
column_labels.border.bottom.width = px(2),
heading.border.bottom.color = col_borde,
heading.border.bottom.width = px(2),
table_body.hlines.color = "#CBD5DE",
table_body.border.bottom.color = col_borde,
table.font.size = px(14),
data_row.padding = px(6),
table_body.border.top.style = "solid",
column_labels.background.color = col_encabezado
)
| Tabla de Pares de Valores | |
| Proposed Depth y Measured Depth (primeras 15 filas de un total de datos agrupados) | |
| Proposed Depth, ft (X) | Measured Depth, ft (Y) |
|---|---|
| 56 | 56.00 |
| 89 | 89.00 |
| 114 | 114.00 |
| 132 | 132.00 |
| 200 | 207.33 |
| 300 | 326.00 |
| 350 | 382.00 |
| 400 | 411.80 |
| 425 | 382.50 |
| 442 | 442.00 |
| 450 | 450.00 |
| 465 | 514.00 |
| 485 | 383.00 |
| 500 | 578.25 |
| 507 | 534.50 |
| Autor: Grupo 1 | |
if (nrow(df_raw) == 0) {
stop("df_raw quedó vacío después de los filtros: revisa que col_x/col_y ",
"se hayan detectado bien y que haya pares con valores > 0.")
}
plot(df_raw$x, df_raw$y,
pch = 20,
col = rgb(0.04, 0.18, 0.29, 0.15),
xlab = "Proposed Depth, ft (X)",
ylab = "Measured Depth, ft (Y)",
main = "Gráfica original: Proposed Depth en comparación con Measured Depth")
Observando la gráfica de dispersión, se propone un Modelo de Regresión Polinómica de grado 2:
\[y = a + b_1 x + b_2 x^2\]
Justificación del grado: se probó también un modelo de grado 3, y la mejora en el R² fue prácticamente nula (menos de 0.05 puntos porcentuales) respecto al de grado 2. Por el principio de parsimonia —preferir el modelo más simple que explique igual de bien los datos—, se conserva el grado 2 en lugar de agregar un término adicional que no aporta poder explicativo real.
m_poli2 <- lm(y ~ poly(x, 2, raw = TRUE), data = pares)
sum_reg <- summary(m_poli2)
b <- coef(m_poli2)
cat("Intercepto (a) :", round(b[1], 4), "\n")
## Intercepto (a) : -123.4239
cat("Pendiente b1 :", round(b[2], 6), "\n")
## Pendiente b1 : 1.062634
cat("Pendiente b2 :", round(b[3], 8), "\n")
## Pendiente b2 : 0.00000577
cat("\nEcuación del modelo:\n")
##
## Ecuación del modelo:
cat("y =", round(b[1], 2),
"+ (", round(b[2], 6), ")x",
"+ (", round(b[3], 8), ")x²\n")
## y = -123.42 + ( 1.062634 )x + ( 0.00000577 )x²
x_grid <- seq(min(pares$x), max(pares$x), length.out = 400)
y_grid <- predict(m_poli2, newdata = data.frame(x = x_grid))
plot(pares$x, pares$y,
pch = 20,
col = rgb(0.04, 0.18, 0.29, 0.15),
xlab = "Proposed Depth, ft (X)",
ylab = "Measured Depth, ft (Y)",
main = "Superposición: Modelo Polinómico y Datos Reales")
lines(x_grid, y_grid, col = col_curva, lwd = 3)
legend("topleft",
legend = c("Datos reales", "Modelo polinómico (grado 2)"),
col = c(col_puntos, col_curva),
pch = c(20, NA),
lty = c(NA, 1),
lwd = c(NA, 3),
bty = "n")
r <- cor(pares$x, pares$y)
r2 <- sum_reg$r.squared * 100
cat("Correlación de Pearson (r):", round(r, 4), "\n")
## Correlación de Pearson (r): 0.9696
cat("Coeficiente de determinación (R²%):", round(r2, 2), "%\n")
## Coeficiente de determinación (R²%): 94.04 %
El coeficiente de determinación (R²) indica qué
porcentaje de la variación en Measured Depth es explicado
por Proposed Depth.
x_estimar1 <- round(min(pares$x), 2)
y_estimada1 <- predict(m_poli2, newdata = data.frame(x = x_estimar1))
cat("Estimación para X =", x_estimar1, "ft:\n")
## Estimación para X = 56 ft:
cat("Measured Depth estimado:", round(y_estimada1, 2), "ft\n\n")
## Measured Depth estimado: -63.9 ft
x_estimar2 <- round(max(pares$x), 2)
y_estimada2 <- predict(m_poli2, newdata = data.frame(x = x_estimar2))
cat("Estimación para X =", x_estimar2, "ft:\n")
## Estimación para X = 13450 ft:
cat("Measured Depth estimado:", round(y_estimada2, 2), "ft\n\n")
## Measured Depth estimado: 15212.42 ft
x_estimar3 <- 1500
y_estimada3 <- predict(m_poli2, newdata = data.frame(x = x_estimar3))
cat("Estimación para X =", x_estimar3, "ft:\n")
## Estimación para X = 1500 ft:
cat("Measured Depth estimado:", round(y_estimada3, 2), "ft\n")
## Measured Depth estimado: 1483.5 ft
Ecuacion <- paste0(
"y = ", round(b[1], 2),
" + (", round(b[2], 6), ")x",
" + (", round(b[3], 8), ")x²"
)
Tabla_resumen <- data.frame(
`Variable Independiente` = "Proposed Depth, ft",
`Variable Dependiente` = "Measured Depth, ft",
`Test Pearson` = round(r, 4),
`Coeficiente de determinación`= round(r2, 2),
`Ecuación del modelo` = Ecuacion,
check.names = FALSE
)
Tabla_resumen %>%
gt() %>%
tab_header(
title = md("**Tabla N°1**"),
subtitle = md("**Resumen del modelo de regresión polinómica (grado 2)**")
) %>%
tab_source_note(source_note = md("Autor: Grupo 1")) %>%
cols_align(align = "center", columns = everything()) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_title()
) %>%
tab_style(
style = list(cell_fill(color = col_encabezado), cell_text(color = "white", weight = "bold")),
locations = cells_column_labels()
) %>%
tab_style(
style = list(cell_fill(color = col_fila_alt)),
locations = cells_body(rows = 1)
) %>%
opt_table_outline(style = "solid", width = px(3), color = col_borde) %>%
tab_options(
table.border.top.color = col_borde,
table.border.bottom.color = col_borde,
table.border.top.style = "solid",
table.border.bottom.style = "solid",
column_labels.border.top.color = col_borde,
column_labels.border.bottom.color = col_borde,
column_labels.border.bottom.width = px(2),
heading.border.bottom.color = col_borde,
heading.border.bottom.width = px(2),
table_body.hlines.color = "#CBD5DE",
table_body.border.bottom.color = col_borde,
table.font.size = px(14),
data_row.padding = px(6)
)
| Tabla N°1 | ||||
| Resumen del modelo de regresión polinómica (grado 2) | ||||
| Variable Independiente | Variable Dependiente | Test Pearson | Coeficiente de determinación | Ecuación del modelo |
|---|---|---|---|---|
| Proposed Depth, ft | Measured Depth, ft | 0.9696 | 94.04 | y = -123.42 + (1.062634)x + (0.00000577)x² |
| Autor: Grupo 1 | ||||
Entre la profundidad propuesta
(Proposed Depth, X) y la profundidad
medida (Measured Depth, Y) existe una relación
polinómica de segundo grado cuya ecuación matemática es:
\[y = -123.42 + (1.062634)x + (0.0000058)x^2\]
Con una correlación de Pearson de 0.97 y un coeficiente de determinación de 94.04%, el modelo indica que la profundidad planificada en el permiso explica en gran medida la profundidad realmente alcanzada durante la perforación, con una ligera curvatura que un modelo puramente lineal no captura del todo.