Este documento recorre, de forma breve y aplicada,
las 9 fases clásicas del proceso KDD utilizando un caso de
riesgo crediticio bancario: predecir si un cliente será
un buen o mal pagador (Good /
Bad).
Contexto de negocio: Un banco alemán otorga créditos personales y necesita un modelo que apoye la decisión de aprobación, minimizando el riesgo de impago (default).
Objetivo analítico: Construir un modelo predictivo que clasifique a un solicitante de crédito como buen riesgo (Good) o mal riesgo (Bad), en función de sus características socioeconómicas y del crédito solicitado.
Pregunta de negocio: ¿Qué variables del cliente y del crédito permiten anticipar el impago, y cómo se traduce esto en una regla de decisión simple para el analista de crédito?
Usamos el dataset GermanCredit, incluido en el paquete
caret. Contiene 1,000 solicitudes de crédito reales
(anonimizadas), con variables financieras, demográficas y del historial
crediticio, y la variable objetivo Class (Good/Bad).
data("GermanCredit")
cat("Dimensiones del dataset:", dim(GermanCredit)[1], "filas x",
dim(GermanCredit)[2], "columnas\n")
## Dimensiones del dataset: 1000 filas x 62 columnas
# Vista rápida de la variable objetivo
table(GermanCredit$Class)
##
## Bad Good
## 300 700
prop.table(table(GermanCredit$Class)) * 100
##
## Bad Good
## 30 70
Lectura ejecutiva: el dataset está desbalanceado (~70% Good / 30% Bad), algo típico en riesgo crediticio y que debe considerarse al evaluar el modelo.
Verificamos valores faltantes, duplicados y variables sin varianza (que no aportan información).
# 1. Valores faltantes
sum(is.na(GermanCredit))
## [1] 0
# 2. Duplicados
sum(duplicated(GermanCredit))
## [1] 0
# 3. Variables con varianza casi nula (no discriminan)
nzv <- nearZeroVar(GermanCredit, saveMetrics = TRUE)
vars_nzv <- rownames(nzv[nzv$nzv == TRUE, ])
length(vars_nzv)
## [1] 13
# Eliminamos esas variables de baja utilidad
credit_clean <- GermanCredit %>% select(-all_of(vars_nzv))
dim(credit_clean)
## [1] 1000 49
Lectura ejecutiva: el dataset no tiene NAs ni duplicados (ya viene curado), pero sí 13 variables casi constantes que se descartan por no aportar poder predictivo.
Seleccionamos un subconjunto interpretable de variables clave para el ejemplo (reducción dimensional guiada por negocio) y transformamos la variable objetivo a factor con niveles explícitos.
vars_negocio <- c("Duration", "Amount", "InstallmentRatePercentage", "Age",
"NumberExistingCredits", "ResidenceDuration", "Class")
credit_model <- credit_clean %>% select(all_of(vars_negocio))
# Aseguramos el factor de la variable objetivo con niveles legibles
credit_model$Class <- factor(credit_model$Class, levels = c("Good", "Bad"))
str(credit_model)
## 'data.frame': 1000 obs. of 7 variables:
## $ Duration : int 6 48 12 42 24 36 24 36 12 30 ...
## $ Amount : int 1169 5951 2096 7882 4870 9055 2835 6948 3059 5234 ...
## $ InstallmentRatePercentage: int 4 2 2 2 3 2 3 2 2 4 ...
## $ Age : int 67 22 49 45 53 35 53 35 61 28 ...
## $ NumberExistingCredits : int 2 1 1 1 2 1 1 1 1 2 ...
## $ ResidenceDuration : int 4 2 3 4 4 4 4 2 4 2 ...
## $ Class : Factor w/ 2 levels "Good","Bad": 1 2 1 1 2 1 1 1 1 2 ...
# Correlación entre variables numéricas (detectar redundancia)
corrplot(cor(credit_model %>% select(-Class)), method = "number", type = "upper",
tl.cex = 0.8, number.cex = 0.7)
Lectura ejecutiva: reducimos de decenas de variables dummy a 6 variables de negocio directamente interpretables (monto, plazo, edad, cuotas, créditos previos, antigüedad de residencia). No se observan correlaciones fuertes que obliguen a eliminar variables adicionales.
Tarea seleccionada: Clasificación supervisada binaria.
Se elige clasificación (y no clustering o asociación) porque contamos
con la variable objetivo etiquetada (Class) y el negocio
necesita una predicción accionable (aprobar/rechazar),
no solo segmentos o reglas de asociación.
Algoritmo seleccionado: Árbol de Decisión (CART /
rpart).
Justificación para un contexto bancario:
Dividimos en entrenamiento/prueba y entrenamos el árbol de decisión.
set.seed(123)
idx <- createDataPartition(credit_model$Class, p = 0.7, list = FALSE)
train <- credit_model[idx, ]
test <- credit_model[-idx, ]
modelo_arbol <- rpart(Class ~ ., data = train, method = "class",
control = rpart.control(maxdepth = 4, cp = 0.01))
rpart.plot(modelo_arbol, type = 3, extra = 104, fallen.leaves = TRUE,
main = "Árbol de Decisión: Riesgo Crediticio", cex = 0.7)
Lectura ejecutiva: el árbol resultante muestra de forma visual las combinaciones de variables (duración del crédito, monto, edad) que separan a los buenos de los malos pagadores, con el porcentaje de casos en cada nodo.
Evaluamos el modelo sobre el conjunto de prueba y revisamos qué variables pesan más.
pred <- predict(modelo_arbol, test, type = "class")
matriz_conf <- confusionMatrix(pred, test$Class, positive = "Bad")
matriz_conf
## Confusion Matrix and Statistics
##
## Reference
## Prediction Good Bad
## Good 199 73
## Bad 11 17
##
## Accuracy : 0.72
## 95% CI : (0.6655, 0.7701)
## No Information Rate : 0.7
## P-Value [Acc > NIR] : 0.2456
##
## Kappa : 0.17
##
## Mcnemar's Test P-Value : 2.821e-11
##
## Sensitivity : 0.18889
## Specificity : 0.94762
## Pos Pred Value : 0.60714
## Neg Pred Value : 0.73162
## Prevalence : 0.30000
## Detection Rate : 0.05667
## Detection Prevalence : 0.09333
## Balanced Accuracy : 0.56825
##
## 'Positive' Class : Bad
##
# Importancia de variables
importancia <- modelo_arbol$variable.importance
barplot(sort(importancia, decreasing = TRUE), las = 2, cex.names = 0.8,
main = "Importancia de Variables", col = "steelblue")
Lectura ejecutiva:
Bad es
clave: interesa detectar bien a los clientes de alto riesgo, aunque el
dataset esté desbalanceado.Duration (plazo del crédito) y Amount
(monto) resultan las variables más predictivas, coincidiendo con la
intuición de negocio: créditos largos y de monto alto concentran más
riesgo.Conocimiento accionable extraído:
Consolidación técnica: el modelo se guarda para su uso en producción (por ejemplo, integrado a un sistema de scoring o a un dashboard de aprobación).
saveRDS(modelo_arbol, "modelo_riesgo_credito.rds")
cat("Modelo guardado como 'modelo_riesgo_credito.rds' para su despliegue.\n")
## Modelo guardado como 'modelo_riesgo_credito.rds' para su despliegue.
Próximos pasos sugeridos para el negocio:
| Fase | Resultado clave |
|---|---|
| 1. Comprensión del dominio | Objetivo: predecir riesgo crediticio |
| 2. Selección de datos | Dataset GermanCredit (1,000 registros) |
| 3. Limpieza | Sin NAs/duplicados; se eliminan variables casi constantes |
| 4. Reducción/Transformación | 6 variables de negocio interpretables |
| 5. Tarea de minería | Clasificación supervisada binaria |
| 6. Algoritmo | Árbol de decisión (CART) |
| 7. Minería de datos | Entrenamiento del árbol sobre 70% de los datos |
| 8. Evaluación | Matriz de confusión + importancia de variables |
| 9. Consolidación | Modelo exportado (.rds) + reglas de negocio accionables |