Se dispone de una base de datos de 5000 transacciones bancarias, clasificadas en tres tipos:
Normal: transacciones habituales del cliente Sospechosa: transacciones con patrones atípicos Fraude: transacciones con alta probabilidad de actividad fraudulenta
El objetivo es construir un modelo de análisis discriminante que permita clasificar nuevas transacciones en uno de estos tres grupos, a partir de variables relacionadas con el comportamiento financiero del cliente.
Este tipo de análisis es relevante en contextos reales como:
Sistemas de detección de fraude en bancos
Seguridad en comercio electrónico
Prevención de pérdidas financieras
Tipo de transacción: (1 = Normal, 2 = Sospechosa, 3 = Fraude)
log_monto: Logaritmo del monto de la transacción.
log_trans_24h: Logaritmo del número de transacciones realizadas por el cliente en las últimas 24 horas. Valores altos pueden indicar actividad inusual.
log_distancia_km: Logaritmo de la distancia geográfica (en km) entre la ubicación habitual del cliente y el lugar de la transacción. Valores altos pueden reflejar transacciones desde ubicaciones atípicas.
desviacion_horaria: Medida continua que representa cuánto se aleja la hora de la transacción del patrón habitual del cliente. Valores altos indican horarios inusuales (por ejemplo, madrugada).
log_intentos_fallidos: Logaritmo del número de intentos fallidos previos (por ejemplo, ingreso incorrecto de clave). Valores elevados pueden indicar intentos de acceso no autorizado.
log_tiempo_entre_trans: Logaritmo del tiempo (en minutos) entre transacciones consecutivas. Valores bajos (en escala original) indican actividad rápida y potencialmente sospechosa.
Transacciones normales: Montos moderados, pocas operaciones, ubicaciones cercanas, horarios habituales.
Transacciones sospechosas: Valores intermedios en varias variables.
Fraude: Montos altos, muchas transacciones en poco tiempo, ubicaciones lejanas, horarios inusuales y múltiples intentos fallidos.
datos <- read.csv("/Users/verar/Downloads/fraude_transacciones.csv")
datos <- data.frame(datos[,1:7])
head(datos)
## log_monto log_trans_24h log_distancia_km desviacion_horaria
## 1 3.491959 0.267064389 3.058356 1.13983440
## 2 3.541905 1.559396166 2.107716 0.80614927
## 3 3.029255 1.440256544 1.292181 -1.21802087
## 4 3.869978 0.783484985 1.677030 0.32141709
## 5 3.381762 1.024567244 2.651197 -0.09020685
## 6 3.696927 -0.003814171 1.262385 -0.25604700
## log_intentos_fallidos log_tiempo_entre_trans grupo
## 1 0.52178777 4.458712 Normal
## 2 0.04668717 4.663755 Normal
## 3 -0.54280611 4.774280 Normal
## 4 -0.12303155 3.634071 Normal
## 5 0.35239779 4.968085 Normal
## 6 -0.56186736 5.202638 Normal
Se busca distinguir entre transacciones fraudulentas y no fraudulentas, identificando qué variables permiten separar mejor ambos grupos y construir un modelo que permita predecir nuevas transacciones.
La variable dependiente es grupo, de tipo categórico.
Las variables independientes son log_monto, log_trans_24h, log_distancia_km, desviacion_horaria, log_intentos_fallidos y log_tiempo_entre_trans.
El análisis discriminante es adecuado porque permite clasificar observaciones en grupos a partir de variables numéricas.
par(mfrow=c(2,3))
boxplot(log_monto ~ grupo, col='skyblue', data=datos)
boxplot(log_trans_24h ~ grupo, col='skyblue', data=datos)
boxplot(log_distancia_km ~ grupo, col='skyblue', data=datos)
boxplot(desviacion_horaria ~ grupo, col='skyblue', data=datos)
boxplot(log_intentos_fallidos ~ grupo, col='skyblue', data=datos)
boxplot(log_tiempo_entre_trans ~ grupo, col='skyblue', data=datos)
Los boxplots muestran diferencias claras entre los grupos. El grupo Fraude presenta valores más altos en la mayoría de variables y el grupo Normal los más bajos
Esto indica la existencia de patrones diferenciados entre los grupos y sugiere que las variables tienen capacidad para discriminar entre ellos.
library(mvnormtest)
mshapiro.test(t(datos[, -which(names(datos)=="grupo")]))
##
## Shapiro-Wilk normality test
##
## data: Z
## W = 0.98905, p-value < 2.2e-16
library(biotools)
## Warning: package 'biotools' was built under R version 4.5.3
## Cargando paquete requerido: MASS
## ---
## biotools version 4.3
boxM(datos[, -which(names(datos)=="grupo")], datos$grupo)
##
## Box's M-test for Homogeneity of Covariance Matrices
##
## data: datos[, -which(names(datos) == "grupo")]
## Chi-Sq (approx.) = 43.282, df = 42, p-value = 0.4164
La prueba de Shapiro-Wilk presenta un p-valor < 0.05, por lo que no se cumple la normalidad. La prueba de Box’s M tiene un p-valor de 0.4164 > 0.05, por lo que se cumple la homogeneidad de covarianzas.
manova_fit <- manova(
cbind(log_monto, log_trans_24h, log_distancia_km,
desviacion_horaria, log_intentos_fallidos,
log_tiempo_entre_trans) ~ grupo,
data = datos
)
Se aplicó la prueba de Box’s M para evaluar la igualdad de matrices de covarianza, obteniéndose un valor de Chi-cuadrado de 43.282 con un p-valor de 0.416 mayor a 0.05
No se rechaza la hipótesis nula, lo que indica que las matrices de covarianza son iguales entre los grupos. Por lo tanto, se cumple este supuesto y el uso del análisis discriminante está justificado.
summary(manova_fit)
## Df Pillai approx F num Df den Df Pr(>F)
## grupo 2 0.68323 431.78 12 9986 < 2.2e-16 ***
## Residuals 4997
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(manova_fit, test="Wilks")
## Df Wilks approx F num Df den Df Pr(>F)
## grupo 2 0.32374 630.27 12 9984 < 2.2e-16 ***
## Residuals 4997
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
El estadístico de Pillai (0.68323) y el Lambda de Wilks (0.32374) presentan p-valores menores a 0.05, por lo que se rechaza la hipótesis nula. Esto indica que existen diferencias estadísticamente significativas entre los grupos en función de las variables analizadas.
Asimismo, el valor de Lambda de Wilks relativamente bajo (0.32374) evidencia que el modelo tiene una buena capacidad para discriminar entre los grupos, lo que respalda la aplicación del análisis discriminante.
library(MASS)
lda_fit <- lda(grupo ~ log_monto + log_trans_24h + log_distancia_km +
desviacion_horaria + log_intentos_fallidos +
log_tiempo_entre_trans,
data = datos)
lda_fit
## Call:
## lda(grupo ~ log_monto + log_trans_24h + log_distancia_km + desviacion_horaria +
## log_intentos_fallidos + log_tiempo_entre_trans, data = datos)
##
## Prior probabilities of groups:
## Fraude Normal Sospechosa
## 0.07 0.78 0.15
##
## Group means:
## log_monto log_trans_24h log_distancia_km desviacion_horaria
## Fraude 4.971090 2.3091132 4.077646 2.4002759
## Normal 3.601113 0.9908171 1.999379 0.4023653
## Sospechosa 4.274717 1.6754687 3.178935 1.3213661
## log_intentos_fallidos log_tiempo_entre_trans
## Fraude 1.36071626 2.241785
## Normal 0.09083588 4.190407
## Sospechosa 0.68512138 3.226164
##
## Coefficients of linear discriminants:
## LD1 LD2
## log_monto -0.30193942 -0.2955025
## log_trans_24h -0.06847524 0.3813189
## log_distancia_km -0.62784855 1.4678456
## desviacion_horaria -0.84387739 -1.1544538
## log_intentos_fallidos 0.26837034 -0.4467930
## log_tiempo_entre_trans 0.87688890 0.2466753
##
## Proportion of trace:
## LD1 LD2
## 0.9949 0.0051
Las probabilidades a priori indican que la mayoría de las observaciones pertenecen al grupo Normal (78%), seguido de Sospechosa (15%) y Fraude (7%).
La primera función discriminante (LD1) explica el 99.49% de la variabilidad, por lo que es la más importante para diferenciar los grupos.
library(MASS)
modelo<-lda(grupo ~ log_monto + log_trans_24h + log_distancia_km +
desviacion_horaria + log_intentos_fallidos +
log_tiempo_entre_trans,
data = datos)
modelo
## Call:
## lda(grupo ~ log_monto + log_trans_24h + log_distancia_km + desviacion_horaria +
## log_intentos_fallidos + log_tiempo_entre_trans, data = datos)
##
## Prior probabilities of groups:
## Fraude Normal Sospechosa
## 0.07 0.78 0.15
##
## Group means:
## log_monto log_trans_24h log_distancia_km desviacion_horaria
## Fraude 4.971090 2.3091132 4.077646 2.4002759
## Normal 3.601113 0.9908171 1.999379 0.4023653
## Sospechosa 4.274717 1.6754687 3.178935 1.3213661
## log_intentos_fallidos log_tiempo_entre_trans
## Fraude 1.36071626 2.241785
## Normal 0.09083588 4.190407
## Sospechosa 0.68512138 3.226164
##
## Coefficients of linear discriminants:
## LD1 LD2
## log_monto -0.30193942 -0.2955025
## log_trans_24h -0.06847524 0.3813189
## log_distancia_km -0.62784855 1.4678456
## desviacion_horaria -0.84387739 -1.1544538
## log_intentos_fallidos 0.26837034 -0.4467930
## log_tiempo_entre_trans 0.87688890 0.2466753
##
## Proportion of trace:
## LD1 LD2
## 0.9949 0.0051
Las funciones discriminante son: LD1=−0.302log_monto−0.068log_trans_24h−0.628log_distancia_km−0.844desviacion_horaria+0.268log_intentos_fallidos+0.877log_tiempo_entre_trans LD2=−0.296log_monto+0.381log_trans_24h+1.468log_distancia_km−1.154desviacion_horaria−0.447log_intentos_fallidos+0.247log_tiempo_entre_trans
En conclusión, LD1 es la función principal de clasificación con un 99% , mientras que LD2 aporta muy poco a la discriminación con un 0.51%.
pred_train <- predict(lda_fit, newdata = datos)
m_confusion <- table(Real = datos$grupo, Predicho = pred_train$class)
m_confusion
## Predicho
## Real Fraude Normal Sospechosa
## Fraude 290 1 59
## Normal 0 3783 117
## Sospechosa 41 223 486
el modelo presenta buen desempeño general de 75.8% destacando una alta capacidad para clasificar.(3783 aciertos). 10. Obtenga predicciones considerando valores supuestos de las variables independientes
nuevo <- data.frame(
log_monto = 4,
log_trans_24h = 1,
log_distancia_km = 2,
desviacion_horaria = 0.5,
log_intentos_fallidos = 0.2,
log_tiempo_entre_trans = 4
)
predict(lda_fit, nuevo)
## $class
## [1] Normal
## Levels: Fraude Normal Sospechosa
##
## $posterior
## Fraude Normal Sospechosa
## 1 3.553829e-06 0.9805088 0.01948766
##
## $x
## LD1 LD2
## 1 0.3667314 -0.3418538
El modelo clasifica la observación como Normal, con una probabilidad de 0.98, muy superior a las demás. Esto indica una clasificación confiable.