INTRODUCCIÓN MARKETING BANCARIO
En el ámbito de la ciencia de datos, la metodología CRISP-DM (Cross
Industry Standard Process for Data Mining) se ha consolidado como un
enfoque estándar y ampliamente adoptado para el desarrollo estructurado
de proyectos de minería de datos.
En este proyecto, aplicaremos CRISP-DM a una base de datos
proveniente de campañas de marketing directo realizadas por una entidad
bancaria portuguesa. Dichas campañas se llevaron a cabo a través de
llamadas telefónicas con el fin de promover productos financieros,
específicamente depósitos a plazo fijo. La base de datos contiene
información sociodemográfica de los clientes, así como detalles de sus
interacciones previas con la entidad bancaria y los resultados de
campañas anteriores.
El objetivo principal de análisis es desarrollar un modelo de
clasificación que permita predecir si un cliente suscribirá o no un
depósito a plazo (representado por la variable binaria y). Este enfoque
permitirá identificar patrones relevantes en los datos y apoyar la toma
de decisiones estratégicas en futuras campañas de marketing.
COMPRESIÓN DEL NEGOCIO
Un banco de Portugal realiza campañas de marketing directo (llamadas
telefónicas) para promocionar depósitos a plazo entre sus clientes.
Actualmente, no cuenta con un sistema predictivo para optimizar estos
contactos
Problema empresarial: Altos costos operativos y
baja efectividad en las campañas telefónicas para depósitos a plazo,
debido a la falta de un sistema que identifique qué clientes tienen
mayor probabilidad de suscribir.
Objetivos
Predecir la probabilidad de suscripción de un depósito a plazo
(variable y), teniendo en cuenta:
- Datos demográficos (edad, ocupación, educación)
- Situación financiera (saldo, créditos)
- Historial de interacciones (contactos previos, resultados de
campañas anteriores)
- Contexto de la llamada (duración, mes, día de contacto)
- Identificar los factores más influyentes en la decisión del
cliente.
COMPRESIÓN DE LOS DATOS
MARKETING BANCARIO
library(readxl)
Banco_2 <- read_excel("Banco 2.xlsx")
head(Banco_2)
## # A tibble: 6 × 17
## age job marital education default balance housing loan contact day
## <dbl> <chr> <chr> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl>
## 1 58 management married tertiary no 2143 yes no unknown 5
## 2 44 technician single secondary no 29 yes no unknown 5
## 3 33 entrepren… married secondary no 2 yes yes unknown 5
## 4 47 blue-coll… married unknown no 1506 yes no unknown 5
## 5 33 unknown single unknown no 1 no no unknown 5
## 6 35 management married tertiary no 231 yes no unknown 5
## # ℹ 7 more variables: month <chr>, duration <dbl>, campaign <dbl>, pdays <dbl>,
## # previous <dbl>, poutcome <chr>, y <chr>
DESCRIPCIÓN DE CADA VARIABLE CUANTITATIVA
Age: Edad del cliente.
Job: Tipo de ocupación (administrativo, tecnico,
retirado, etc.).
Marital: Casado, soltero o divorciado/viudo.
Education: Nivel educativo (primaria, secundaria,
terciaria, desconocido).
Default: Tiene deudas impagas en créditos
anteriores (sí/no).
Balance: Saldo medio anual en euros.
Housing: ¿Tiene préstamo hipotecario? (sí/no).
Loan: ¿Tiene préstamo personal? (sí/no).
Contact: Medio usado para el contacto (teléfono,
celular o desconocido).
Day: Día del último contacto (numérico).
Month: Mes del último contacto (ene a dic).
Duration: Duración de la última llamada, en
segundos.
Campaign: Número de contactos durante la campaña
actual.
Pdays: Días desde el último contacto previo (-1 si
nunca fue contactado).
Previus: Número de contactos antes de esta
campaña.
Poutcome: Resultado de la campaña anterior (éxito,
fracaso, desconocido, otro).
y: Variable objetivo: Indica si contrató un
depósito a plazo (sí/no).
# Cargar librerías necesarias
library(readxl)
library(modeest)
## Warning: package 'modeest' was built under R version 4.4.3
# Cargar el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas de edad
media <- mean(Banco_2$age, na.rm = TRUE)
mediana <- median(Banco_2$age, na.rm = TRUE)
moda <- mfv(Banco_2$age, na_rm = TRUE)
cuartiles <- quantile(Banco_2$age, na.rm = TRUE)
# Mostrar resultados
cat("Los resultados de la variable age son:\n")
## Los resultados de la variable age son:
cat("La media es:", media, "\n")
## La media es: 40.93621
cat("La mediana es:", mediana, "\n")
## La mediana es: 39
cat("La moda es:", moda, "\n")
## La moda es: 32
cat("Los cuartiles son:\n")
## Los cuartiles son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## 18 33 39 48 95
#####
# Cargar librerías necesarias
library(readxl)
library(modeest)
# Leer correctamente el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'balance'
media <- mean(Banco_2$balance, na.rm = TRUE)
mediana <- median(Banco_2$balance, na.rm = TRUE)
moda <- mfv(Banco_2$balance, na_rm = TRUE)
cuartiles <- quantile(Banco_2$balance, na.rm = TRUE)
# Mostrar resultados en consola
cat("Los resultados de la variable balance son:\n")
## Los resultados de la variable balance son:
cat("La media del balance es:", media, "\n")
## La media del balance es: 1362.272
cat("La mediana del balance es:", mediana, "\n")
## La mediana del balance es: 448
cat("La moda del balance es:", moda, "\n")
## La moda del balance es: 0
cat("Los cuartiles del balance son:\n")
## Los cuartiles del balance son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## -8019 72 448 1428 102127
library(readxl)
library(modeest)
# Cargar el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'day'
media <- mean(Banco_2$day, na.rm = TRUE)
mediana <- median(Banco_2$day, na.rm = TRUE)
moda <- mfv(Banco_2$day, na_rm = TRUE)
cuartiles <- quantile(Banco_2$day, na.rm = TRUE)
# Imprimir resultados con texto
cat("Los resultados de la variable day son:\n")
## Los resultados de la variable day son:
cat("La media del día es:", media, "\n")
## La media del día es: 15.80642
cat("La mediana del día es:", mediana, "\n")
## La mediana del día es: 16
cat("La moda del día es:", moda, "\n")
## La moda del día es: 20
cat("Los cuartiles del día son:\n")
## Los cuartiles del día son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## 1 8 16 21 31
library(readxl)
library(modeest)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'duration'
media <- mean(Banco_2$duration, na.rm = TRUE)
mediana <- median(Banco_2$duration, na.rm = TRUE)
moda <- mfv(Banco_2$duration, na_rm = TRUE)
cuartiles <- quantile(Banco_2$duration, na.rm = TRUE)
# Imprimir resultados con texto
cat("Los resultados de la variable duration son:\n")
## Los resultados de la variable duration son:
cat("La media de la duración es:", media, "segundos\n")
## La media de la duración es: 258.1631 segundos
cat("La mediana de la duración es:", mediana, "segundos\n")
## La mediana de la duración es: 180 segundos
cat("La moda de la duración es:", moda, "segundos\n")
## La moda de la duración es: 124 segundos
cat("Los cuartiles de la duración son:\n")
## Los cuartiles de la duración son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## 0 103 180 319 4918
library(readxl)
library(modeest)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'campaign'
media <- mean(Banco_2$campaign, na.rm = TRUE)
mediana <- median(Banco_2$campaign, na.rm = TRUE)
moda <- mfv(Banco_2$campaign, na_rm = TRUE)
cuartiles <- quantile(Banco_2$campaign, na.rm = TRUE)
# Imprimir resultados con texto
cat("Los resultados de la variable campaign son:\n")
## Los resultados de la variable campaign son:
cat("La media de los contactos en la campaña es:", media, "\n")
## La media de los contactos en la campaña es: 2.763841
cat("La mediana es:", mediana, "\n")
## La mediana es: 2
cat("La moda es:", moda, "\n")
## La moda es: 1
cat("Los cuartiles son:\n")
## Los cuartiles son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## 1 1 2 3 63
library(readxl)
library(modeest)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'pdays'
media <- mean(Banco_2$pdays, na.rm = TRUE)
mediana <- median(Banco_2$pdays, na.rm = TRUE)
moda <- mfv(Banco_2$pdays, na_rm = TRUE)
cuartiles <- quantile(Banco_2$pdays, na.rm = TRUE)
# Imprimir resultados con texto
cat("Los resultados de la variable pdays son:\n")
## Los resultados de la variable pdays son:
cat("La media de pdays es:", media, "\n")
## La media de pdays es: 40.19783
cat("La mediana es:", mediana, "\n")
## La mediana es: -1
cat("La moda es:", moda, "\n")
## La moda es: -1
cat("Los cuartiles de pdays son:\n")
## Los cuartiles de pdays son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## -1 -1 -1 -1 871
# Filtrar valores distintos de -1
pdays_filtrado <- Banco_2$pdays[Banco_2$pdays != -1]
# Calcular estadísticas sin los -1
media <- mean(pdays_filtrado)
mediana <- median(pdays_filtrado)
moda <- mfv(pdays_filtrado)
cuartiles <- quantile(pdays_filtrado)
# Imprimir resultados sin -1
cat("La media de pdays (excluyendo -1) es:", media, "\n")
## La media de pdays (excluyendo -1) es: 224.5777
cat("La mediana es:", mediana, "\n")
## La mediana es: 194
cat("La moda es:", moda, "\n")
## La moda es: 182
cat("Los cuartiles de pdays (sin -1) son:\n")
## Los cuartiles de pdays (sin -1) son:
print(cuartiles)
## 0% 25% 50% 75% 100%
## 1 133 194 327 871
library(readxl)
library(modeest)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular estadísticas para 'previous'
media_previous <- mean(Banco_2$previous, na.rm = TRUE)
mediana_previous <- median(Banco_2$previous, na.rm = TRUE)
moda_previous <- mfv(Banco_2$previous, na_rm = TRUE)
cuartiles_previous <- quantile(Banco_2$previous, na.rm = TRUE)
# Imprimir resultados con texto
cat("Los resultados de la variable previous son:\n")
## Los resultados de la variable previous son:
cat("La media de previous es:", media_previous, "\n")
## La media de previous es: 0.5803234
cat("La mediana es:", mediana_previous, "\n")
## La mediana es: 0
cat("La moda es:", moda_previous, "\n")
## La moda es: 0
cat("Los cuartiles de previous son:\n")
## Los cuartiles de previous son:
print(cuartiles_previous)
## 0% 25% 50% 75% 100%
## 0 0 0 0 275
INTERPRETACIÓN DE CADA VARIABLE
AGE
La edad promedio de los clientes es de 40.9 años, con una mediana de
39 años, lo que indica que la distribución es ligeramente asimétrica
hacia edades más altas. La moda es 32 años, lo que significa que esta es
la edad más frecuente en la base de datos. El 25% de los clientes tienen
33 años o menos, mientras que el 75% tiene 48 años o menos. Esto sugiere
que la mayoría de los clientes están en un rango de edad económicamente
activo (30-50 años), con una presencia significativa de personas más
jóvenes (32 años como moda).
BALANCE
El saldo promedio en las cuentas es de 1,362 unidades monetarias,
pero la mediana es de solo 448, lo que revela una fuerte asimetría
positiva debido a algunos clientes con saldos muy altos (hasta 102,127).
La moda es 0, lo que indica que muchas cuentas no tienen saldo o están
en cero. El 25% de los clientes tienen saldos de 72 o menos, y el 75%
tiene saldos de 1,428 o menos. Esto muestra que la mayoría de los
clientes tienen saldos bajos, con pocos casos de saldos extremadamente
altos que distorsionan la media.
DAY
El día promedio del último contacto es el 15.8 (mitad del mes), con
una mediana de 16 y una moda de 20, lo que sugiere que los contactos se
concentran hacia finales del mes. El 25% de los clientes fueron
contactados antes del día 8, y el 75% antes del día 21. Esto podría
indicar que las campañas se intensifican en la segunda quincena,
posiblemente para coincidir con períodos de pago o mayor disponibilidad
de fondos.
DURATION
La duración promedio de las llamadas es de 258 segundos (4.3
minutos), pero la mediana es de 180 segundos (3 minutos), lo que indica
que algunas llamadas muy largas (hasta 4,918 segundos) elevan el
promedio. La moda es 124 segundos (~2 minutos), lo que confirma que la
mayoría de las llamadas son relativamente cortas. El 25% de las llamadas
duran menos de 103 segundos, y el 75% menos de 319 segundos. Esto
sugiere que, aunque hay llamadas extensas, la mayoría son breves.
CAMPAIGN
El número promedio de contactos por cliente es de 2.76, con una
mediana de 2 y una moda de 1, lo que indica que la mayoría de los
clientes fueron contactados una o dos veces. Sin embargo, hay casos
extremos (hasta 63 contactos), lo que podría reflejar estrategias de
seguimiento agresivas para ciertos clientes. El 75% de los clientes
fueron contactados 3 veces o menos, lo que sugiere que, en general, las
campañas no son excesivamente intrusivas.
PDAYS
La mayoría de los clientes no fueron contactados previamente
(mediana y moda = -1). Entre los que sí fueron contactados, el promedio
de días desde el último contacto es de 224.6 (7.5 meses), con una
mediana de 194 días (6.5 meses). Esto indica que los contactos previos
son poco frecuentes y que la mayoría de las interacciones ocurren en la
campaña actual.
PREVIUS
La mayoría de los clientes no tuvieron contactos previos (mediana y
moda = 0). El promedio es de 0.58, lo que confirma que las campañas
anteriores fueron mínimas o nulas para la mayoría
VARIABLES CATEGORICAS
library(readxl)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular frecuencia de cada categoría de 'job'
frecuencia_job <- table(Banco_2$job)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'job' es:\n")
## La frecuencia de cada categoría de 'job' es:
print(frecuencia_job)
##
## admin. blue-collar entrepreneur housemaid management
## 5171 9732 1487 1240 9458
## retired self-employed services student technician
## 2264 1579 4154 938 7597
## unemployed unknown
## 1303 288
library(readxl)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular frecuencia de cada categoría de 'marital'
frecuencia_marital <- table(Banco_2$marital)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'marital' es:\n")
## La frecuencia de cada categoría de 'marital' es:
print(frecuencia_marital)
##
## divorced married single
## 5207 27214 12790
library(readxl)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular frecuencia de cada categoría de 'education'
frecuencia_education <- table(Banco_2$education)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'education' es:\n")
## La frecuencia de cada categoría de 'education' es:
print(frecuencia_education)
##
## primary secondary tertiary unknown
## 6851 23202 13301 1857
library(readxl)
# Leer el archivo Excel
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Calcular frecuencia de cada categoría de 'default'
frecuencia_default <- table(Banco_2$default)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'default' es:\n")
## La frecuencia de cada categoría de 'default' es:
print(frecuencia_default)
##
## no yes
## 44396 815
# Calcular frecuencia de cada categoría de 'housing'
frecuencia_housing <- table(Banco_2$housing)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'housing' es:\n")
## La frecuencia de cada categoría de 'housing' es:
print(frecuencia_housing)
##
## no yes
## 20081 25130
# Calcular frecuencia de cada categoría de 'loan'
frecuencia_loan <- table(Banco_2$loan)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'loan' es:\n")
## La frecuencia de cada categoría de 'loan' es:
print(frecuencia_loan)
##
## no yes
## 37967 7244
# Calcular frecuencia de cada categoría de 'contact'
frecuencia_contact <- table(Banco_2$contact)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'contact' es:\n")
## La frecuencia de cada categoría de 'contact' es:
print(frecuencia_contact)
##
## cellular telephone unknown
## 29285 2906 13020
# Calcular frecuencia de cada categoría de 'month'
frecuencia_month <- table(Banco_2$month)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'month' es:\n")
## La frecuencia de cada categoría de 'month' es:
print(frecuencia_month)
##
## apr aug dec feb jan jul jun mar may nov oct sep
## 2932 6247 214 2649 1403 6895 5341 477 13766 3970 738 579
# Calcular frecuencia de cada categoría de 'poutcome'
frecuencia_poutcome <- table(Banco_2$poutcome)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'poutcome' es:\n")
## La frecuencia de cada categoría de 'poutcome' es:
print(frecuencia_poutcome)
##
## failure other success unknown
## 4901 1840 1511 36959
# Calcular frecuencia de cada categoría de 'y'
frecuencia_y <- table(Banco_2$y)
# Imprimir los resultados
cat("La frecuencia de cada categoría de 'y' es:\n")
## La frecuencia de cada categoría de 'y' es:
print(frecuencia_y)
##
## no yes
## 39922 5289
INTERPRETACION DE CADA VARIABLE
JOB
La distribución de ocupaciones muestra que los grupos más
representados son los trabajadores manuales (blue-collar, 9,732) y los
gerentes (management, 9,458), lo que refleja el perfil laboral típico de
la base de clientes. Las ocupaciones menos frecuentes son estudiantes
(938) y amas de casa (housemaid, 1,240), lo que podría indicar que estos
grupos tienen menor interacción con productos bancarios complejos como
depósitos a plazo. Destaca la presencia significativa de técnicos
(technician, 7,597) y personal administrativo (admin., 5,171), lo que
sugiere una base de clientes diversa pero con predominio de empleados
formales.
MARITAL
La mayoría de los clientes están casados (27,214), seguidos por
solteros (12,790) y divorciados (5,207). Esta distribución podría ser
relevante para las estrategias de marketing, ya que las personas casadas
suelen tomar decisiones financieras conjuntas y podrían ser más
propensas a productos de ahorro a largo plazo. La proporción de
divorciados (aproximadamente 11.5%) es significativa y podría
representar un segmento con necesidades financieras específicas.
EDUCATION
Predomina la educación secundaria (23,202), seguida por
terciaria/universitaria (13,301) y primaria (6,851). Este perfil
educativo sugiere que la mayoría de los clientes tienen al menos
educación media completa, lo que podría facilitar la comprensión de
productos financieros más complejos. La presencia de un grupo con
educación desconocida (unknown, 1,857) podría representar oportunidades
para mejorar la recolección de datos o indicar clientes con menor
engagement bancario
DEFAULT
La abrumadora mayoría no presenta incumplimientos (44,396 vs. 815
con default=yes). Esta distribución extremadamente sesgada sugiere que
la base contiene principalmente clientes con buen historial crediticio,
o que los clientes con incumplimientos son sistemáticamente excluidos de
las campañas de marketing. La variable podría tener poco poder
predictivo debido a este desbalance
HOUSING
La distribución es relativamente equilibrada (20,081 sin crédito
vs. 25,130 con crédito hipotecario). Esto indica que aproximadamente el
55.6% de los clientes tienen préstamos para vivienda, lo que podría
relacionarse con su capacidad de ahorro y propensión a otros productos
financieros. Los clientes sin hipoteca podrían representar tanto a
jóvenes como a personas con mayor capacidad de ahorro.
LOAN
La mayoría no tiene préstamos personales (37,967 vs. 7,244 con
préstamos). Esta proporción (84% sin préstamos) sugiere que los
préstamos personales no son un producto masivo en esta cartera, o que
los clientes con préstamos podrían estar menos dispuestos a contratar
depósitos a plazo debido a sus obligaciones de deuda existentes.
CONTACT
El contacto celular (cellular, 29,285) domina claramente sobre el
telefónico fijo (telephone, 2,906) y los casos desconocidos (unknown,
13,020). Esta distribución refleja la preferencia actual por la
comunicación móvil y sugiere que las campañas podrían optimizarse para
este canal. Los contactos desconocidos representan un reto para el
análisis y podrían indicar registros incompletos.
MONTH
Mayo (may, 13,766) destaca como el mes con mayor actividad de
campaña, seguido por julio (jul, 6,895) y agosto (aug, 6,247). Los meses
con menor actividad son diciembre (dec, 214) y marzo (mar, 477). Esta
distribución podría reflejar estrategias de marketing estacionales,
evitando periodos festivos (diciembre) o coincidiendo con momentos de
bonificación (mayo-julio). La variación mensual debería considerarse al
analizar los resultados de la campaña.
POUTCOME
Predominan los casos sin información previa (unknown, 36,959), lo
que limita el análisis del historial. Entre los resultados conocidos,
los fracasos (failure, 4,901) superan a los éxitos (success, 1,511) y
otros resultados (other, 1,840). Esto sugiere que, cuando hay historial
disponible, las campañas anteriores tuvieron más resultados negativos
que positivos, lo que podría afectar la efectividad de los contactos
actuales.
Y
El marcado desbalanceo (39,922 no vs. 5,289 sí) indica que solo el
11.7% de los clientes contactados suscribieron el depósito. Esta
proporción plantea desafíos para el modelado predictivo, ya que los
algoritmos podrían tender a favorecer la clase mayoritaria. Las
estrategias de muestreo o ponderación podrían ser necesarias para
mejorar la predicción de la clase minoritaria (suscritores).
DEFINICIÓN DE VARIABLES PREDICTORAS (X) Y VARIABLE OBJETIVO
(Y)
Las variables X son como la edad del cliente (age), su tipo de
trabajo (job), su estado civil (marital), el nivel educativo
(education), ¿Tiene deudas impagas en créditos anteriores? (default), el
balance promedio anual (balance), si tiene préstamos de vivienda
(housing), si tiene un préstamo personal (loan), el tipo de contacto
realizado (contact), el día y mes del último contacto (day y month), la
duración del último contacto (duration), el número de contactos en la
campaña (campaign), los días desde el último contacto (pdays), el número
de contactos previos (previous) y el resultado de la campaña anterior
(poutcome). Por otro lado, la variable Y es el resultado que se desea
predecir, en este caso, si el cliente ha suscrito o no un depósito a
plazo (y), que es una variable binaria (“yes” o “no”).
Por lo tanto, nuestro problema estadistico para esta base de datos
sera ¿Qué características de los clientes influyen
significativamente en la probabilidad de que suscriban un depósito a
plazo fijo?
PREPARACIÓN DE LOS DATOS
Se adoptó una estrategia sistemática para seleccionar las variables
más relevantes. Inicialmente, se construyó un modelo logístico completo
que incorporaba todas las variables disponibles: demográficas (como
edad, estado civil y educación), financieras (saldo, préstamos,
créditos) y operacionales (duración del contacto, resultado de campañas
anteriores, entre otras). Este modelo inicial sirvió como punto de
referencia para evaluar los p-valores asociados a cada variable, se
identificaron aquellas con un impacto real en la predicción (p <
0.05).
MODELO LOGISTICO COMPLETO (PRUEBA PARA IDENTIFICAR VARIABLES
IMPORTANTES)
# Cargar librerías necesarias
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(readxl)
# Cargar los datos (reemplaza la ruta si es necesario)
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Convertir la variable dependiente 'y' a valores numéricos (0 y 1)
Banco_2$y <- ifelse(Banco_2$y == "yes", 1, 0)
# Convertir las variables categóricas a factores
Banco_2$job <- factor(Banco_2$job, levels = c("admin.", "unknown", "unemployed", "management", "housemaid", "entrepreneur", "student",
"blue-collar", "self-employed", "retired", "technician", "services"))
Banco_2$marital <- factor(Banco_2$marital, levels = c("married", "divorced", "single"))
Banco_2$education <- factor(Banco_2$education, levels = c("unknown", "secondary", "primary", "tertiary"))
Banco_2$default <- factor(Banco_2$default, levels = c("yes", "no"))
Banco_2$housing <- factor(Banco_2$housing, levels = c("yes", "no"))
Banco_2$loan <- factor(Banco_2$loan, levels = c("yes", "no"))
Banco_2$contact <- factor(Banco_2$contact, levels = c("unknown", "telephone", "cellular"))
Banco_2$month <- factor(Banco_2$month, levels = c("jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"))
Banco_2$poutcome <- factor(Banco_2$poutcome, levels = c("unknown", "other", "failure", "success"))
# Crear el modelo de regresión logística
# Vamos a predecir la variable dependiente 'y', que ahora es binaria (0 o 1)
model <- glm(y ~ age + job + marital + education + default + balance + housing + loan + contact + day + month + duration +
campaign + pdays + previous + poutcome,
data = Banco_2,
family = binomial)
# Ver los resultados del modelo
summary(model)
##
## Call:
## glm(formula = y ~ age + job + marital + education + default +
## balance + housing + loan + contact + day + month + duration +
## campaign + pdays + previous + poutcome, family = binomial,
## data = Banco_2)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -6.559e+00 2.645e-01 -24.801 < 2e-16 ***
## age 1.127e-04 2.205e-03 0.051 0.959233
## jobunknown -3.133e-01 2.335e-01 -1.342 0.179656
## jobunemployed -1.767e-01 1.116e-01 -1.583 0.113456
## jobmanagement -1.653e-01 7.329e-02 -2.255 0.024130 *
## jobhousemaid -5.040e-01 1.365e-01 -3.693 0.000221 ***
## jobentrepreneur -3.571e-01 1.256e-01 -2.844 0.004455 **
## jobstudent 3.821e-01 1.090e-01 3.505 0.000457 ***
## jobblue-collar -3.099e-01 7.267e-02 -4.264 2.01e-05 ***
## jobself-employed -2.983e-01 1.120e-01 -2.664 0.007726 **
## jobretired 2.524e-01 9.722e-02 2.596 0.009436 **
## jobtechnician -1.760e-01 6.893e-02 -2.554 0.010664 *
## jobservices -2.238e-01 8.406e-02 -2.662 0.007763 **
## maritaldivorced 1.795e-01 5.891e-02 3.046 0.002318 **
## maritalsingle 2.720e-01 4.594e-02 5.919 3.23e-09 ***
## educationsecondary -6.695e-02 9.124e-02 -0.734 0.463085
## educationprimary -2.505e-01 1.039e-01 -2.411 0.015915 *
## educationtertiary 1.285e-01 9.586e-02 1.340 0.180204
## defaultno 1.668e-02 1.628e-01 0.102 0.918407
## balance 1.283e-05 5.148e-06 2.493 0.012651 *
## housingno 6.754e-01 4.387e-02 15.395 < 2e-16 ***
## loanno 4.254e-01 5.999e-02 7.091 1.33e-12 ***
## contacttelephone 1.460e+00 1.006e-01 14.508 < 2e-16 ***
## contactcellular 1.623e+00 7.317e-02 22.184 < 2e-16 ***
## day 9.969e-03 2.497e-03 3.993 6.53e-05 ***
## monthfeb 1.114e+00 1.321e-01 8.435 < 2e-16 ***
## monthmar 2.852e+00 1.522e-01 18.735 < 2e-16 ***
## monthapr 1.262e+00 1.217e-01 10.367 < 2e-16 ***
## monthmay 8.626e-01 1.210e-01 7.131 9.96e-13 ***
## monthjun 1.715e+00 1.342e-01 12.781 < 2e-16 ***
## monthjul 4.309e-01 1.198e-01 3.597 0.000322 ***
## monthaug 5.678e-01 1.211e-01 4.688 2.76e-06 ***
## monthsep 2.136e+00 1.522e-01 14.034 < 2e-16 ***
## monthoct 2.143e+00 1.411e-01 15.193 < 2e-16 ***
## monthnov 3.883e-01 1.246e-01 3.115 0.001836 **
## monthdec 1.953e+00 1.995e-01 9.788 < 2e-16 ***
## duration 4.194e-03 6.453e-05 64.986 < 2e-16 ***
## campaign -9.078e-02 1.014e-02 -8.955 < 2e-16 ***
## pdays -1.027e-04 3.061e-04 -0.335 0.737268
## previous 1.015e-02 6.503e-03 1.561 0.118476
## poutcomeother 2.953e-01 1.068e-01 2.766 0.005677 **
## poutcomefailure 9.179e-02 9.347e-02 0.982 0.326093
## poutcomesuccess 2.383e+00 8.625e-02 27.627 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 32631 on 45210 degrees of freedom
## Residual deviance: 21562 on 45168 degrees of freedom
## AIC: 21648
##
## Number of Fisher Scoring iterations: 6
# Hacer predicciones con el modelo
predicciones <- predict(model, type = "response")
predicciones_class <- ifelse(predicciones > 0.5, 1, 0)
# Evaluar el desempeño del modelo
table(Predicted = predicciones_class, Actual = Banco_2$y)
## Actual
## Predicted 0 1
## 0 38940 3456
## 1 982 1833
Se desarrolló un modelo de regresión logística para identificar los
factores determinantes en la suscripción de depósitos a plazo (variable
‘y’). El modelo incorporó variables demográficas (edad, estado civil),
financieras (saldo, créditos), operacionales (duración de contacto,
medio de contacto) e históricas (resultados de campañas anteriores). Los
resultados mostraron que la duración del contacto (duration) tuvo el
efecto más significativo (p < 0.001), donde llamadas más largas
aumentaron considerablemente la probabilidad de suscripción. Variables
como el tipo de contacto (cellular/telephone vs unknown) y meses
específicos (marzo, octubre) también mostraron fuerte significancia
estadística. El modelo presentó una exactitud global del 90.19%, aunque
con cierta tendencia a subestimar los casos positivos debido al
desbalanceo natural de los datos (11.7% de suscripciones). Los
coeficientes sugieren que clientes jubilados, con mayor saldo y sin
préstamos personales tienen mayor propensión a suscribir, mientras que
múltiples contactos (campaign) reducen la probabilidad de éxito. Este
análisis proporciona insights valiosos para optimizar las estrategias de
marketing, focalizando esfuerzos en los segmentos y momentos
identificados como más efectivos.
Finalmente, se seleccionaron como variables independientes aquellas
que se consideran relevantes para el comportamiento del cliente frente a
la campaña. Estas incluyen: duration (duración de la
última llamada), campaign (número de contactos
realizados durante la campaña), contact (medio de
contacto utilizado), balance (saldo promedio anual en
la cuenta), loan (si tiene un préstamo personal),
housing (si tiene un préstamo hipotecario),
job (ocupación), marital (estado
civil), month (mes de contacto) y
poutcome (resultado de campañas anteriores).
MODELADO
Se desarrolló un modelo de regresión logística , seleccionando
únicamente las variables con mayor impacto estadístico para predecir la
suscripción a depósitos a plazo (variable ‘y’)
# Cargar librerías necesarias
library(dplyr)
library(ggplot2)
library(readxl)
# Cargar los datos
Banco_2 <- read_excel("C:/Users/Sanvi/Downloads/Banco 2.xlsx")
# Convertir la variable dependiente 'y' a binaria (0 = no, 1 = yes)
Banco_2$y <- ifelse(tolower(trimws(Banco_2$y)) == "yes", 1, 0)
# Convertir variables categóricas a factores con niveles definidos
Banco_2$job <- factor(Banco_2$job, levels = c("admin.", "unknown", "unemployed", "management", "housemaid", "entrepreneur", "student",
"blue-collar", "self-employed", "retired", "technician", "services"))
Banco_2$marital <- factor(Banco_2$marital, levels = c("married", "divorced", "single"))
Banco_2$education <- factor(Banco_2$education, levels = c("unknown", "secondary", "primary", "tertiary"))
Banco_2$housing <- factor(Banco_2$housing, levels = c("yes", "no"))
Banco_2$loan <- factor(Banco_2$loan, levels = c("yes", "no"))
Banco_2$contact <- factor(Banco_2$contact, levels = c("unknown", "telephone", "cellular"))
Banco_2$month <- factor(Banco_2$month, levels = c("jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"))
Banco_2$poutcome <- factor(Banco_2$poutcome, levels = c("unknown", "other", "failure", "success"))
# Eliminar filas con NA (si las hay, por seguridad)
Banco_2 <- na.omit(Banco_2)
# Crear el nuevo modelo logístico con variables seleccionadas
modelo_opt <- glm(y ~ balance + day + duration + campaign +
job + marital + education + housing + loan +
contact + month + poutcome,
data = Banco_2,
family = binomial)
# Ver el resumen del modelo
summary(modelo_opt)
##
## Call:
## glm(formula = y ~ balance + day + duration + campaign + job +
## marital + education + housing + loan + contact + month +
## poutcome, family = binomial, data = Banco_2)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -6.534e+00 1.907e-01 -34.260 < 2e-16 ***
## balance 1.289e-05 5.127e-06 2.515 0.011903 *
## day 9.898e-03 2.496e-03 3.965 7.33e-05 ***
## duration 4.194e-03 6.453e-05 64.988 < 2e-16 ***
## campaign -9.037e-02 1.013e-02 -8.925 < 2e-16 ***
## jobunknown -3.122e-01 2.331e-01 -1.339 0.180441
## jobunemployed -1.779e-01 1.116e-01 -1.594 0.111000
## jobmanagement -1.646e-01 7.323e-02 -2.248 0.024567 *
## jobhousemaid -5.043e-01 1.360e-01 -3.707 0.000210 ***
## jobentrepreneur -3.586e-01 1.254e-01 -2.860 0.004241 **
## jobstudent 3.822e-01 1.070e-01 3.571 0.000356 ***
## jobblue-collar -3.116e-01 7.261e-02 -4.292 1.77e-05 ***
## jobself-employed -2.983e-01 1.120e-01 -2.664 0.007720 **
## jobretired 2.541e-01 8.738e-02 2.907 0.003644 **
## jobtechnician -1.760e-01 6.892e-02 -2.554 0.010661 *
## jobservices -2.252e-01 8.404e-02 -2.680 0.007359 **
## maritaldivorced 1.785e-01 5.865e-02 3.043 0.002339 **
## maritalsingle 2.704e-01 4.225e-02 6.400 1.56e-10 ***
## educationsecondary -6.705e-02 9.093e-02 -0.737 0.460895
## educationprimary -2.493e-01 1.039e-01 -2.399 0.016423 *
## educationtertiary 1.291e-01 9.530e-02 1.354 0.175597
## housingno 6.755e-01 4.350e-02 15.529 < 2e-16 ***
## loanno 4.254e-01 5.986e-02 7.108 1.18e-12 ***
## contacttelephone 1.461e+00 1.001e-01 14.593 < 2e-16 ***
## contactcellular 1.622e+00 7.310e-02 22.189 < 2e-16 ***
## monthfeb 1.115e+00 1.321e-01 8.434 < 2e-16 ***
## monthmar 2.850e+00 1.522e-01 18.727 < 2e-16 ***
## monthapr 1.258e+00 1.217e-01 10.339 < 2e-16 ***
## monthmay 8.587e-01 1.208e-01 7.107 1.18e-12 ***
## monthjun 1.714e+00 1.342e-01 12.766 < 2e-16 ***
## monthjul 4.290e-01 1.198e-01 3.581 0.000342 ***
## monthaug 5.664e-01 1.211e-01 4.677 2.91e-06 ***
## monthsep 2.134e+00 1.521e-01 14.029 < 2e-16 ***
## monthoct 2.144e+00 1.410e-01 15.201 < 2e-16 ***
## monthnov 3.885e-01 1.246e-01 3.118 0.001818 **
## monthdec 1.952e+00 1.995e-01 9.783 < 2e-16 ***
## poutcomeother 3.139e-01 7.927e-02 3.960 7.49e-05 ***
## poutcomefailure 9.765e-02 5.747e-02 1.699 0.089284 .
## poutcomesuccess 2.397e+00 6.669e-02 35.947 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 32631 on 45210 degrees of freedom
## Residual deviance: 21565 on 45172 degrees of freedom
## AIC: 21643
##
## Number of Fisher Scoring iterations: 6
# Hacer predicciones
pred_opt <- predict(modelo_opt, type = "response")
pred_class_opt <- ifelse(pred_opt > 0.5, 1, 0)
# Matriz de confusión
conf_mat <- table(Predicho = pred_class_opt, Real = Banco_2$y)
print("Matriz de confusión:")
## [1] "Matriz de confusión:"
print(conf_mat)
## Real
## Predicho 0 1
## 0 38942 3453
## 1 980 1836
# Calcular exactitud del modelo
accuracy <- sum(diag(conf_mat)) / sum(conf_mat)
cat("Exactitud del modelo:", round(accuracy, 4), "\n")
## Exactitud del modelo: 0.9019
INTERPRETACION DEL MODELO LOGISTICO
Duración del Contacto (duration)
El tiempo de interacción con el cliente es el factor más
determinante. Por cada segundo adicional de duración en la llamada, la
probabilidad de suscripción aumenta significativamente (coeficiente
+0.0042, p < 0.001). Esto sugiere que las conversaciones más extensas
permiten una mejor identificación de necesidades y oferta
personalizada.
Resultado de Campañas Anteriores (poutcome)
Tipo de Contacto (contact)
El canal de comunicación marca una diferencia crucial. Los contactos
realizados mediante celular (coeficiente +1.62) o teléfono fijo (+1.46)
son significativamente más efectivos que los contactos genéricos
(“unknown”). Esto probablemente refleja la mayor capacidad de estos
canales para establecer una conexión personalizada e inmediata con el
cliente. Las estrategias de marketing deberían priorizar estos canales
directos sobre métodos impersonales como correos masivos.
Número de Intentos de Contacto (campaign)
Cada intento adicional de contacto reduce la probabilidad de éxito
(coeficiente -0.09). Esto indica un claro efecto de saturación o
molestia cuando los clientes son contactados repetidamente. Se
recomienda limitar los intentos a un máximo de 2-3 por campaña y
desarrollar estrategias de contactos más inteligentes y espaciados en el
tiempo para evitar el rechazo.
Situación Crediticia (housing y loan)
Los clientes sin deudas hipotecarias (housing = no) muestran una
mayor disposición a contratar depósitos (coeficiente +0.68), al igual
que aquellos sin préstamos personales (loan = no, coeficiente +0.43).
Esto sugiere que la capacidad financiera disponible es un factor clave.
Los equipos comerciales podrían utilizar estos indicadores para
priorizar clientes con mayor liquidez y capacidad de ahorro.
Perfil Ocupacional (job)
Estudiantes (coeficiente +0.38) y jubilados (+0.25) presentan mayor
propensión a suscribir, posiblemente por necesidades específicas de
planificación financiera. En contraste, trabajadores manuales
(blue-collar, housemaid) muestran menor interés. Esta información
permite afinar los mensajes comerciales según el perfil profesional del
cliente.
Estado Civil (marital)
Los clientes solteros (coeficiente +0.27) y divorciados (+0.18)
muestran mayor probabilidad de suscripción que los casados. Esto podría
relacionarse con diferentes prioridades financieras o mayor flexibilidad
en la toma de decisiones. Las campañas podrían adaptar su enfoque según
este perfil demográfico.
Temporalidad (month)
Los meses de marzo (coeficiente +2.85), octubre (+2.14) y diciembre
(+1.95) presentan especial efectividad, probablemente asociados a ciclos
económicos como pagos de bonos o cierres fiscales. Este patrón temporal
sugiere la conveniencia de intensificar esfuerzos comerciales durante
estos períodos clave.
Saldo Bancario (balance)
Aunque con un efecto modesto (coeficiente +1.29e-05), los clientes
con mayores saldos muestran mayor propensión. Esto refuerza la
estrategia de priorizar clientes con mayor capacidad económica, aunque
debe combinarse con otros factores para una segmentación efectiva
Los p-valores en este análisis de regresión
logística nos indican la significancia estadística de cada variable
predictora
Variables Altamente Significativas (p <
0.001)
Estas variables tienen un impacto extremadamente confiable en la
predicción:
Duration (p < 2e-16): La duración del contacto
es el factor más importante.
Contactcellular (p < 2e-16): Los contactos por
celular son significativamente más efectivos.
Poutcomesuccess (p < 2e-16): El éxito previo en
campañas es el predictor más fuerte.
Monthmar (p < 2e-16): Marzo muestra un efecto
estacional muy marcado.
Variables Muy Significativas (p < 0.01)
Campaign (p < 2e-16): Cada contacto adicional
reduce claramente la probabilidad.
Housingno (p < 2e-16): No tener crédito
hipotecario aumenta notablemente la propensión.
Maritalsingle (p = 1.56e-10): Los solteros muestran
mayor probabilidad que otros estados civiles.
Variables Significativas (p < 0.05)
balance (p = 0.012): El saldo tiene un efecto
pequeño pero significativo.
jobblue-collar (p = 1.77e-05): Los trabajadores
manuales tienen menor propensión.
educationprimary (p = 0.016): Educación primaria
vs. secundaria muestra diferencia.
Variables Marginalmente Significativas (0.05 < p <
0.1)
poutcomefailure (p = 0.089): Los fracasos previos
podrían tener cierto efecto negativo.
Variables No Significativas (p > 0.1)
Estas variables no aportan evidencia suficiente de su impacto:
jobunknown (p = 0.180)
jobunemployed (p = 0.111)
educationsecondary (p = 0.461)
educationtertiary (p = 0.176)
IMPORTANCIA BASADA EN LOS P-VALORES
Variables con p < 0.001: Factores críticos que
deben ser el foco principal.
Variables con 0.001 < p < 0.05: Predictores
importantes a considerar.
Variables con p > 0.05: Podrían eliminarse para
simplificar el modelo sin perder poder predictivo.
Los p-valores en este análisis revelan qué variables tienen un
impacto estadísticamente significativo en la probabilidad de que un
cliente suscriba un depósito a plazo. Las variables con p-valores
extremadamente bajos (p < 0.001), como duration, contactcellular y
poutcomesuccess, emergen como los predictores más confiables y potentes,
demostrando una relación altamente significativa con el resultado.
Variables con p-valores entre 0.001 y 0.05, como balance, campaign y
varias categorías de job, también muestran influencia significativa,
aunque con menor fuerza relativa. Por otro lado, variables como
educationsecondary y jobunknown (p > 0.05) no aportan evidencia
suficiente para considerarse relevantes en el modelo actual.
Esta jerarquía de significancia estadística permite priorizar
acciones comerciales: enfocarse en los factores más impactantes (como
maximizar la duración de contactos de calidad o capitalizar el historial
previo de éxito) mientras se descartan variables redundantes. Los
p-valores, así, no solo validan la solidez del modelo, sino que también
guían decisiones estratégicas basadas en evidencia cuantitativa. En
esencia, el modelo confirma que la efectividad de las campañas depende
críticamente de cómo y a quién se contacta, más que de características
demográficas genéricas.
EVALUACIÓN
# Predicciones (probabilidades)
pred_opt <- predict(modelo_opt, type = "response")
# Clasificación binaria: 1 si probabilidad > 0.5, si no 0
pred_class_opt <- ifelse(pred_opt > 0.5, 1, 0)
# Matriz de confusión
matriz_conf <- table(Predicho = pred_class_opt, Real = Banco_2$y)
print("Matriz de confusión:")
## [1] "Matriz de confusión:"
print(matriz_conf)
## Real
## Predicho 0 1
## 0 38942 3453
## 1 980 1836
# Cálculo de exactitud (accuracy)
exactitud <- mean(pred_class_opt == Banco_2$y)
print(paste("Exactitud del modelo:", round(exactitud, 4)))
## [1] "Exactitud del modelo: 0.9019"
La matriz de confusión es una herramienta que permite evaluar el
desempeño de un modelo de clasificación comparando las predicciones
realizadas con los valores reales. En este caso, el objetivo del modelo
es predecir si un cliente suscribirá un depósito a plazo como parte de
una campaña de marketing telefónico llevada a cabo por una entidad
bancaria portuguesa.
En la matriz presentada, las filas corresponden a las predicciones
del modelo y las columnas a los valores reales:
El modelo predijo correctamente que 38,942 clientes no suscribieron
el depósito (predicción 0, valor real 0).
También acertó al predecir que 1,836 clientes sí lo suscribieron
(predicción 1, valor real 1).
Sin embargo, cometió algunos errores: clasificó erróneamente a 3,453
clientes como no suscriptores, cuando en realidad sí lo eran (falsos
negativos). Asimismo, predijo como suscriptores a 980 clientes que en
realidad no lo fueron (falsos positivos).
A partir de esta información, se calculó la exactitud del modelo,
que corresponde al porcentaje de predicciones correctas respecto al
total de casos. En este análisis, el modelo alcanzó una exactitud del
90,19%, lo que indica un buen nivel de desempeño general. Sin embargo,
también es importante considerar los errores cometidos, especialmente
los falsos negativos, ya que representan posibles oportunidades perdidas
para la campaña.
DESPLIEGUE
Se ha desarrollado una aplicación interactiva que permite a los
usuarios ingresar datos clave de los clientes y obtener, en tiempo real,
una predicción sobre la probabilidad de que estos suscriban un depósito
a plazo. Esta herramienta utiliza un modelo logístico ajustado con las
variables más significativas, identificadas mediante un riguroso
análisis estadístico, lo que garantiza resultados precisos y accionables
para los equipos comerciales y de marketing. La aplicación se ha
construido siguiendo la metodología CRISP-DM (Cross Industry Standard
Process for Data Mining), un estándar ampliamente reconocido en
proyectos de ciencia de datos que consta de seis fases principales:
comprensión del negocio, comprensión de los datos, preparación de los
datos, modelado, evaluación y despliegue. Este enfoque estructurado
asegura que la solución no solo sea robusta y escalable, sino también
adaptable a cambios en los datos o en las necesidades del negocio. Entre
los principales beneficios de la aplicación destacan su alta precisión,
respaldada por métricas validadas como una exactitud del 90.19%, y su
capacidad para adaptarse a nuevos datos mediante actualizaciones
periódicas del modelo. Además, la herramienta ofrece transparencia al
explicar las predicciones en términos comprensibles, lo que facilita su
adopción por parte de los usuarios finales. Al integrar ciencia de datos
con usabilidad, esta aplicación se convierte en un activo estratégico
para optimizar campañas, priorizar clientes y personalizar
interacciones, todo ello con el respaldo de un proceso metodológico
sólido y reproducible.
saveRDS(modelo_opt, file = "modelo_logistico_Banco2.rds")
# app.R
library(shiny)
library(readxl)
# Cargar modelo
modelo <- readRDS("modelo_logistico_Banco2.rds")
# Interfaz de usuario
ui <- fluidPage(
titlePanel("Predicción de aceptación de campaña bancaria"),
sidebarLayout(
sidebarPanel(
numericInput("balance", "Balance", value = 0),
numericInput("day", "Día del mes", value = 15),
numericInput("duration", "Duración (segundos)", value = 100),
numericInput("campaign", "Número de contactos durante campaña", value = 1),
selectInput("job", "Trabajo", choices = c("admin.", "blue-collar", "entrepreneur", "housemaid",
"management", "retired", "self-employed",
"services", "student", "technician",
"unemployed", "unknown")),
selectInput("marital", "Estado civil", choices = c("married", "single", "divorced")),
selectInput("education", "Educación", choices = c("primary", "secondary", "tertiary", "unknown")),
selectInput("housing", "Crédito hipotecario", choices = c("yes", "no")),
selectInput("loan", "Préstamo personal", choices = c("yes", "no")),
selectInput("contact", "Tipo de contacto", choices = c("cellular", "telephone", "unknown")),
selectInput("month", "Mes del contacto", choices = c("jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec")),
selectInput("poutcome", "Resultado de campaña anterior", choices = c("success", "failure", "other", "unknown")),
actionButton("predecir", "Predecir")
),
mainPanel(
h3("Resultado de la predicción:"),
verbatimTextOutput("resultado")
)
)
)
# Lógica del servidor
server <- function(input, output) {
observeEvent(input$predecir, {
# Crear un nuevo dataframe con los inputs
nuevo_dato <- data.frame(
balance = input$balance,
day = input$day,
duration = input$duration,
campaign = input$campaign,
job = input$job,
marital = input$marital,
education = input$education,
housing = input$housing,
loan = input$loan,
contact = input$contact,
month = input$month,
poutcome = input$poutcome
)
# Predecir probabilidad
prob <- predict(modelo, newdata = nuevo_dato, type = "response")
# Clasificar
clase <- ifelse(prob > 0.5, "Acepta (1)", "No acepta (0)")
# Mostrar resultado
output$resultado <- renderText({
paste("Probabilidad de aceptar:", round(prob, 4), "\nClasificación:", clase)
})
})
}
# Ejecutar la app
shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents
CONCLUSIÓN
El análisis desarrollado bajo la metodología CRISP-DM permitió
abordar de forma integral un problema de clasificación relacionado con
campañas de marketing directo implementadas por una entidad bancaria
portuguesa. Utilizando una base de datos rica en información
demográfica, financiera y de comportamiento del cliente, se construyó un
modelo predictivo capaz de anticipar si un cliente suscribirá un
depósito a plazo. La selección adecuada de variables y la evaluación
mediante una matriz de confusión mostraron que el modelo alcanzó una
exactitud del 90,19%, lo cual refleja un desempeño sólido y útil para la
toma de decisiones estratégicas.
Como complemento a este análisis, se diseñó una aplicación
interactiva que permite visualizar los resultados del modelo y realizar
predicciones de manera sencilla. Esta herramienta ofrece a los usuarios
una interfaz amigable para explorar los datos, interpretar los
resultados y facilitar la implementación del modelo en contextos reales
de negocio. La incorporación de esta app fortalece la utilidad práctica
del trabajo, permitiendo que las áreas comerciales o de marketing del
banco puedan identificar de forma anticipada a los clientes con mayor
probabilidad de conversión y enfocar mejor sus esfuerzos.
En conjunto, este proyecto no solo proporciona un modelo predictivo
robusto, sino también una solución tecnológica funcional que apoya la
eficiencia y efectividad de futuras campañas de marketing.
INTRODUCCION RENDIMIENTO ESTUDIANTIL EN UN EXAMEN DE
INGRESO
En el contexto actual, donde la toma de decisiones basada en datos
se ha vuelto fundamental en múltiples sectores, la minería de datos y la
ciencia de datos juegan un papel crucial. Para llevar a cabo estos
procesos de manera estructurada y eficiente, se ha adoptado ampliamente
la metodología CRISP-DM (Cross Industry Standard Process for Data
Mining), la cual ofrece un enfoque estándar compuesto por seis fases que
guían el desarrollo de proyectos de análisis de datos desde la
comprensión del problema hasta la implementación de soluciones.
En este estudio, se aplica dicha metodología a un conjunto de datos
que contiene información detallada sobre el desempeño de los candidatos
en un examen de admisión común, junto con diversas variables
demográficas y académicas. Esta base de datos permite investigar los
factores que pueden influir en el éxito en pruebas competitivas,
convirtiéndose en una herramienta valiosa tanto para investigadores en
el ámbito educativo como para profesionales en ciencia de datos
interesados en generar modelos predictivos y obtener conocimientos
útiles para mejorar los procesos de selección académica.
COMPRENSIÓN DEL NEGOCIO
Una institución académica desea comprender mejor los factores que
influyen en el desempeño de los estudiantes en un examen de admisión
común. Actualmente, no cuenta con un sistema predictivo que permita
anticipar los resultados o identificar perfiles de estudiantes que
puedan requerir apoyo académico adicional.
Problema educativo:
Dificultad para identificar de forma temprana a los estudiantes con
mayor o menor probabilidad de éxito en el examen de ingreso, lo cual
limita la toma de decisiones basada en datos para mejorar los procesos
de orientación, refuerzo académico y selección.
Objetivos
Predecir el nivel de desempeño de un estudiante en el examen de
admisión (variable Performance), teniendo en cuenta:
Factores demográficos: género, casta (grupo social), medio de
instrucción, ocupación de los padres.
Formación académica: tipo de educación recibida en grados
anteriores, asistencia a clases de refuerzo.
Historial académico: porcentaje de calificaciones obtenidas en los
grados 10 y 12.
Condiciones del examen: duración del examen, condiciones
contextuales.
COMPRENSIÓN DE DATOS
library(readxl)
Rendimiento_2 <- read_excel("Rendimiento_2.xlsx")
head(Rendimiento_2)
## # A tibble: 6 × 12
## Gender Caste coaching Class_ten_education twelve_education medium
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 male General NO SEBA AHSEC ENGLISH
## 2 male OBC WA SEBA AHSEC OTHERS
## 3 male OBC OA OTHERS CBSE ENGLISH
## 4 male General WA SEBA AHSEC OTHERS
## 5 male General OA SEBA CBSE ENGLISH
## 6 male General WA CBSE CBSE ENGLISH
## # ℹ 6 more variables: Class_X_Percentage <chr>, Class_XII_Percentage <chr>,
## # Father_occupation <chr>, Mother_occupation <chr>, time <chr>,
## # Performance <chr>
DESCRIPCIÒN DE CADA VARIABLE
Examination Performance: Resultado del estudiante
en el examen de admisión.
Sex: Género del candidato.
Caste: Clasificación de casta del candidato.
Coaching Details: Tipo de clases preparatorias
asistidas por el candidato.
Board Details: Consejo educativo en los grados X y
XII.
Medium of Instruction: Idioma de enseñanza en el
grado XII.
Class X Percentage: Calificación porcentual en el
grado X.
Class XII Percentage: Calificación porcentual en el
grado XII.
Father’s Occupation / Mother’s Occupation:
Profesión de los padres del candidato
Rendimiento_2 <- read_excel("C:/Users/Sanvi/Downloads/Rendimiento_2.xlsx")
frecuencia_gender <- table(Rendimiento_2$Gender)
cat("Frecuencia de 'Gender':\n")
## Frecuencia de 'Gender':
print(frecuencia_gender)
##
## female male
## 311 355
frecuencia_caste <- table(Rendimiento_2$Caste)
cat("Frecuencia de 'Caste':\n")
## Frecuencia de 'Caste':
print(frecuencia_caste)
##
## General OBC SC ST
## 329 162 67 108
frecuencia_coaching <- table(Rendimiento_2$coaching)
cat("Frecuencia de 'Coaching':\n")
## Frecuencia de 'Coaching':
print(frecuencia_coaching)
##
## NO OA WA
## 150 67 449
frecuencia_class10 <- table(Rendimiento_2$Class_ten_education)
cat("Frecuencia de 'Class_ten_education':\n")
## Frecuencia de 'Class_ten_education':
print(frecuencia_class10)
##
## CBSE OTHERS SEBA
## 249 21 396
frecuencia_class12 <- table(Rendimiento_2$twelve_education)
cat("Frecuencia de 'twelve_education':\n")
## Frecuencia de 'twelve_education':
print(frecuencia_class12)
##
## AHSEC CBSE OTHERS
## 368 290 8
frecuencia_medium <- table(Rendimiento_2$medium)
cat("Frecuencia de 'medium':\n")
## Frecuencia de 'medium':
print(frecuencia_medium)
##
## ASSAMESE ENGLISH OTHERS
## 56 536 74
frecuencia_x <- table(Rendimiento_2$Class_X_Percentage)
cat("Frecuencia de 'Class_X_Percentage':\n")
## Frecuencia de 'Class_X_Percentage':
print(frecuencia_x)
##
## Average Excellent Good Vg
## 13 511 41 101
frecuencia_xii <- table(Rendimiento_2$Class_XII_Percentage)
cat("Frecuencia de 'Class_XII_Percentage':\n")
## Frecuencia de 'Class_XII_Percentage':
print(frecuencia_xii)
##
## Average Excellent Good Vg
## 12 398 75 181
frecuencia_father <- table(Rendimiento_2$Father_occupation)
cat("Frecuencia de 'Father_occupation':\n")
## Frecuencia de 'Father_occupation':
print(frecuencia_father)
##
## BANK_OFFICIAL BUSINESS COLLEGE_TEACHER CULTIVATOR DOCTOR
## 23 103 27 27 55
## ENGINEER OTHERS SCHOOL_TEACHER
## 45 277 109
frecuencia_mother <- table(Rendimiento_2$Mother_occupation)
cat("Frecuencia de 'Mother_occupation':\n")
## Frecuencia de 'Mother_occupation':
print(frecuencia_mother)
##
## BANK_OFFICIAL BUSINESS COLLEGE_TEACHER CULTIVATOR DOCTOR
## 4 3 20 1 13
## ENGINEER HOUSE_WIFE OTHERS SCHOOL_TEACHER
## 3 442 72 108
frecuencia_time <- table(Rendimiento_2$time)
cat("Frecuencia de 'time':\n")
## Frecuencia de 'time':
print(frecuencia_time)
##
## FIVE FOUR ONE SEVEN THREE TWO
## 1 11 199 1 86 368
frecuencia_perf <- table(Rendimiento_2$Performance)
cat("Frecuencia de 'Performance':\n")
## Frecuencia de 'Performance':
print(frecuencia_perf)
##
## Average Excellent Good Vg
## 157 101 210 198
INTERPRETACIÒN DE CADA VARIABLE
Género (Gender):
Hay una ligera mayoría de estudiantes varones (355) en comparación
con las mujeres (311). Esto indica una participación equilibrada por
género, sin una predominancia marcada.
Casta (Caste):
La mayoría de los estudiantes pertenecen a la casta “General” (329),
seguida por OBC (162), ST (108) y SC (67). Esta distribución puede ser
útil para analizar si la casta tiene alguna influencia sobre el
rendimiento académico o el acceso a recursos.
Asistencia a clases de refuerzo (Coaching):
La mayoría de los estudiantes asistieron a clases de refuerzo de
tipo “WA” (449), mientras que 150 no asistieron (“NO”) y 67 asistieron a
“OA”. Esto indica que la gran mayoría tuvo algún tipo de apoyo académico
externo.
Educación en décimo grado
(Class_ten_education):
Los programas de educación “SEBA” (396) y “CBSE” (249) son los más
comunes, mientras que “OTHERS” es minoritario (21). SEBA parece ser el
sistema educativo predominante en décimo grado.
Educación en duodécimo grado
(twelve_education):
La mayoría de los estudiantes provienen de AHSEC (368) y CBSE (290),
mientras que muy pocos (8) cursaron estudios bajo otros sistemas
(“OTHERS”). Esto refleja que AHSEC y CBSE dominan la educación en este
nivel
Idioma de instrucción (medium):
El inglés es el medio de instrucción más utilizado (536
estudiantes), muy por encima del asamés (56) y otras lenguas (74). Esto
puede ser relevante para evaluar el impacto del idioma sobre el
rendimiento.
Porcentaje de calificaciones en décimo grado
(Class_X_Percentage):
La mayoría de los estudiantes obtuvo un rendimiento “Excellent”
(511), seguido por “Vg” (101), “Good” (41) y “Average” (13). Esto
muestra un desempeño académico alto en décimo grado.
Porcentaje de calificaciones en duodécimo grado
(Class_XII_Percentage):
Similar al nivel anterior, la mayoría de estudiantes alcanzó un
rendimiento “Excellent” (398), seguido por “Vg” (181), “Good” (75) y
“Average” (12). Se observa una continuidad en los altos niveles de
desempeño académico.
Ocupación del padre (Father_occupation):
La ocupación más común entre los padres es “OTHERS” (277), lo cual
abarca múltiples profesiones no especificadas. Luego vienen “BUSINESS”
(103) y “SCHOOL_TEACHER” (109), seguidos por profesiones como doctor,
ingeniero, etc.
Ocupación de la madre (Mother_occupation):
La gran mayoría de las madres son “HOUSE_WIFE” (442), seguido por
“SCHOOL_TEACHER” (108) y “OTHERS” (72). Las ocupaciones profesionales
son mucho menos frecuentes entre las madres.
Tiempo del examen (time):
La mayoría de los estudiantes tomaron el examen en “TWO” (368) y
“ONE” (199), indicando que estas son las franjas horarias más comunes.
Las demás categorías (como “FIVE”, “SEVEN”) tienen frecuencias muy
bajas.
Desempeño general (Performance):
La categoría más numerosa es “Good” (210), seguida muy de cerca por
“Vg” (198), “Excellent” (101) y finalmente “Average” (157). Aunque hay
una buena proporción de estudiantes con desempeño sobresaliente, también
hay una presencia significativa de estudiantes con rendimiento promedio
o bajo.
DEFINICIÓN DE VARIABLES PREDICTORAS (X) Y VARIABLE OBJETIVO
(Y)
En este conjunto de datos, la variable dependiente (Y) es
Examination Performance, ya que representa el resultado del examen que
se desea predecir. Las variables independientes (X), que pueden influir
en ese resultado, incluyen el género, casta, tipo de preparación,
consejo educativo, idioma de enseñanza, calificaciones en grados X y
XII, y la ocupación de los padres. Estas variables permiten analizar
cómo factores académicos y socioeconómicos afectan el desempeño en
exámenes de admisión.
Por lo que, nuestro problema estadistico para esta base de datos
sera ¿Qué factores personales, educativos y familiares influyen
significativamente en el rendimiento de los estudiantes en el examen de
ingreso universitario?
PREPARACIÓN DE LOS DATOS
Se adoptó una estrategia sistemática para seleccionar las variables
más relevantes en la predicción del rendimiento estudiantil.
Inicialmente, se construyó un modelo de regresión logística binaria que
incorporó todas las variables disponibles en la base de datos:
características personales (como género, casta, tipo de educación en los
grados 10 y 12, idioma de instrucción), académicas (porcentajes de
calificaciones obtenidas en los grados 10 y 12), socioeconómicas
(ocupación de los padres) y logísticas (tiempo en que se presentó el
examen, asistencia a clases de refuerzo).
Este modelo completo sirvió como punto de partida para evaluar la
significancia estadística de cada predictor. Se examinaron los valores p
asociados a cada variable, identificando aquellas con un impacto
significativo en la probabilidad de tener un buen desempeño académico (p
< 0.05).
MODELO LOGISTICO COMPLETO (PRUEBA PARA IDENTIFICAR VARIABLES
IMPORTANTES)
# Cargar librerías necesarias
library(readxl)
library(dplyr)
library(MASS) # Para polr
## Warning: package 'MASS' was built under R version 4.4.3
##
## Adjuntando el paquete: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
library(caret) # Para matriz de confusión
## Cargando paquete requerido: lattice
# Paso 1: Cargar los datos
Rendimiento_2 <- read_excel("C:/Users/Sanvi/Downloads/Rendimiento_2.xlsx")
# Paso 2: Convertir la variable dependiente Performance a factor ordenado
Rendimiento_2$Performance <- factor(Rendimiento_2$Performance,
levels = c("Average", "Good", "Vg", "Excellent"),
ordered = TRUE)
# Paso 3: Convertir otras variables categóricas a factores
Rendimiento_2 <- Rendimiento_2 %>%
mutate(across(c(Gender, Caste, coaching, Class_ten_education, twelve_education, medium,
Class_X_Percentage, Class_XII_Percentage, Father_occupation, Mother_occupation, time),
as.factor))
# Paso 4: Ajustar el modelo de regresión logística ordinal
modelo <- polr(Performance ~ Gender + Caste + coaching + Class_ten_education + twelve_education +
medium + Class_X_Percentage + Class_XII_Percentage + Father_occupation +
Mother_occupation + time,
data = Rendimiento_2, Hess = TRUE)
# Ver resumen del modelo
summary(modelo)
## Call:
## polr(formula = Performance ~ Gender + Caste + coaching + Class_ten_education +
## twelve_education + medium + Class_X_Percentage + Class_XII_Percentage +
## Father_occupation + Mother_occupation + time, data = Rendimiento_2,
## Hess = TRUE)
##
## Coefficients:
## Value Std. Error t value
## Gendermale 0.22322 0.1708 1.3069
## CasteOBC -1.09292 0.2019 -5.4142
## CasteSC -2.67490 0.3036 -8.8118
## CasteST -5.93332 0.4720 -12.5717
## coachingOA 1.19048 0.3449 3.4521
## coachingWA 0.20855 0.2182 0.9557
## Class_ten_educationOTHERS 0.85440 0.5517 1.5487
## Class_ten_educationSEBA -0.50584 0.2972 -1.7020
## twelve_educationCBSE -0.63353 0.2971 -2.1320
## twelve_educationOTHERS -0.56079 1.0152 -0.5524
## mediumENGLISH 0.70443 0.3354 2.1004
## mediumOTHERS 1.04288 0.3868 2.6961
## Class_X_PercentageExcellent -0.82855 0.8922 -0.9287
## Class_X_PercentageGood -0.58421 0.8969 -0.6513
## Class_X_PercentageVg -1.18681 0.8982 -1.3214
## Class_XII_PercentageExcellent -0.46363 0.9788 -0.4737
## Class_XII_PercentageGood -1.12443 0.9408 -1.1952
## Class_XII_PercentageVg -1.11523 0.9608 -1.1607
## Father_occupationBUSINESS -0.94596 0.5091 -1.8581
## Father_occupationCOLLEGE_TEACHER 0.22238 0.6029 0.3689
## Father_occupationCULTIVATOR -1.36075 0.6934 -1.9623
## Father_occupationDOCTOR -1.08787 0.5641 -1.9285
## Father_occupationENGINEER -0.19697 0.5670 -0.3474
## Father_occupationOTHERS -0.83945 0.4823 -1.7404
## Father_occupationSCHOOL_TEACHER -1.20340 0.5204 -2.3123
## Mother_occupationBUSINESS -0.73357 1.5207 -0.4824
## Mother_occupationCOLLEGE_TEACHER 0.09273 1.1406 0.0813
## Mother_occupationCULTIVATOR 0.97063 2.0070 0.4836
## Mother_occupationDOCTOR -0.42997 1.2173 -0.3532
## Mother_occupationENGINEER -1.47427 1.4225 -1.0364
## Mother_occupationHOUSE_WIFE -1.15382 1.0512 -1.0976
## Mother_occupationOTHERS -1.29713 1.0783 -1.2030
## Mother_occupationSCHOOL_TEACHER -1.20112 1.0736 -1.1188
## timeFOUR 1.24080 2.0678 0.6001
## timeONE 1.46363 2.0144 0.7266
## timeSEVEN 1.48465 2.6786 0.5543
## timeTHREE 1.88038 2.0074 0.9367
## timeTWO 1.87198 2.0161 0.9285
##
## Intercepts:
## Value Std. Error t value
## Average|Good -4.5936 2.2946 -2.0019
## Good|Vg -1.9533 2.2903 -0.8528
## Vg|Excellent 0.0830 2.2878 0.0363
##
## Residual Deviance: 1279.013
## AIC: 1361.013
# Paso 5: Hacer predicciones
predicciones <- predict(modelo, newdata = Rendimiento_2)
# Paso 6: Matriz de confusión
confusionMatrix(data = predicciones, reference = Rendimiento_2$Performance)
## Confusion Matrix and Statistics
##
## Reference
## Prediction Average Good Vg Excellent
## Average 114 9 4 0
## Good 42 119 66 20
## Vg 1 76 109 54
## Excellent 0 6 19 27
##
## Overall Statistics
##
## Accuracy : 0.5541
## 95% CI : (0.5154, 0.5922)
## No Information Rate : 0.3153
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.3799
##
## Mcnemar's Test P-Value : NA
##
## Statistics by Class:
##
## Class: Average Class: Good Class: Vg Class: Excellent
## Sensitivity 0.7261 0.5667 0.5505 0.26733
## Specificity 0.9745 0.7193 0.7201 0.95575
## Pos Pred Value 0.8976 0.4818 0.4542 0.51923
## Neg Pred Value 0.9202 0.7828 0.7911 0.87948
## Prevalence 0.2357 0.3153 0.2973 0.15165
## Detection Rate 0.1712 0.1787 0.1637 0.04054
## Detection Prevalence 0.1907 0.3709 0.3604 0.07808
## Balanced Accuracy 0.8503 0.6430 0.6353 0.61154
Se construyó un modelo de regresión logística ordinal como prueba
exploratoria con el objetivo de identificar las variables más relevantes
en la predicción del rendimiento académico de los estudiantes. Este
modelo incluyó variables demográficas, académicas y familiares. Los
resultados muestran que algunas variables tienen asociaciones
estadísticamente significativas con el nivel de rendimiento. En
particular, pertenecer a una casta distinta a la “General” mostró una
fuerte relación negativa con el rendimiento: los coeficientes para las
castas OBC (-1.09), SC (-2.67) y ST (-5.93) fueron significativamente
negativos (p < 0.05), lo que sugiere que estos estudiantes tienen
menor probabilidad de obtener niveles altos de rendimiento.
Asimismo, haber recibido clases de refuerzo únicamente de manera
online (coachingOA) se asoció positivamente con un mayor rendimiento
(coef. = 1.19, p < 0.01). También se observó un efecto significativo
del medio de instrucción: estudiar en inglés (coef. = 0.70) o en un
medio catalogado como “Otros” (coef. = 1.04) aumentó la probabilidad de
lograr un mejor desempeño.
Finalmente, se seleccionaron las variables más relevantes para
explicar el rendimiento académico (Performance) a partir del análisis
del modelo logístico ordinal. Las variables retenidas fueron: Caste,
coaching, twelve_education, medium y Father_occupation, ya que mostraron
una asociación estadísticamente significativa con la variable
dependiente y contribuyen a un modelo más sencillo y explicativo.
MODELADO
Se construyó un nuevo modelo logístico ordinal utilizando únicamente
las variables que mostraron mayor significancia estadística en el
análisis previo. Este modelo reducido incluyó las variables Caste,
coaching, twelve_education, medium y Father_occupation, con el objetivo
de mejorar la interpretabilidad y la eficiencia predictiva, enfocándose
en los factores que realmente impactan el rendimiento académico.
# Cargar librería
library(MASS)
# Ajustar el modelo ordinal con variables significativas
modelo_significativo <- polr(
Performance ~ Caste + coaching + twelve_education + medium + Father_occupation,
data = Rendimiento_2,
Hess = TRUE
)
# Ver resumen del modelo
summary(modelo_significativo)
## Call:
## polr(formula = Performance ~ Caste + coaching + twelve_education +
## medium + Father_occupation, data = Rendimiento_2, Hess = TRUE)
##
## Coefficients:
## Value Std. Error t value
## CasteOBC -1.1755 0.1930 -6.0921
## CasteSC -2.6897 0.2974 -9.0438
## CasteST -5.9851 0.4488 -13.3344
## coachingOA 1.2482 0.3215 3.8828
## coachingWA 0.2530 0.1945 1.3009
## twelve_educationCBSE -0.1297 0.1824 -0.7111
## twelve_educationOTHERS 0.3242 0.9337 0.3472
## mediumENGLISH 0.7246 0.3248 2.2307
## mediumOTHERS 0.9503 0.3686 2.5778
## Father_occupationBUSINESS -0.9960 0.4825 -2.0645
## Father_occupationCOLLEGE_TEACHER 0.3633 0.5700 0.6374
## Father_occupationCULTIVATOR -1.0068 0.6513 -1.5460
## Father_occupationDOCTOR -0.7695 0.5163 -1.4904
## Father_occupationENGINEER 0.1658 0.5315 0.3120
## Father_occupationOTHERS -0.7566 0.4576 -1.6536
## Father_occupationSCHOOL_TEACHER -1.1125 0.4887 -2.2762
##
## Intercepts:
## Value Std. Error t value
## Average|Good -3.0630 0.5858 -5.2286
## Good|Vg -0.5193 0.5732 -0.9061
## Vg|Excellent 1.4098 0.5734 2.4588
##
## Residual Deviance: 1319.739
## AIC: 1357.739
# Predicciones del modelo
predicciones <- predict(modelo_significativo, newdata = Rendimiento_2)
# Matriz de confusión
matriz_confusion <- table(Predicho = predicciones, Real = Rendimiento_2$Performance)
print(matriz_confusion)
## Real
## Predicho Average Good Vg Excellent
## Average 110 9 5 0
## Good 46 97 53 20
## Vg 1 96 123 61
## Excellent 0 8 17 20
# Calcular la exactitud del modelo
exactitud <- sum(diag(matriz_confusion)) / sum(matriz_confusion)
cat("La exactitud del modelo es:", round(exactitud * 100, 2), "%\n")
## La exactitud del modelo es: 52.55 %
INTERPRETACIÒN DEL MODELO LOGISTICO
Caste:
OBC (-1.1755, t = -6.09): Ser de la casta OBC está asociado con una
menor probabilidad de alcanzar un nivel más alto de desempeño académico
en comparación con la categoría base (General), y este efecto es
estadísticamente significativo.
SC (-2.6897, t = -9.04): Pertenecer a la casta SC tiene un efecto
negativo aún más pronunciado en el rendimiento en comparación con
General, con alta significancia estadística.
ST (-5.9851, t = -13.33): La categoría ST muestra el mayor efecto
negativo, sugiriendo que los estudiantes de esta casta tienen menor
probabilidad de alcanzar niveles superiores de desempeño.
coaching:
OA (coaching asistido ocasionalmente) (1.2482, t = 3.88): Haber
recibido coaching ocasional se asocia con una mayor probabilidad de un
mejor rendimiento, siendo estadísticamente significativo.
WA (coaching asistido regularmente) (0.2530, t = 1.30): El coaching
regular muestra un efecto positivo, aunque menos marcado y no
estadísticamente significativo en este modelo.
twelve_education:
CBSE (-0.1297, t = -0.71) y OTHERS (0.3242, t = 0.35): La educación
secundaria de tipo CBSE y otras modalidades no presentan efectos
estadísticamente significativos en comparación con la categoría base
AHSEC.
medium:
ENGLISH (0.7246, t = 2.23): Estudiar en medio inglés está asociado
con una mayor probabilidad de lograr un mejor rendimiento académico, y
este resultado es estadísticamente significativo.
OTHERS (0.9503, t = 2.58): Otros medios de instrucción también
presentan un efecto positivo significativo en el desempeño.
Father_occupation:
BUSINESS (-0.9960, t = -2.06): Tener un padre con ocupación en
negocios está relacionado con una menor probabilidad de un mejor
rendimiento académico, con significancia estadística.
SCHOOL_TEACHER (-1.1125, t = -2.28): Que el padre sea maestro de
escuela también se asocia con un menor rendimiento académico,
estadísticamente significativo.
COLLEGE_TEACHER (0.3633, t = 0.64), CULTIVATOR (-1.0068, t = -1.55),
DOCTOR (-0.7695, t = -1.49), ENGINEER (0.1658, t = 0.31), OTHERS
(-0.7566, t = -1.65): Estas ocupaciones no muestran efectos
estadísticamente significativos.
Esta jerarquía basada en los valores t permite identificar qué
variables tienen un impacto más sólido y confiable en el desempeño
académico, facilitando la toma de decisiones informadas. Las variables
con valores t altos en magnitud (por ejemplo, las castas OBC, SC y ST,
el coaching ocasional y el medio de instrucción en inglés u otros)
destacan como factores clave que influyen significativamente en el
rendimiento. Por otro lado, aquellas variables con valores t cercanos a
cero sugieren un efecto débil o incierto, por lo que pueden ser
consideradas menos relevantes o prescindibles. De esta manera, el valor
t no solo evalúa la fuerza estadística del modelo, sino que también guía
la selección de variables que aportan valor real al análisis. En
esencia, el modelo revela que aspectos específicos como la casta, el
tipo de coaching recibido y el medio de instrucción tienen un papel
mucho más decisivo en el rendimiento estudiantil que otras
características menos significativas.
EVALUACIÓN
# Predicciones del modelo
predicciones <- predict(modelo_significativo, newdata = Rendimiento_2)
# Matriz de confusión
matriz_confusion <- table(Predicho = predicciones, Real = Rendimiento_2$Performance)
print(matriz_confusion)
## Real
## Predicho Average Good Vg Excellent
## Average 110 9 5 0
## Good 46 97 53 20
## Vg 1 96 123 61
## Excellent 0 8 17 20
# Calcular la exactitud del modelo
exactitud <- sum(diag(matriz_confusion)) / sum(matriz_confusion)
cat("La exactitud del modelo es:", round(exactitud * 100, 2), "%\n")
## La exactitud del modelo es: 52.55 %
La matriz de confusión muestra cómo el modelo clasificó a los
estudiantes en las categorías de desempeño: Average, Good, Vg y
Excellent, en comparación con sus clasificaciones reales. Por ejemplo,
de los estudiantes que realmente tienen un desempeño Average, el modelo
predijo correctamente 110 casos, pero clasificó erróneamente a 9 como
Good y a 5 como Vg. De manera similar, para la categoría Good, 97
estudiantes fueron correctamente clasificados, aunque 46 se asignaron
erróneamente a Average, 53 a Vg y 20 a Excellent. En el grupo Vg, 123
predicciones fueron correctas, pero hubo errores que incluyeron 1 caso
clasificado como Average, 96 como Good y 61 como Excellent. Finalmente,
en la categoría Excellent, el modelo acertó en 20 casos, mientras que
clasificó erróneamente a 8 como Good y 17 como Vg.
Estos resultados reflejan que el modelo tiene una capacidad moderada
para distinguir entre las diferentes categorías de desempeño, logrando
una exactitud general del 52.55%. Esto significa que aproximadamente la
mitad de las predicciones del modelo coinciden con la clasificación real
de los estudiantes, indicando que aunque el modelo captura ciertas
tendencias, aún hay margen para mejorar su precisión, especialmente en
diferenciar claramente entre categorías intermedias como Good y Vg.
DESPLIEGUE
Se ha desarrollado una aplicación interactiva que permite a los
usuarios ingresar datos relevantes de los estudiantes, como casta, tipo
de coaching, educación en grado 12, medio de instrucción y ocupación del
padre, para obtener en tiempo real una predicción del desempeño
académico categorizado en Average, Good, Vg o Excellent. Esta
herramienta utiliza un modelo logístico ordinal ajustado con las
variables más significativas, seleccionadas a través de un análisis
riguroso basado en criterios estadísticos como el valor t, lo que
garantiza predicciones confiables y útiles para docentes, orientadores y
administradores académicos.
La aplicación fue creada siguiendo la metodología CRISP-DM,
asegurando que la solución sea robusta, escalable y adaptable a futuros
cambios en los datos o en los requerimientos del sistema educativo.
Entre los beneficios clave de esta aplicación se encuentran su
capacidad para facilitar la identificación temprana de estudiantes con
distintos niveles de desempeño, permitiendo así diseñar estrategias
personalizadas de apoyo académico. Además, el modelo cuenta con una
exactitud del 52.55%, lo que representa una base sólida para la toma de
decisiones informadas. La herramienta también ofrece explicaciones
claras sobre las predicciones, facilitando su comprensión y adopción por
parte de los usuarios finales.
Al combinar técnicas avanzadas de análisis estadístico con una
interfaz amigable, esta aplicación se posiciona como un recurso
estratégico para mejorar la gestión educativa, optimizar recursos y
potenciar el éxito académico de los estudiantes.
library(shiny)
library(MASS)
# Interfaz de usuario
ui <- fluidPage(
titlePanel("Predicción de Rendimiento Académico"),
sidebarLayout(
sidebarPanel(
selectInput("caste", "Casta:",
choices = c("General", "OBC", "SC", "ST")),
selectInput("coaching", "Recibe coaching:",
choices = c("NO", "WA", "OA")),
selectInput("twelve_education", "Educación secundaria:",
choices = c("AHSEC", "CBSE", "OTHERS")),
selectInput("medium", "Medio de instrucción:",
choices = c("ENGLISH", "ASSAMESE", "OTHERS")),
selectInput("father_occupation", "Ocupación del padre:",
choices = c("DOCTOR", "SCHOOL_TEACHER", "COLLEGE_TEACHER",
"BUSINESS", "ENGINEER", "BANK_OFFICIAL",
"CULTIVATOR", "OTHERS")),
actionButton("predict", "Predecir Rendimiento")
),
mainPanel(
h3("Resultado de la Predicción:"),
verbatimTextOutput("prediction"),
h3("Probabilidades por Categoría:"),
tableOutput("probabilities")
)
)
)
# Lógica del servidor
server <- function(input, output) {
# Cargar el modelo (deberías tenerlo previamente guardado)
# modelo <- readRDS("modelo_ordinal.rds")
# O crear el modelo aquí mismo (solo para demostración)
modelo <- reactive({
# Este es solo un ejemplo - deberías usar tu modelo real
polr(Performance ~ Caste + coaching + twelve_education + medium + Father_occupation,
data = Rendimiento_2, Hess = TRUE)
})
# Hacer la predicción cuando se presiona el botón
observeEvent(input$predict, {
# Crear dataframe con los inputs
new_data <- data.frame(
Caste = input$caste,
coaching = input$coaching,
twelve_education = input$twelve_education,
medium = input$medium,
Father_occupation = input$father_occupation
)
# Hacer la predicción
pred <- predict(modelo(), newdata = new_data, type = "class")
probs <- predict(modelo(), newdata = new_data, type = "probs")
# Mostrar resultados
output$prediction <- renderPrint({
cat("Rendimiento predicho:", as.character(pred))
})
output$probabilities <- renderTable({
data.frame(
Categoría = c("Excellent", "Vg", "Good", "Average"),
Probabilidad = round(as.numeric(probs) * 100, 2)
)
}, digits = 2)
})
}
# Ejecutar la aplicación
shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents
CONCLUSIÓN
El análisis realizado, basado en un enfoque riguroso de selección de
variables y modelado estadístico, permitió construir un modelo logístico
ordinal para predecir el desempeño académico de los estudiantes en
distintas categorías: Average, Good, Vg y Excellent. Partiendo de un
conjunto amplio de variables demográficas, educativas y familiares, se
identificaron las más significativas —como la casta, el tipo de coaching
recibido, la educación en grado 12, el medio de instrucción y la
ocupación del padre— que aportan información valiosa para la predicción
del rendimiento.
La evaluación del modelo a través de la matriz de confusión mostró
una exactitud del 52.55%, lo que indica un nivel razonable de predicción
para esta clase de datos educativos y permite un uso práctico para
orientar intervenciones académicas. Además, se desarrolló una aplicación
interactiva que facilita la implementación del modelo, permitiendo a
usuarios ingresar datos clave y obtener predicciones en tiempo real
sobre el desempeño esperado, lo que apoya a docentes y orientadores en
la identificación temprana de estudiantes que puedan requerir atención
personalizada.
En resumen, este proyecto ofrece un modelo predictivo sólido junto
con una herramienta tecnológica accesible, que en conjunto contribuyen a
mejorar la gestión educativa y optimizar los recursos para maximizar el
éxito estudiantil, todo ello sustentado en un proceso metodológico
estructurado y validado estadísticamente.