El sector financiero desempeña un papel fundamental para la economía, debido a que permite la captación de recursos, el acceso a créditos y la promoción de ahorro por parte de la población. Razón por la que funciona como un motor para el desarrollo económico, el cual aborda cómo la banca, el mercado de capitales y la inversión han sido y seguirán siendo ejes fundamentales en el progreso de Colombia y América Latina. Dentro de este sector hay una alta competencia debido a una gran oferta de entidades financieras, razón por la que dichas entidades utilizan diferentes estrategias de marketing para ofrecer productos financieros a sus clientes y fidelizar con ellos, entre ellos los depósitos a término, los cuales representan una alternativa de inversión y ahorro que generará rentabilidad mediante el pago de intereses.
En los últimos años, especialmente después de la pandemia de COVID-19, los bancos han incrementado el uso de campañas vía telefónica y herramientas de análisis de datos para así poder determinar posibles clientes potenciales y mejorar la efectividad de sus estrategias comerciales, en un contexto de rápida digitalización financiera (Galdos-Fisher et al., 2024). No obstante, no todos los clientes aceptan este tipo de productos financieros, debido a que su decisión puede tener múltiples factores económicos, demográficos y financieros, como el saldo de sus cuentas, nivel educativo, la existencia de préstamos o la duración del contacto realizado por el banco.
En este contexto, resulta relevante analizar las variables que influyen en la probabilidad de que un cliente acepte o no un depósito ofrecido por una entidad financiera. Comprender estos factores permite identificar patrones de comportamiento de los usuarios y aporta información útil para optimizar las campañas de marketing bancario y mejorar la toma de decisiones comerciales.
Por esta razón, en el presente trabajo se desarrolló un análisis estadístico y predictivo utilizando una base de datos bancaria denominada bank.csv. Inicialmente, se realizó un proceso de transformación y análisis descriptivo de las variables más relevantes. Posteriormente, se implementaron modelos de clasificación como K-Nearest Neighbors (KNN) y regresión logística (LOGIT), con el objetivo de predecir la aceptación de depósitos bancarios por parte de los clientes y evaluar el desempeño predictivo de cada modelo.
La base de datos utilizada contiene información de clientes bancarios contactados durante campañas de marketing financiero. La variable principal de estudio fue deposit, la cual indica si el cliente aceptó o no el producto financiero ofrecido. Posteriormente, esta variable fue transformada en una variable binaria denominada Y, asignando:
| Valor | Interpretación |
|---|---|
| 1 | El cliente aceptó el depósito |
| 0 | El cliente no aceptó el depósito |
Adicionalmente, se creó la variable categórica Y_f, utilizada principalmente para la interpretación de resultados y la evaluación de los modelos mediante matrices de confusión.
Las variables utilizadas para explicar la aceptación del depósito bancario fueron las siguientes:
duration: “duración de la llamada realizada al cliente”, se eligio esta variable porque, lógicamente, si un cliente se queda más tiempo hablando con el asesor, es porque tiene interés en el producto. Es un indicador directo de qué tan efectiva fue la llamada.
balance: “balance promedio de la cuenta bancaria”, se incluyo porque el saldo que tiene una persona en su cuenta dice mucho de su capacidad para invertir. Si alguien tiene un saldo muy bajo o en cero, es muy poco probable que quiera abrir un depósito a término.
housing: “indicador de crédito hipotecario”, se escogio esta variable porque el saldo que tiene una persona en su cuenta dice mucho de su capacidad para invertir. Si alguien tiene un saldo muy bajo o en cero, es muy poco probable que quiera abrir un depósito a término.
loan: “indicador de préstamo personal”, Al igual que la vivienda, tener otros préstamos reduce el dinero libre que le queda al cliente a fin de mes. Sospechamos que quienes tienen deudas activas aceptarán menos los depósitos.
Education: “nivel educativo”, Decidimos incluir la educación porque el nivel de estudio suele influir en cómo las personas manejan sus ahorros. Queremos comprobar si las personas con más estudios están más abiertas a este tipo de inversiones financieras.
Las variables housing y loan fueron transformadas a formato binario (0 y 1) con el fin de poder utilizarlas en los modelos de clasificación. Este proceso permite representar de manera numérica si el cliente cuenta o no con un crédito hipotecario o un préstamo personal. En este caso, el valor 1 indica la presencia del producto financiero y el valor 0 su ausencia, facilitando así el análisis y la aplicación de los modelos predictivos.
# Base de datos
datos <- read.csv("bank.csv", sep = ";")
names(datos)
## [1] "age" "job" "marital" "education" "default" "balance"
## [7] "housing" "loan" "contact" "day" "month" "duration"
## [13] "campaign" "pdays" "previous" "poutcome" "deposit"
head(datos)
## age job marital education default balance housing loan contact day
## 1 59 admin. married secondary no 2343 yes no unknown 5
## 2 56 admin. married secondary no 45 no no unknown 5
## 3 41 technician married secondary no 1270 yes no unknown 5
## 4 55 services married secondary no 2476 yes no unknown 5
## 5 54 admin. married tertiary no 184 no no unknown 5
## 6 42 management single tertiary no 0 yes yes unknown 5
## month duration campaign pdays previous poutcome deposit
## 1 may 1042 1 -1 0 unknown yes
## 2 may 1467 1 -1 0 unknown yes
## 3 may 1389 1 -1 0 unknown yes
## 4 may 579 1 -1 0 unknown yes
## 5 may 673 2 -1 0 unknown yes
## 6 may 562 2 -1 0 unknown yes
# Variable dependiente
datos$Y <- ifelse(datos$deposit == "yes", 1, 0)
datos$Y_f <- factor(datos$Y,
levels = c(0,1),
labels = c("No","Si"))
table(datos$Y_f)
##
## No Si
## 5873 5289
# Variables binarias
datos$housing <- ifelse(datos$housing == "yes", 1, 0)
datos$loan <- ifelse(datos$loan == "yes", 1, 0)
# Variables categoricas
datos$education <- as.factor(datos$education)
datos$job <- as.factor(datos$job)
Como parte del análisis exploratorio, se calcularon medidas descriptivas para las variables numéricas duration y balance, incluyendo media, mediana, moda, varianza, desviación estándar, cuartiles y coeficiente de variación.
Asimismo, se construyeron histogramas, diagramas de caja y gráficos de barras para analizar la distribución de los datos, detectar posibles valores atípicos y evaluar el comportamiento de las variables categóricas.
Para el análisis de las variables usamos diferentes medios, para el análisis de la variable seleccionada llamada duration se realizó la gráfica boxplot, en la cual se identificó patrones de una tendencia donde la comunicación con los usuario son cortas, sin embargo , hay muchos puntos atípicos donde la variabilidad se puede ver sesgada, por lo tanto la duración interactiva del asesor y el cliente, podría desempeñar un papel importante en la aceptación del depósito.
## Variable: duration
X <- datos$duration
# Media
mean(X, na.rm = TRUE)
## [1] 371.9938
# Mediana
median(X, na.rm = TRUE)
## [1] 255
# Moda
library(modeest)
mlv(X, method = "mfv")[1]
## [1] 97
# Varianza y desviación estandar
var(X, na.rm = TRUE)
## [1] 120498.1
sd(X, na.rm = TRUE)
## [1] 347.1284
# Cuartiles
quantile(X, 0.25, na.rm = TRUE)
## 25%
## 138
quantile(X, 0.50, na.rm = TRUE)
## 50%
## 255
quantile(X, 0.75, na.rm = TRUE)
## 75%
## 496
# Coeficiente de variación
(sd(X, na.rm = TRUE) / mean(X, na.rm = TRUE)) * 100
## [1] 93.31563
library(ggplot2)
library(plotly)
grafico1 <- ggplot(datos, aes(x = duration)) +
geom_histogram() +
labs(title = "Distribución de Duration",
x = "Duration")
ggplotly(grafico1)
grafico3 <- ggplot(datos, aes(y = duration)) +
geom_boxplot(fill = "lightgreen") +
labs(title = "Boxplot Duration",
y = "Duration")
ggplotly(grafico3)
Por otro lado, la variable balance nos enfrentamos nuevamente a la variabilidad alta de los datos, respecto ya que no presentan como tan una tendencia normal, en cambio los valores se concentran en valores bajos y cercanos a cero, más sin embargo, encontramos datos que generan una cola, siendo excesivamente alto con respecto a la conglomeración que se presenta en la parte izquierda, denominados datos atípicos, esto tenderá a una dispersión alta.
## Variable: balance
X <- datos$balance
mean(X, na.rm = TRUE)
## [1] 1528.539
median(X, na.rm = TRUE)
## [1] 550
mlv(X, method = "mfv")[1]
## [1] 0
var(X, na.rm = TRUE)
## [1] 10403291
sd(X, na.rm = TRUE)
## [1] 3225.413
quantile(X, 0.25, na.rm = TRUE)
## 25%
## 122
quantile(X, 0.50, na.rm = TRUE)
## 50%
## 550
quantile(X, 0.75, na.rm = TRUE)
## 75%
## 1708
(sd(X, na.rm = TRUE) / mean(X, na.rm = TRUE)) * 100
## [1] 211.0129
grafico2 <- ggplot(datos, aes(x = balance)) +
geom_histogram(bins = 30,
fill = "lightgreen",
color = "black") +
labs(title = "Distribución de Balance",
x = "Balance",
y = "Frecuencia")
ggplotly(grafico2)
grafico4 <- ggplot(datos, aes(y = balance)) +
geom_boxplot(fill = "lightgreen") +
labs(title = "Boxplot Balance",
y = "Balance")
ggplotly(grafico4)
Para el análisis de las variables categóricas se presentó el histograma comparando con si y no en las variables Depósito y Crédito Hipotecario lo que nos permite ver, cual es la diferencia entre las variables, son variables que se encuentran rozando la igualdad sin embargo, hay diferencias, como en el caso de los depósitos se percibe que la demanda no es tanta como el rechazo a estos, por otro lado los créditos sigue esta misma dinámica.
Observamos también por medio de la variable educación que la cantidad de personas que se encuentran con un nivel educativo secundaria es visiblemente elevado con respecto a los otros, siendo un aproximado de 50% de los usuarios de la base de datos.
# Frecuencias Y_f
table(datos$Y_f)
##
## No Si
## 5873 5289
prop.table(table(datos$Y_f))*100
##
## No Si
## 52.61602 47.38398
grafico_y <- ggplot(datos, aes(x = Y_f)) +
geom_bar(fill = "skyblue",
color = "black") +
labs(title = "Distribución de depósitos",
x = "Depósito",
y = "Frecuencia")
ggplotly(grafico_y)
# Frecuencias housing
table(datos$housing)
##
## 0 1
## 5881 5281
prop.table(table(datos$housing))*100
##
## 0 1
## 52.68769 47.31231
grafico_housing <- ggplot(datos,
aes(x = factor(housing))) +
geom_bar(fill = "skyblue",
color = "black") +
labs(title = "Crédito hipotecario",
x = "Housing",
y = "Frecuencia")
ggplotly(grafico_housing)
Finalmente, el análisis de las variables loan se observa que la cantidad de usuarios que toman un prestamos es muy escaso, con respecto a los que no lo toman, siendo muy alta la probabilidad que no lo tomen.
# Frecuencias loan
table(datos$loan)
##
## 0 1
## 9702 1460
prop.table(table(datos$loan))*100
##
## 0 1
## 86.91991 13.08009
grafico_loan <- ggplot(datos,
aes(x = factor(loan))) +
geom_bar(fill = "lightgreen",
color = "black") +
labs(title = "Préstamos",
x = "Loan",
y = "Frecuencia")
ggplotly(grafico_loan)
Con el propósito de comprender el comportamiento de las variables incluidas en el estudio, se realizaron análisis descriptivos utilizando medidas de tendencia central, dispersión y representaciones gráficas elaboradas con las librerías ggplot2 y plotly.
Los histogramas permitieron identificar la distribución de las variables cuantitativas, mientras que los diagramas de caja facilitaron la detección de valores atípicos y niveles de dispersión. Asimismo, los gráficos de barras permitieron analizar la distribución de las variables categóricas y de la variable objetivo asociada a la aceptación del depósito bancario.
El primer modelo implementado fue K-Nearest Neighbors (KNN), un algoritmo de clasificación no paramétrico basado en la similitud entre observaciones.
La base de datos fue dividida en:
70% para entrenamiento 30% para prueba
Posteriormente, las variables independientes fueron estandarizadas mediante la función scale(), debido a que el algoritmo KNN utiliza distancias entre observaciones y es sensible a diferencias de escala.
Con el fin de encontrar el mejor desempeño del modelo, se evaluaron valores de ( k ) entre 1 y 50, seleccionando el valor que produjo la mayor precisión sobre el conjunto de prueba.
dummies_job <- model.matrix(~ job - 1, data = datos)
dummies_education <- model.matrix(~ education - 1, data = datos)
datos_knn <- cbind(
datos[, c("Y","Y_f","duration","balance","housing","loan")],
dummies_job,
dummies_education
)
datos_knn <- na.omit(datos_knn)
# Train
set.seed(28)
idx <- createDataPartition(datos_knn$Y_f, p=0.75, list=FALSE)
train_knn <- datos_knn[idx,]
test_knn <- datos_knn[-idx,]
# KNN
X_train <- train_knn[,-c(1,2)]
Y_train <- train_knn$Y_f
X_test <- test_knn[,-c(1,2)]
Y_test <- test_knn$Y_f
# Escalar correctamente
X_train <- scale(X_train)
media <- attr(X_train,"scaled:center")
sdv <- attr(X_train,"scaled:scale")
X_test <- scale(X_test, center=media, scale=sdv)
# Buscar mejor k
k <- 1:50
resultado <- data.frame(k, precision=0)
for(i in k){
pred <- knn(train=X_train, test=X_test, cl=Y_train, k=i)
resultado$precision[i] <- mean(pred == Y_test)
}
# Gráfico
ggplot(resultado, aes(k, precision)) + geom_line()
mejor_k <- resultado$k[which.max(resultado$precision)]
# Modelo final
pred_knn <- knn(train=X_train, test=X_test, cl=Y_train, k=mejor_k)
cm_knn <- confusionMatrix(pred_knn, Y_test, positive="Si")
accuracy_knn <- cm_knn$overall["Accuracy"]
El segundo modelo implementado fue la Regresión Logística, utilizada para estimar la probabilidad de aceptación del depósito bancario. La probabilidad de aceptación se modeló mediante la función logística:
\[P(Y=1) = \frac{1}{1 + e^{-z}}\] Donde la combinación lineal de las variables (\(z\)) es:
\[\ln\left(\frac{p}{1-p}\right) = \beta_0 + \beta_1 \text{duration} + \beta_2 \text{balance} + \beta_3 \text{housing} + \beta_4 \text{loan}\] El modelo fue estimado utilizando la función glm() con familia binomial. Posteriormente, se generaron probabilidades de clasificación para cada cliente y se evaluó el desempeño mediante métricas como la Matriz de Confusión, Sensibilidad, Especificidad y Accuracy. Además, se calculó un umbral óptimo utilizando el índice de Youden con el fin de mejorar el equilibrio entre sensibilidad y especificidad.
set.seed(28)
idx <- createDataPartition(y = datos$Y_f, p = 0.75, list = FALSE)
datos_entrena <- datos[idx, ]
datos_test <- datos[-idx, ]
modelo_logit <- glm(Y ~ duration + balance + housing + loan + education,
data = datos_entrena,
family = binomial())
summary(modelo_logit)
##
## Call:
## glm(formula = Y ~ duration + balance + housing + loan + education,
## family = binomial(), data = datos_entrena)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.703e+00 8.989e-02 -18.945 < 2e-16 ***
## duration 4.936e-03 1.313e-04 37.597 < 2e-16 ***
## balance 3.625e-05 8.947e-06 4.052 5.07e-05 ***
## housing -1.161e+00 5.548e-02 -20.919 < 2e-16 ***
## loan -7.977e-01 8.754e-02 -9.112 < 2e-16 ***
## educationsecondary 4.599e-01 8.453e-02 5.441 5.30e-08 ***
## educationtertiary 7.894e-01 8.815e-02 8.956 < 2e-16 ***
## educationunknown 5.530e-01 1.426e-01 3.878 0.000105 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 11583.1 on 8371 degrees of freedom
## Residual deviance: 8551.5 on 8364 degrees of freedom
## AIC: 8567.5
##
## Number of Fisher Scoring iterations: 5
p_hat <- predict(modelo_logit, newdata = datos_test, type = "response")
roc_o <- roc(response = datos_test$Y_f,
predictor = p_hat,
levels = c("No", "Si"))
thr <- coords(roc_o, x = "best", best.method = "youden", ret = "threshold")
umbral <- as.numeric(thr)
pred_clase2 <- factor(ifelse(p_hat >= umbral, "Si", "No"),
levels = c("No", "Si"))
cm_logit <- confusionMatrix(pred_clase2, datos_test$Y_f, positive = "Si")
auc_val <- auc(roc_o)
plot(roc_o,
main = sprintf("ROC Logit | AUC = %.3f | Umbral = %.3f", auc_val, umbral),
col = "blue", lwd = 2)
El modelo K-Nearest Neighbors (KNN) fue implementado utilizando variables previamente estandarizadas, debido a que este algoritmo basa su funcionamiento en distancias entre observaciones y es sensible a diferencias de escala entre variables.
Después de evaluar distintos valores de (k) entre 1 y 50, se seleccionó el valor que presentó la mayor precisión sobre el conjunto de prueba.
cm_knn
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Si
## No 1116 341
## Si 352 981
##
## Accuracy : 0.7516
## 95% CI : (0.7351, 0.7676)
## No Information Rate : 0.5262
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.5021
##
## Mcnemar's Test P-Value : 0.704
##
## Sensitivity : 0.7421
## Specificity : 0.7602
## Pos Pred Value : 0.7359
## Neg Pred Value : 0.7660
## Prevalence : 0.4738
## Detection Rate : 0.3516
## Detection Prevalence : 0.4778
## Balanced Accuracy : 0.7511
##
## 'Positive' Class : Si
##
Los resultados muestran que el modelo KNN logró clasificar correctamente aproximadamente el 75.16% de las observaciones (Accuracy). Asimismo, presentó una sensibilidad de 74.21%, indicando una capacidad adecuada para identificar correctamente a los clientes que aceptaron el depósito bancario.
La especificidad alcanzó un valor de 76.02%, evidenciando también una capacidad aceptable para identificar correctamente a los clientes que no aceptaron el producto financiero.
La Regresión Logística fue implementada utilizando una variable dependiente binaria asociada a la aceptación del depósito bancario.
El modelo permitió estimar la probabilidad de aceptación del producto financiero a partir de variables relacionadas con duración de la llamada, balance financiero y obligaciones crediticias de los clientes.
cm_logit
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Si
## No 1031 220
## Si 437 1102
##
## Accuracy : 0.7645
## 95% CI : (0.7483, 0.7802)
## No Information Rate : 0.5262
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.5316
##
## Mcnemar's Test P-Value : < 2.2e-16
##
## Sensitivity : 0.8336
## Specificity : 0.7023
## Pos Pred Value : 0.7160
## Neg Pred Value : 0.8241
## Prevalence : 0.4738
## Detection Rate : 0.3950
## Detection Prevalence : 0.5516
## Balanced Accuracy : 0.7680
##
## 'Positive' Class : Si
##
Los resultados muestran que el modelo Logit logró clasificar correctamente aproximadamente el 76.45% de las observaciones.
La sensibilidad alcanzó un valor de 83.36%, indicando que el modelo presenta una alta capacidad para detectar correctamente los clientes que aceptaron el depósito bancario.
Por otro lado, la especificidad fue de 70.23%, mostrando una capacidad moderada para identificar correctamente los clientes que no aceptaron el producto financiero. Adicionalmente, la curva ROC y el estadístico AUC permitieron evaluar la capacidad discriminatoria del modelo. ## 5.3 Comparación entre modelos
tabla_comparativa <- data.frame(
METRICA = c("Accuracy", "Sensibilidad", "Especificidad", "Balanced Accuracy", "Kappa"),
`Modelo KNN` = c(as.numeric(cm_knn$overall["Accuracy"]),
as.numeric(cm_knn$byClass["Sensitivity"]),
as.numeric(cm_knn$byClass["Specificity"]),
as.numeric(cm_knn$byClass["Balanced Accuracy"]),
as.numeric(cm_knn$overall["Kappa"])),
`Modelo Logit` = c(as.numeric(cm_logit$overall["Accuracy"]),
as.numeric(cm_logit$byClass["Sensitivity"]),
as.numeric(cm_logit$byClass["Specificity"]),
as.numeric(cm_logit$byClass["Balanced Accuracy"]),
as.numeric(cm_logit$overall["Kappa"]))
)
# La presentamos de forma elegante
knitr::kable(tabla_comparativa, digits = 4, caption = "Tabla comparativa de modelos KNN vs Logit")
| METRICA | Modelo.KNN | Modelo.Logit |
|---|---|---|
| Accuracy | 0.7516 | 0.7645 |
| Sensibilidad | 0.7421 | 0.8336 |
| Especificidad | 0.7602 | 0.7023 |
| Balanced Accuracy | 0.7511 | 0.7680 |
| Kappa | 0.5021 | 0.5316 |
Los resultados evidencian que ambos modelos presentaron desempeños relativamente similares en términos de exactitud global.
El modelo KNN obtuvo una ligera ventaja en accuracy y especificidad, mostrando una mejor capacidad para identificar correctamente a los clientes que no aceptaron el depósito bancario.
Sin embargo, el modelo Logit presentó una sensibilidad superior, logrando detectar con mayor precisión los casos positivos asociados a clientes que sí aceptaron el depósito. Este aspecto resulta especialmente relevante en campañas de marketing financiero, donde suele ser más importante identificar potenciales clientes interesados en el producto.
Además, la Regresión Logística ofrece una ventaja importante en términos de interpretación estadística, ya que permite analizar el efecto individual de cada variable sobre la probabilidad de aceptación del depósito bancario.
En consecuencia, aunque ambos modelos presentaron resultados satisfactorios, el modelo Logit puede considerarse más apropiado para este problema debido a su capacidad interpretativa y su mejor desempeño en sensibilidad.
A la luz de los resultados obtenidos, se considera que los modelos ajustados sí lograron responder al objetivo principal de la investigación, ya que permitieron clasificar a los clientes según su probabilidad de aceptar un depósito bancario e identificar las variables clave que influyen en esta decisión.
Comparación y Selección del Modelo: Aunque el modelo KNN presentó una ligera ventaja en términos de exactitud global al capturar patrones locales en los datos, el modelo Logit demostró ser superior para los objetivos de la entidad financiera. Esto se debe a su mayor sensibilidad (0.8336) y a su capacidad interpretativa, permitiendo entender cómo factores como el balance o la ausencia de deudas previas aumentan la probabilidad de éxito.
Limitaciones y Hallazgos: Se identificó que variables como la duración de la llamada y el balance financiero influyen significativamente en el modelo. No obstante, se reconoce una limitación técnica respecto a la variable duration, la cual podría generar fuga de información, dado que su valor real solo se conoce una vez finalizada la interacción con el cliente.
Recomendaciones: Para futuras implementaciones, se recomienda la incorporación de técnicas de validación cruzada y la exploración de modelos alternativos que permitan mitigar el impacto de los valores atípicos observados. En conclusión, para procesos de toma de decisiones y optimización de campañas de marketing, el modelo de Regresión Logística es el más conveniente por su equilibrio entre precisión técnica y utilidad estratégica.
El sector financiero como motor del desarrollo económico. (s/f). Universidad del Rosario. Recuperado el 15 de mayo de 2026, de https://urosario.edu.co/eventos/facultad-de-economia/el-sector-financiero-como-motor-del-desarrollo-economico
7 bank marketing strategies to grow deposits in 2026. (s/f). Meniga. Recuperado el 15 de mayo de 2026, de https://www.meniga.com/guides/deposit-growth-strategies-for-banks/
Top 10 Estrategias de los Grandes Bancos para Aumentar la Satisfacción del Cliente. (2024, agosto 29). Latinia. https://latinia.com/recursos/mejores-estrategias-bancarias-para-la-satisfaccion-del-cliente
(S/f). Johogo.com. Recuperado el 15 de mayo de 2026, de https://eli.johogo.com/Class/CCU/SEM/_Multivariate%20Data%20Analysis_Hair.pdf
UCI machine learning repository. (s/f). Uci.edu. Recuperado el 15 de mayo de 2026, de https://archive.ics.uci.edu/dataset/222/bank+marketing
Moro, S., Cortez, P., & Rita, P. (2014). A data-driven approach to predict the success of bank telemarketing. Decision Support Systems, 62, 22–31. https://doi.org/10.1016/j.dss.2014.03.001