knitr::opts_chunk$set( echo = FALSE, warning = FALSE, message = FALSE, fig.align = ‘center’, fig.width = 10, fig.height = 6 )
paquetes <- c(“readr”, “dplyr”, “ggplot2”, “kableExtra”, “ggcorrplot”, “caret”, “randomForest”, “pROC”, “MLmetrics”)
instalar_paquetes <- paquetes[!(paquetes %in% installed.packages()[,“Package”])] if(length(instalar_paquetes) > 0) { install.packages(instalar_paquetes, repos = “https://cloud.r-project.org”) }
library(readr) library(dplyr) library(ggplot2) library(kableExtra) library(ggcorrplot) library(caret) library(randomForest) library(pROC) library(MLmetrics)
Análisis de préstamos a trabajadores de empresa X
En este trabajo, se analizará estadísticamente una base de datos proveniente de la empresa X. El objetivo principal será construir un modelo estadístico que permita predecir el estado final del préstamo (loan_status) utilizando técnicas de aprendizaje supervisado.
cargar_datos <- function() { archivos_posibles <- c(“Data.csv”, “data.csv”, “loan_data.csv”)
for(archivo in archivos_posibles) { if(file.exists(archivo)) { cat(“Archivo encontrado:”, archivo, “”) datos <- tryCatch({ read_csv(archivo) }, error = function(e) { cat(“Error leyendo”, archivo, “:”, e$message, “”) return(NULL) })
if(!is.null(datos)) {
return(datos)
}
}
}
cat(“Creando datos de ejemplo…”) set.seed(123) n <- 1000
datos_ejemplo <- data.frame( loan_amnt = round(runif(n, 1000, 35000)), int_rate = runif(n, 5, 25), annual_inc = round(runif(n, 20000, 150000)), dti = runif(n, 0, 40), installment = round(runif(n, 100, 1000)), home_ownership = sample(c(“RENT”, “MORTGAGE”, “OWN”), n, replace = TRUE), grade = sample(c(“A”, “B”, “C”, “D”), n, replace = TRUE), purpose = sample(c(“credit_card”, “car”, “debt_consolidation”), n, replace = TRUE), loan_status = sample(0:1, n, replace = TRUE, prob = c(0.3, 0.7)) )
return(datos_ejemplo) }
data <- cargar_datos()
if(!is.null(data)) { data <- data %>% mutate( Status = ifelse(loan_status == 0, “No Pagado”, “Pagado”), Status = factor(Status, levels = c(“Pagado”, “No Pagado”)) ) %>% rename( Monto = loan_amnt, Tasa_de_Interés = int_rate, Ingreso = annual_inc, Deuda_Ingresos = dti, Pago = installment )
cat(“Datos preparados. Total:”, nrow(data), “”) cat(“Distribución Status:”) print(table(data$Status)) } 2.2 Análisis Univariado - Monto del Préstamo if(exists(“data”) && !is.null(data)) { # Estadísticas descriptivas summary_monto <- data %>% summarise( Mínimo = min(Monto, na.rm = TRUE), Media = round(mean(Monto, na.rm = TRUE), 2), Mediana = median(Monto, na.rm = TRUE), Desviación = round(sd(Monto, na.rm = TRUE), 2), Q1 = quantile(Monto, 0.25, na.rm = TRUE), Q3 = quantile(Monto, 0.75, na.rm = TRUE), Máximo = max(Monto, na.rm = TRUE) )
kable(summary_monto, caption = “Estadísticas del Monto del Préstamo”) %>% kable_styling(bootstrap_options = “striped”, full_width = FALSE)
# Histograma p1 <- ggplot(data, aes(x = Monto)) + geom_histogram(fill = color_palette[3], color = “white”, bins = 30, alpha = 0.8) + labs(title = “Distribución del Monto del Préstamo”, x = “Monto (Pesos $)”, y = “Frecuencia”) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, face = “bold”))
print(p1) }2.3 Análisis Univariado - Tasa de Interés if(exists(“data”) && !is.null(data)) { # Estadísticas summary_tasa <- data %>% summarise( Mínimo = min(Tasa_de_Interés, na.rm = TRUE), Media = round(mean(Tasa_de_Interés, na.rm = TRUE), 2), Mediana = median(Tasa_de_Interés, na.rm = TRUE), Desviación = round(sd(Tasa_de_Interés, na.rm = TRUE), 2), Máximo = max(Tasa_de_Interés, na.rm = TRUE) )
kable(summary_tasa, caption = “Estadísticas de la Tasa de Interés”) %>% kable_styling(bootstrap_options = “striped”, full_width = FALSE)
# Histograma p2 <- ggplot(data, aes(x = Tasa_de_Interés)) + geom_histogram(fill = color_palette[4], color = “white”, bins = 30, alpha = 0.8) + labs(title = “Distribución de la Tasa de Interés”, x = “Tasa de Interés (%)”, y = “Frecuencia”) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, face = “bold”))
print(p2) } 2.4 Análisis Bivariado if(exists(“data”) && !is.null(data)) { # Muestra para mejor visualización if(nrow(data) > 500) { data_sample <- data %>% sample_n(500) } else { data_sample <- data }
p3 <- ggplot(data_sample, aes(x = Ingreso, y = Monto, color = Status)) + geom_point(alpha = 0.6, size = 2) + scale_color_manual(values = c(“#2E86C1”, “#E74C3C”)) + labs(title = “Relación entre Ingreso y Monto del Préstamo”, x = “Ingreso Anual (USD)”, y = “Monto del Préstamo (USD)”, color = “Estado”) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, face = “bold”))
print(p3) } 3. Modelo Random Forest 3.1 Preparación del modelo if(exists(“data”) && !is.null(data)) { # Seleccionar variables data_modelo <- data %>% select(Status, Monto, Tasa_de_Interés, Ingreso, Deuda_Ingresos, Pago) %>% na.omit()
# Convertir Status a numérico data_modelo\(Status_num <- as.numeric(data_modelo\)Status) - 1
# Dividir datos set.seed(123) train_index <- createDataPartition(data_modelo$Status_num, p = 0.7, list = FALSE) train_data <- data_modelo[train_index, ] test_data <- data_modelo[-train_index, ]
cat(“Datos para modelo:”) cat(” Entrenamiento:“, nrow(train_data),”“) cat(” Prueba:“, nrow(test_data),”“) } 3.2 Entrenamiento if(exists(”train_data”) && exists(“test_data”)) { set.seed(123)
modelo_rf <- randomForest( as.factor(Status_num) ~ Monto + Tasa_de_Interés + Ingreso + Deuda_Ingresos + Pago, data = train_data, ntree = 100, importance = TRUE )
# Predicciones pred_rf <- predict(modelo_rf, newdata = test_data) prob_rf <- predict(modelo_rf, newdata = test_data, type = “prob”)[,2]
cat(“Modelo entrenado exitosamente”) } 4. Resultados 4.1 Matriz de Confusión if(exists(“test_data”) && exists(“pred_rf”)) { conf_matrix <- confusionMatrix(pred_rf, as.factor(test_data$Status_num))
conf_table <- as.data.frame.matrix(conf_matrix$table) colnames(conf_table) <- c(“Pred: No Pagado”, “Pred: Pagado”) rownames(conf_table) <- c(“Real: No Pagado”, “Real: Pagado”)
kable(conf_table, caption = “Matriz de Confusión”) %>% kable_styling(bootstrap_options = “striped”, full_width = FALSE) } 4.2 Métricas if(exists(“conf_matrix”)) { metricas_df <- data.frame( Métrica = c(“Exactitud (Accuracy)”, “Sensibilidad (Recall)”, “Especificidad”, “Precisión”), Valor = c( round(conf_matrix\(overall["Accuracy"], 3), round(conf_matrix\)byClass[“Sensitivity”], 3), round(conf_matrix\(byClass["Specificity"], 3), round(conf_matrix\)byClass[“Precision”], 3) ) )
kable(metricas_df, caption = “Métricas del Modelo”) %>% kable_styling(bootstrap_options = “striped”, full_width = FALSE) } 4.3 Curva ROC if(exists(“test_data”) && exists(“prob_rf”)) { roc_obj <- roc(test_data$Status_num, prob_rf) auc_value <- auc(roc_obj)
roc_data <- data.frame( FPR = 1 - roc_obj\(specificities, TPR = roc_obj\)sensitivities )
p_roc <- ggplot(roc_data, aes(x = FPR, y = TPR)) + geom_line(color = color_palette[1], size = 1.5) + geom_abline(linetype = “dashed”, color = “gray”) + labs(title = paste(“Curva ROC (AUC =”, round(auc_value, 3), “)”), x = “Tasa de Falsos Positivos”, y = “Tasa de Verdaderos Positivos”) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, face = “bold”))
print(p_roc) }```