#La Regresión Logística Simple, desarrollada por
#David Cox en 1958, es un método de regresión que permite
#estimar la probabilidad de una variable cualitativa binaria
#en función de una variable cuantitativa. Una de las principales
#aplicaciones de la regresión logística es la de clasificación
#binaria, en el que las observaciones se clasifican en un grupo
#u otro dependiendo del valor que tome la variable empleada
#como predictor. Por ejemplo, clasificar a un individuo
#desconocido como hombre o mujer en función del tamaño de la
#mandíbula.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(plotly)
##
## Adjuntando el paquete: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(ISLR) #Contiene datasets del libro
#"An Introduction to Statistical Learning with
#Applications in R"
#install.packages("dplyr")
library(dplyr)
library(readr)
library(ggplot2)
library(plotly)
dsBankFull <- read_csv("bank-full.csv")
## Rows: 45211 Columns: 17
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (10): job, marital, education, default, housing, loan, contact, month, p...
## dbl (7): age, balance, day, duration, campaign, pdays, previous
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Un conjunto de datos simulado que contiene
#información sobre diez mil clientes. El objetivo aquí es
#predecir qué clientes incumplirán con su deuda de tarjeta
#de crédito.
head(dsBankFull)
## # 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>
#default: Un factor con niveles No y Sí que indica si el
#cliente incumplió con su deuda.
#student: Un factor con niveles No y Sí que indica si el
#cliente es estudiante.
#balance: El saldo promedio que el cliente tiene pendiente
#en su tarjeta de crédito después de realizar su pago mensual.
#income: Ingresos del cliente.
# Se recodifican los niveles No, Yes a 1 y 0
dsBankFull <- dsBankFull %>%
mutate(y = as.factor(y))
dsBankFullTr <- dsBankFull %>%
select(y, balance) %>%
mutate(y = recode(y,
"no" = 0,
"yes" = 1))
head(dsBankFullTr)
## # A tibble: 6 × 2
## y balance
## <dbl> <dbl>
## 1 0 2143
## 2 0 29
## 3 0 2
## 4 0 1506
## 5 0 1
## 6 0 231
#Para evitar estos problemas la regresión logística transforma
#el valor devuelto por la regresión lineal (β0+β1X) empleando
#una función cuyo resultado está siempre comprendido entre
#0 y 1. Utilizando la función sigmoide.
#Para valores de x muy grandes positivos, el valor de e^−x
#es aproximadamente 0 por lo que el valor de la función
#sigmoide es 1. Para valores de x muy grandes negativos,
#el valor e^−x tiende a infinito por lo que el valor de la
#función sigmoide es 0.
# Ajuste de un modelo logístico.
modelo_logistico <- glm(y ~ balance,
data = dsBankFullTr,
family = "binomial")
#Variable de respuesta=default
#Variable predictora=balance
#binomial porque tenemos una variable de respuesta con dos opciones
#names(modelo_logistico)
# Representación gráfica del modelo.
ggplot(data = dsBankFullTr, aes(x = balance, y = y)) +
geom_point(aes(color = as.factor(y)), shape = 1) +
stat_function(fun = function(x){predict(modelo_logistico,
newdata = data.frame(balance = x),
type = "response")}) +
theme_bw() +
labs(title = "Regresión logística",
y = "Probabilidad y") +
theme(legend.position = "none")

# Con geom_smooth se puede obtener el gráfico directamente.
a<-ggplot(data = dsBankFullTr, aes(x = balance, y = y)) +
geom_point(aes(color = as.factor(y)), shape = 1) +
geom_smooth(method = "glm",
method.args = list(family = "binomial"),
color = "gray20",
se = FALSE) +
theme_bw() +
theme(legend.position = "none")
ggplotly(a)
## `geom_smooth()` using formula = 'y ~ x'
#Identificar la ecuación
#ln(p/1-p)=β0+β1X
summary <- summary(modelo_logistico)
summary
##
## Call:
## glm(formula = y ~ balance, family = "binomial", data = dsBankFullTr)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.081e+00 1.595e-02 -130.50 <2e-16 ***
## balance 3.958e-05 3.840e-06 10.31 <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: 32532 on 45209 degrees of freedom
## AIC: 32536
##
## Number of Fisher Scoring iterations: 4
Intercepto <- summary$coefficients[1,1];Intercepto
## [1] -2.080967
Pendiente <- summary$coefficients[2,1];Pendiente
## [1] 3.958116e-05
#ln(p/1-p)= -10.65 + 0.005499x
#Tarea para hoy Incluir la ecuación en el gráfico
#Test de Wald para coeficientes individuales
#Significancia de la variable independiente
#Ho:La variable NO es significativa.
#Ha:La variable es significativa.
#summary
#como el p-valor de los coeficientes es menor que el nivel
#de significancia 0.05 se rechaza la hipótesis nula. Es decir,
#la variable es significativa.
#ln(p/1-p)= -10.65 + 0.005499x
#Analizar los coeficientes
exp(Pendiente)
## [1] 1.00004
exp(Intercepto)
## [1] 0.1248094
#odd Ratio de la variable independiente es 1.005514
#Por cada unidad que aumenta la variable balance el odds
#de que se presente el evento aumenta 1.005514 veces.
#Calcular las probabilidades
head(modelo_logistico$fitted.values)
## 1 2 3 4 5 6
## 0.1196083 0.1110738 0.1109683 0.1169786 0.1109644 0.1118657
head(round(modelo_logistico$fitted.values,0),10)
## 1 2 3 4 5 6 7 8 9 10
## 0 0 0 0 0 0 0 0 0 0
#Probabilidad de que ocurra el evento 1 y así sucesivamente
#Clasificar según la probabilidad
#Elegir un punto de corte
dsBankFullTr$pred <- as.numeric(modelo_logistico$fitted.values>=0.5)
df <- data.frame(round(modelo_logistico$fitted.values,0),dsBankFullTr$pred)
# Crear un nuevo conjunto de datos para hacer predicciones
#(balance es la variable independiente)
nuevos_datos <- data.frame(balance = c(100, 500,
1000, 1500,
2000, 2500))
summary(dsBankFullTr$balance)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -8019 72 448 1362 1428 102127
# Realizar predicciones con el modelo logístico
predicciones <- predict(modelo_logistico,
newdata = nuevos_datos,
type = "response")
#type = "response" se especifica para obtener las
#probabilidades predichas.
# Mostrar las predicciones
print(predicciones)
## 1 2 3 4 5 6
## 0.1113516 0.1129279 0.1149257 0.1169541 0.1190136 0.1211043
#Clasificar según un umbral
umbral <- 0.5
clases_predichas <- ifelse(predicciones >= umbral, "Yes", "No")
print(clases_predichas)
## 1 2 3 4 5 6
## "No" "No" "No" "No" "No" "No"
#consultar y agregar al script la Matriz de confusión
library(caret)
## Cargando paquete requerido: lattice
##
## Adjuntando el paquete: 'caret'
## The following object is masked from 'package:purrr':
##
## lift
matriz_conf <- confusionMatrix(as.factor(dsBankFullTr$y),
as.factor(dsBankFullTr$pred))
#Acepta variables tipo factor
matriz_conf
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 39911 11
## 1 5285 4
##
## Accuracy : 0.8829
## 95% CI : (0.8799, 0.8858)
## No Information Rate : 0.9997
## P-Value [Acc > NIR] : 1
##
## Kappa : 8e-04
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.8830649
## Specificity : 0.2666667
## Pos Pred Value : 0.9997245
## Neg Pred Value : 0.0007563
## Prevalence : 0.9996682
## Detection Rate : 0.8827719
## Detection Prevalence : 0.8830152
## Balanced Accuracy : 0.5748658
##
## 'Positive' Class : 0
##