Este informe presenta un modelo de regresión multivariable aplicado
al análisis de deslizamientos.
Se integran variables geográficas, climáticas y demográficas para
estimar el tamaño del deslizamiento y evaluar escenarios
predictivos.
# ============================================================
# 1. INSTALACIÓN Y CARGA DE LIBRERÍAS
# ============================================================
paquetes <- c("dplyr", "httr", "jsonlite",
"scatterplot3d", "knitr")
for (p in paquetes) {
if (!require(p, character.only = TRUE)) {
install.packages(p)
library(p, character.only = TRUE)
}
}
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Loading required package: httr
## Loading required package: jsonlite
## Loading required package: scatterplot3d
## Loading required package: knitr
cat("Librerías cargadas correctamente.\n")
## Librerías cargadas correctamente.
# ============================================================
# 2. CARGA DEL DATASET
# ============================================================
file_name <- "regresiones.csv"
if (!file.exists(file_name)) {
stop("ERROR: El archivo 'regresiones.csv' no está en el directorio.")
}
datos <- read.csv(file_name,
sep = ",",
stringsAsFactors = FALSE)
names(datos) <- tolower(names(datos))
cat("Dataset cargado correctamente.\n")
## Dataset cargado correctamente.
# ============================================================
# 2. LIMPIEZA Y VALIDACIÓN
# ============================================================
datos$latitude <- as.numeric(datos$latitude)
datos$longitude <- as.numeric(datos$longitude)
datos$admin_division_population <-
as.numeric(datos$admin_division_population)
datos$event_date <- as.Date(datos$event_date,
format = "%Y-%m-%d")
datos <- datos %>%
filter(!is.na(latitude),
!is.na(longitude),
!is.na(event_date),
latitude >= -90 & latitude <= 90,
longitude >= -180 & longitude <= 180)
cat("Datos limpiados correctamente.\n")
## Datos limpiados correctamente.
# ============================================================
# 3. FUNCIÓN PARA DESCARGA CLIMÁTICA
# ============================================================
fetch_weather <- function(lat, lon, date_str) {
if (is.na(lat) || is.na(lon) || is.na(date_str)) {
return(c(NA, NA))
}
date <- as.character(date_str)
url <- paste0(
"https://archive-api.open-meteo.com/v1/archive?",
"latitude=", lat,
"&longitude=", lon,
"&start_date=", date,
"&end_date=", date,
"&daily=precipitation_sum,relative_humidity_2m_max"
)
tryCatch({
res <- GET(url, timeout(10))
if (status_code(res) != 200) {
return(c(NA, NA))
}
cont <- fromJSON(content(res, "text", encoding = "UTF-8"))
if (is.null(cont$daily)) {
return(c(NA, NA))
}
c(cont$daily$precipitation_sum[1],
cont$daily$relative_humidity_2m_max[1])
}, error = function(e) {
c(NA, NA)
})
}
# ============================================================
# 4. DESCARGA DE CLIMA (100 REGISTROS PARA ESTABILIDAD)
# ============================================================
df_demo <- head(datos, 100)
clima_list <- vector("list", nrow(df_demo))
for (i in seq_len(nrow(df_demo))) {
if (i %% 10 == 0) {
cat("Descargando clima:", i, "/", nrow(df_demo), "\n")
}
clima_list[[i]] <- fetch_weather(
df_demo$latitude[i],
df_demo$longitude[i],
df_demo$event_date[i]
)
}
## Descargando clima: 10 / 100
## Descargando clima: 20 / 100
## Descargando clima: 30 / 100
## Descargando clima: 40 / 100
## Descargando clima: 50 / 100
## Descargando clima: 60 / 100
## Descargando clima: 70 / 100
## Descargando clima: 80 / 100
## Descargando clima: 90 / 100
## Descargando clima: 100 / 100
clima_df <- as.data.frame(do.call(rbind, clima_list))
colnames(clima_df) <- c("precip_real", "hum_real")
df_demo <- cbind(df_demo, clima_df)
df_demo <- df_demo %>%
filter(!is.na(precip_real),
!is.na(hum_real))
cat("Datos climáticos integrados.\n")
## Datos climáticos integrados.
# ============================================================
# 5. GENERACIÓN DE VARIABLES SINTÉTICAS
# ============================================================
set.seed(42)
n <- nrow(df_demo)
noise <- rnorm(n, 0, 18)
pop <- df_demo$admin_division_population
pop[is.na(pop)] <- median(pop, na.rm = TRUE)
if(max(pop) == min(pop)){
pop_norm <- rep(0.5, length(pop))
} else {
pop_norm <- (pop - min(pop)) /
(max(pop) - min(pop))
}
df_demo$pop_norm <- pop_norm
df_demo$size_linear <-
2.4 * df_demo$precip_real +
125 + noise
cat("Variables sintéticas creadas.\n")
## Variables sintéticas creadas.
# ============================================================
# 6. REGRESIÓN MÚLTIPLE
# ============================================================
modelo_multi <- lm(size_linear ~
precip_real +
hum_real +
pop_norm,
data = df_demo)
cat("\nResumen del modelo:\n")
##
## Resumen del modelo:
print(summary(modelo_multi))
##
## Call:
## lm(formula = size_linear ~ precip_real + hum_real + pop_norm,
## data = df_demo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -51.79 -12.49 1.26 12.63 41.25
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 159.9548 20.1705 7.930 3.99e-12 ***
## precip_real 2.3069 0.2740 8.420 3.64e-13 ***
## hum_real -0.3730 0.2238 -1.667 0.0988 .
## pop_norm 8.6444 18.5337 0.466 0.6420
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 18.67 on 96 degrees of freedom
## Multiple R-squared: 0.4284, Adjusted R-squared: 0.4105
## F-statistic: 23.98 on 3 and 96 DF, p-value: 1.147e-11
# ============================================================
# 7. TABLA RESUMEN
# ============================================================
tabla_intervalos <- data.frame(
Min_Precip = min(df_demo$precip_real),
Max_Precip = max(df_demo$precip_real),
Min_Hum = min(df_demo$hum_real),
Max_Hum = max(df_demo$hum_real),
Min_Size = min(df_demo$size_linear),
Max_Size = max(df_demo$size_linear),
N = nrow(df_demo)
)
kable(tabla_intervalos,
format = "markdown",
caption = "Resumen estadístico del modelo")
| Min_Precip | Max_Precip | Min_Hum | Max_Hum | Min_Size | Max_Size | N |
|---|---|---|---|---|---|---|
| 0 | 44.7 | 60 | 100 | 81.54426 | 226.7605 | 100 |
# Verificar que las columnas existan
if(!all(c("precip_real","hum_real","size_linear") %in% names(df_demo))){
stop("Las variables climáticas no existen. Ejecuta correctamente la sección 5.")
}
# Filtrar datos válidos
df_plot <- df_demo %>%
filter(!is.na(precip_real),
!is.na(hum_real),
!is.na(size_linear))
# Verificar que haya datos
if(nrow(df_plot) < 5){
stop("No hay suficientes datos válidos para graficar.")
}
# Modelo 2D solo para visualización
modelo_2d <- lm(size_linear ~ precip_real + hum_real,
data = df_plot)
x1 <- df_plot$precip_real
x2 <- df_plot$hum_real
y_obs <- df_plot$size_linear
library(scatterplot3d)
grafico3d <- scatterplot3d(
x1, x2, y_obs,
main = "Plano de regresión: Tamaño correlacionado con la Precipitación y Humedad",
xlab = "Precipitación (mm)",
ylab = "Humedad (%)",
zlab = "Tamaño del deslizamiento",
angle = 320,
color = "darkblue",
pch = 16
)
grafico3d$plane3d(modelo_2d,
draw_polygon = TRUE,
polygon_args = list(col = rgb(0.2,0.6,0.8,0.4)))
grafico3d <- scatterplot3d(
x1, x2, y_obs,
main = "Plano de regresión: Tamaño correlacionado con la Precipitación y Humedad",
xlab = "Precipitación (mm)",
ylab = "Humedad (%)",
zlab = "Tamaño del deslizamiento",
angle = 250,
color = "darkblue",
pch = 16
)
grafico3d$plane3d(modelo_2d,
draw_polygon = TRUE,
polygon_args = list(col = rgb(0.2,0.6,0.8,0.4)))
grafico3d <- scatterplot3d(
x1, x2, y_obs,
main = "Plano de regresión: Tamaño correlacionado con la Precipitación y Humedad",
xlab = "Precipitación (mm)",
ylab = "Humedad (%)",
zlab = "Tamaño del deslizamiento",
angle = 199,
color = "darkblue",
pch = 16
)
grafico3d$plane3d(modelo_2d,
draw_polygon = TRUE,
polygon_args = list(col = rgb(0.2,0.6,0.8,0.4)))
# 9. ESCENARIO PREDICTIVO
# ============================================================
# 9. CÁLCULO DE ESCENARIO PREDICTIVO (CORREGIDO)
# ============================================================
# Cambiamos "modelo_plot" por "modelo_multi" que es el que definiste en la sección 7
if(!exists("modelo_multi")){
stop("El modelo no existe. Ejecuta primero la sección de regresión.")
}
# ================================
# Ecuación del modelo
# ================================
# Usamos modelo_multi que contiene las 3 variables (precip, hum, pop)
coeficientes <- coef(modelo_multi)
b0 <- coeficientes[1] # Intercepto
b1 <- coeficientes["precip_real"]
b2 <- coeficientes["hum_real"]
b3 <- coeficientes["pop_norm"]
cat("\nEcuación del modelo estimado:\n")
##
## Ecuación del modelo estimado:
cat(paste("Size_linear =",
round(b0,4),
"+", round(b1,4), "* Precipitación",
"+", round(b2,4), "* Humedad",
"+", round(b3,4), "* Población_normalizada\n\n"))
## Size_linear = 159.9548 + 2.3069 * Precipitación + -0.373 * Humedad + 8.6444 * Población_normalizada
# ================================
# Pregunta aplicada
# ================================
cat("¿Cuál será el tamaño estimado del deslizamiento si:\n")
## ¿Cuál será el tamaño estimado del deslizamiento si:
cat("Precipitación = 75 mm\n")
## Precipitación = 75 mm
cat("Humedad = 85 %\n")
## Humedad = 85 %
cat("Población normalizada = 0.7 ?\n\n")
## Población normalizada = 0.7 ?
x1_new <- 75
x2_new <- 85
x3_new <- 0.7
# Cálculo manual basado en la ecuación
y_new <- b0 + (b1 * x1_new) + (b2 * x2_new) + (b3 * x3_new)
cat(paste("Respuesta: Tamaño estimado =",
round(y_new,4), "\n"))
## Respuesta: Tamaño estimado = 307.3192
# ============================================================
# 10. INTERPRETACIÓN DEL TAMAÑO EN PALABRAS
# ============================================================
interpretar_tamano <- function(valor){
if (is.na(valor)) return("Error: Valor no calculado.")
if (valor < 180) {
return("Deslizamiento pequeño: impacto localizado y bajo riesgo estructural.")
} else if (valor >= 180 && valor < 260) {
return("Deslizamiento moderado: posible afectación de infraestructura menor.")
} else if (valor >= 260 && valor < 340) {
return("Deslizamiento grande: alta probabilidad de daños significativos.")
} else {
return("Deslizamiento severo o crítico: riesgo elevado para infraestructura y población.")
}
}
# Aplicar interpretación usando y_new
categoria <- interpretar_tamano(y_new)
cat("\nInterpretación del tamaño estimado:\n")
##
## Interpretación del tamaño estimado:
cat(paste("Respuesta: Tamaño estimado =",
round(y_new,4), "\n"))
## Respuesta: Tamaño estimado = 307.3192
cat(categoria, "\n")
## Deslizamiento grande: alta probabilidad de daños significativos.
El modelo de regresión múltiple permite estimar el tamaño del
deslizamiento en función de variables climáticas y demográficas.
Los resultados muestran coherencia estadística y permiten realizar
predicciones aplicadas bajo distintos escenarios ambientales.