Modelos Lineales Generalizados

Modelo logístico

Author

Dante Conti, Sergi Ramirez, (c) IDEAI

Published

April 21, 2026

Modified

April 21, 2026

1 Introducción

El objetivo detrás del uso de modelos es el de intentar explicar el comportamiento de una variable en función del comportamiento de otras que se cree que influyen en ella.

Hay tipos de variables a predecir que no pueden analizarse correctamente con el modelo de regresión lineal múltiple porque la variable respuesta, la que interesa predecir en cada ejemplo, no sigue una distribución de probabilidad normal (supuesto necesario para utilizar la regresión lineal) o ni siquiera es continua. Por ejemplo disponemos:

  • variable dicotómica/binaria asignando los valores 0 y 1 a las dos posibles respuestas, lo que encaja perfectamente con una distribución de probabilidad de Bernoulli (muy distinta de la normal, ya que es discreta, aunque podría parecerse)

  • variables de tipo recuento (solo cero o valores positivos) modelizables mediante una variable discreta que podría seguir una distribución de Poisson (que es también distinta a la normal, por ser discreta, aunque también podría parecerse).

El modelo lineal generalizado (GLM) consiste en modelos que generlizan el caso en que la variable respuesta sea normal a cualquier tipo de distribución de probabilidad perteneciente a la familia exponencial y que permite varianzas no constantes en los errores.

1.1 El modelo y sus componentes

El modelo lineal generalizado se escribe como:

\[ \mu = g^{-1}(\eta) \]

en el que se tiene las siguientes componentes:

  1. \(\mu = E(Y)\): la media de la variable respuesta Y, que puede seguir cualquier distribución de probabilidad de la familia exponencial.

  2. \(\eta = X\beta\): la “estructura” que aportan las variables explicativas/predictoras.

  3. \(g(\cdot)\) (función de enlace): relaciona los dos componentes anteriores.

1.2 Función de enlace

Cada distribución de probabilidad tiene asociada una función enlace canónica:

  • Para la normal es la identidad: \(g(\mu) = \mu\)

  • Para la Bernoulli, es la función logit: \(g(\mu) = logit(\mu) = log(\frac{\mu}{1-\mu})\)

  • Para la Poisson, es el logaritmo: \(g(\mu) = log(\mu)\)

  • Para la gamma, es la inversa: \(g(\mu) = 1/\mu\)

2 La regresión logística

La regresión logística es un modelo lineal generalizado que se utiliza cuando la variable respuesta es binaria, es decir, cuando solo puede tomar dos valores, habitualmente 0 y 1.

Ejemplos típicos:

  • aprobar / no aprobar
  • enfermo / no enfermo
  • compra / no compra
  • fraude / no fraude

A diferencia de la regresión lineal, aquí no modelizamos directamente el valor de la variable respuesta, sino la probabilidad de que ocurra el evento de interés.

2.1 ¿Por qué no usar regresión lineal?

Si la respuesta solo puede valer 0 o 1, una recta de regresión puede producir predicciones imposibles, por ejemplo menores que 0 o mayores que 1. Además, la relación entre predictores y probabilidad no suele ser lineal.

La regresión logística resuelve este problema modelizando:

[ (p) = () = _0 + _1X_1 + + _pX_p ]

donde:

  • (p = P(Y=1)) es la probabilidad del evento de interés
  • () son las odds
  • (()) es el logit

3 Objetivos de aprendizaje

En este tutorial aprenderemos a:

  1. entender qué hace la regresión logística
  2. ajustar un modelo con glm()
  3. interpretar coeficientes y odds ratio
  4. obtener probabilidades predichas
  5. clasificar observaciones
  6. evaluar el modelo con matriz de confusión y AUC
  7. representar gráficamente los resultados
  8. revisar observaciones influyentes
Mostrar código
list.of.packages <- c("tidyverse", "ggplot2", "broom", "pROC", "caret", "haven", "mice", "ResourceSelection", "Epi")

new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[, "Package"])]
if (length(new.packages) > 0) {
  install.packages(new.packages)
}

invisible(lapply(list.of.packages, require, character.only = TRUE))
rm(list.of.packages, new.packages)

4 Conjunto de datos de trabajo

Este conjunto de datos simula un entorno académico realista para 10 000 estudiantes y está diseñado para predecir el abandono escolar . Incluye características demográficas, conductuales y de rendimiento académico, como promedio general de calificaciones (GPA), promedio general de calificaciones semestral (GPA semestral), promedio general acumulado de calificaciones (CGPA), hábitos de estudio, asistencia, índice de estrés, nivel educativo de los padres y departamento.

Aunque sintéticos, los datos imitan fielmente la distribución real de los estudiantes , incluyendo una ligera asimetría en los ingresos y el estrés y correlaciones lógicas entre el rendimiento académico y el riesgo de abandono escolar.

Variable objetivo:

  • Dropout(0 = continuó, 1 = abandonó)

Características principales:

  • Student_ID: Identificador único de estudiante
  • Age: Edad del estudiante en años
  • Gender: Masculino / Femenino
  • Family_Income: Ingresos` familiares mensuales
  • Internet_Access: Sí / No
  • Study_Hours_per_Day Horas de estudio promedio por día
  • Attendance_Rate Porcentaje de asistencia
  • Assignment_Delay_Days: Retraso promedio en la asignación (en días)
  • Travel_Time_Minutes: Tiempo de desplazamiento diario en minutos
  • Part_Time_Job Sí / No
  • Scholarship Sí / No
  • Stress_Index Nivel de estrés autoinformado (1–10)
  • GPA, Semester_GPA, CGPA: Rendimiento académico
  • Semester Año actual (años 1-4)
  • Department Ciencias, Artes, Negocios, Informática, Ingeniería
  • Parental_Education Nivel educativo más alto de los padre
Mostrar código
datos <- read.csv("student_dropout_dataset_v3.csv")

tempData <- mice(datos, m = 5, maxit = 50, meth = 'pmm', seed = 500)

 iter imp variable
  1   1  Family_Income  Study_Hours_per_Day  Stress_Index
  1   2  Family_Income  Study_Hours_per_Day  Stress_Index
  1   3  Family_Income  Study_Hours_per_Day  Stress_Index
  1   4  Family_Income  Study_Hours_per_Day  Stress_Index
  1   5  Family_Income  Study_Hours_per_Day  Stress_Index
  2   1  Family_Income  Study_Hours_per_Day  Stress_Index
  2   2  Family_Income  Study_Hours_per_Day  Stress_Index
  2   3  Family_Income  Study_Hours_per_Day  Stress_Index
  2   4  Family_Income  Study_Hours_per_Day  Stress_Index
  2   5  Family_Income  Study_Hours_per_Day  Stress_Index
  3   1  Family_Income  Study_Hours_per_Day  Stress_Index
  3   2  Family_Income  Study_Hours_per_Day  Stress_Index
  3   3  Family_Income  Study_Hours_per_Day  Stress_Index
  3   4  Family_Income  Study_Hours_per_Day  Stress_Index
  3   5  Family_Income  Study_Hours_per_Day  Stress_Index
  4   1  Family_Income  Study_Hours_per_Day  Stress_Index
  4   2  Family_Income  Study_Hours_per_Day  Stress_Index
  4   3  Family_Income  Study_Hours_per_Day  Stress_Index
  4   4  Family_Income  Study_Hours_per_Day  Stress_Index
  4   5  Family_Income  Study_Hours_per_Day  Stress_Index
  5   1  Family_Income  Study_Hours_per_Day  Stress_Index
  5   2  Family_Income  Study_Hours_per_Day  Stress_Index
  5   3  Family_Income  Study_Hours_per_Day  Stress_Index
  5   4  Family_Income  Study_Hours_per_Day  Stress_Index
  5   5  Family_Income  Study_Hours_per_Day  Stress_Index
  6   1  Family_Income  Study_Hours_per_Day  Stress_Index
  6   2  Family_Income  Study_Hours_per_Day  Stress_Index
  6   3  Family_Income  Study_Hours_per_Day  Stress_Index
  6   4  Family_Income  Study_Hours_per_Day  Stress_Index
  6   5  Family_Income  Study_Hours_per_Day  Stress_Index
  7   1  Family_Income  Study_Hours_per_Day  Stress_Index
  7   2  Family_Income  Study_Hours_per_Day  Stress_Index
  7   3  Family_Income  Study_Hours_per_Day  Stress_Index
  7   4  Family_Income  Study_Hours_per_Day  Stress_Index
  7   5  Family_Income  Study_Hours_per_Day  Stress_Index
  8   1  Family_Income  Study_Hours_per_Day  Stress_Index
  8   2  Family_Income  Study_Hours_per_Day  Stress_Index
  8   3  Family_Income  Study_Hours_per_Day  Stress_Index
  8   4  Family_Income  Study_Hours_per_Day  Stress_Index
  8   5  Family_Income  Study_Hours_per_Day  Stress_Index
  9   1  Family_Income  Study_Hours_per_Day  Stress_Index
  9   2  Family_Income  Study_Hours_per_Day  Stress_Index
  9   3  Family_Income  Study_Hours_per_Day  Stress_Index
  9   4  Family_Income  Study_Hours_per_Day  Stress_Index
  9   5  Family_Income  Study_Hours_per_Day  Stress_Index
  10   1  Family_Income  Study_Hours_per_Day  Stress_Index
  10   2  Family_Income  Study_Hours_per_Day  Stress_Index
  10   3  Family_Income  Study_Hours_per_Day  Stress_Index
  10   4  Family_Income  Study_Hours_per_Day  Stress_Index
  10   5  Family_Income  Study_Hours_per_Day  Stress_Index
  11   1  Family_Income  Study_Hours_per_Day  Stress_Index
  11   2  Family_Income  Study_Hours_per_Day  Stress_Index
  11   3  Family_Income  Study_Hours_per_Day  Stress_Index
  11   4  Family_Income  Study_Hours_per_Day  Stress_Index
  11   5  Family_Income  Study_Hours_per_Day  Stress_Index
  12   1  Family_Income  Study_Hours_per_Day  Stress_Index
  12   2  Family_Income  Study_Hours_per_Day  Stress_Index
  12   3  Family_Income  Study_Hours_per_Day  Stress_Index
  12   4  Family_Income  Study_Hours_per_Day  Stress_Index
  12   5  Family_Income  Study_Hours_per_Day  Stress_Index
  13   1  Family_Income  Study_Hours_per_Day  Stress_Index
  13   2  Family_Income  Study_Hours_per_Day  Stress_Index
  13   3  Family_Income  Study_Hours_per_Day  Stress_Index
  13   4  Family_Income  Study_Hours_per_Day  Stress_Index
  13   5  Family_Income  Study_Hours_per_Day  Stress_Index
  14   1  Family_Income  Study_Hours_per_Day  Stress_Index
  14   2  Family_Income  Study_Hours_per_Day  Stress_Index
  14   3  Family_Income  Study_Hours_per_Day  Stress_Index
  14   4  Family_Income  Study_Hours_per_Day  Stress_Index
  14   5  Family_Income  Study_Hours_per_Day  Stress_Index
  15   1  Family_Income  Study_Hours_per_Day  Stress_Index
  15   2  Family_Income  Study_Hours_per_Day  Stress_Index
  15   3  Family_Income  Study_Hours_per_Day  Stress_Index
  15   4  Family_Income  Study_Hours_per_Day  Stress_Index
  15   5  Family_Income  Study_Hours_per_Day  Stress_Index
  16   1  Family_Income  Study_Hours_per_Day  Stress_Index
  16   2  Family_Income  Study_Hours_per_Day  Stress_Index
  16   3  Family_Income  Study_Hours_per_Day  Stress_Index
  16   4  Family_Income  Study_Hours_per_Day  Stress_Index
  16   5  Family_Income  Study_Hours_per_Day  Stress_Index
  17   1  Family_Income  Study_Hours_per_Day  Stress_Index
  17   2  Family_Income  Study_Hours_per_Day  Stress_Index
  17   3  Family_Income  Study_Hours_per_Day  Stress_Index
  17   4  Family_Income  Study_Hours_per_Day  Stress_Index
  17   5  Family_Income  Study_Hours_per_Day  Stress_Index
  18   1  Family_Income  Study_Hours_per_Day  Stress_Index
  18   2  Family_Income  Study_Hours_per_Day  Stress_Index
  18   3  Family_Income  Study_Hours_per_Day  Stress_Index
  18   4  Family_Income  Study_Hours_per_Day  Stress_Index
  18   5  Family_Income  Study_Hours_per_Day  Stress_Index
  19   1  Family_Income  Study_Hours_per_Day  Stress_Index
  19   2  Family_Income  Study_Hours_per_Day  Stress_Index
  19   3  Family_Income  Study_Hours_per_Day  Stress_Index
  19   4  Family_Income  Study_Hours_per_Day  Stress_Index
  19   5  Family_Income  Study_Hours_per_Day  Stress_Index
  20   1  Family_Income  Study_Hours_per_Day  Stress_Index
  20   2  Family_Income  Study_Hours_per_Day  Stress_Index
  20   3  Family_Income  Study_Hours_per_Day  Stress_Index
  20   4  Family_Income  Study_Hours_per_Day  Stress_Index
  20   5  Family_Income  Study_Hours_per_Day  Stress_Index
  21   1  Family_Income  Study_Hours_per_Day  Stress_Index
  21   2  Family_Income  Study_Hours_per_Day  Stress_Index
  21   3  Family_Income  Study_Hours_per_Day  Stress_Index
  21   4  Family_Income  Study_Hours_per_Day  Stress_Index
  21   5  Family_Income  Study_Hours_per_Day  Stress_Index
  22   1  Family_Income  Study_Hours_per_Day  Stress_Index
  22   2  Family_Income  Study_Hours_per_Day  Stress_Index
  22   3  Family_Income  Study_Hours_per_Day  Stress_Index
  22   4  Family_Income  Study_Hours_per_Day  Stress_Index
  22   5  Family_Income  Study_Hours_per_Day  Stress_Index
  23   1  Family_Income  Study_Hours_per_Day  Stress_Index
  23   2  Family_Income  Study_Hours_per_Day  Stress_Index
  23   3  Family_Income  Study_Hours_per_Day  Stress_Index
  23   4  Family_Income  Study_Hours_per_Day  Stress_Index
  23   5  Family_Income  Study_Hours_per_Day  Stress_Index
  24   1  Family_Income  Study_Hours_per_Day  Stress_Index
  24   2  Family_Income  Study_Hours_per_Day  Stress_Index
  24   3  Family_Income  Study_Hours_per_Day  Stress_Index
  24   4  Family_Income  Study_Hours_per_Day  Stress_Index
  24   5  Family_Income  Study_Hours_per_Day  Stress_Index
  25   1  Family_Income  Study_Hours_per_Day  Stress_Index
  25   2  Family_Income  Study_Hours_per_Day  Stress_Index
  25   3  Family_Income  Study_Hours_per_Day  Stress_Index
  25   4  Family_Income  Study_Hours_per_Day  Stress_Index
  25   5  Family_Income  Study_Hours_per_Day  Stress_Index
  26   1  Family_Income  Study_Hours_per_Day  Stress_Index
  26   2  Family_Income  Study_Hours_per_Day  Stress_Index
  26   3  Family_Income  Study_Hours_per_Day  Stress_Index
  26   4  Family_Income  Study_Hours_per_Day  Stress_Index
  26   5  Family_Income  Study_Hours_per_Day  Stress_Index
  27   1  Family_Income  Study_Hours_per_Day  Stress_Index
  27   2  Family_Income  Study_Hours_per_Day  Stress_Index
  27   3  Family_Income  Study_Hours_per_Day  Stress_Index
  27   4  Family_Income  Study_Hours_per_Day  Stress_Index
  27   5  Family_Income  Study_Hours_per_Day  Stress_Index
  28   1  Family_Income  Study_Hours_per_Day  Stress_Index
  28   2  Family_Income  Study_Hours_per_Day  Stress_Index
  28   3  Family_Income  Study_Hours_per_Day  Stress_Index
  28   4  Family_Income  Study_Hours_per_Day  Stress_Index
  28   5  Family_Income  Study_Hours_per_Day  Stress_Index
  29   1  Family_Income  Study_Hours_per_Day  Stress_Index
  29   2  Family_Income  Study_Hours_per_Day  Stress_Index
  29   3  Family_Income  Study_Hours_per_Day  Stress_Index
  29   4  Family_Income  Study_Hours_per_Day  Stress_Index
  29   5  Family_Income  Study_Hours_per_Day  Stress_Index
  30   1  Family_Income  Study_Hours_per_Day  Stress_Index
  30   2  Family_Income  Study_Hours_per_Day  Stress_Index
  30   3  Family_Income  Study_Hours_per_Day  Stress_Index
  30   4  Family_Income  Study_Hours_per_Day  Stress_Index
  30   5  Family_Income  Study_Hours_per_Day  Stress_Index
  31   1  Family_Income  Study_Hours_per_Day  Stress_Index
  31   2  Family_Income  Study_Hours_per_Day  Stress_Index
  31   3  Family_Income  Study_Hours_per_Day  Stress_Index
  31   4  Family_Income  Study_Hours_per_Day  Stress_Index
  31   5  Family_Income  Study_Hours_per_Day  Stress_Index
  32   1  Family_Income  Study_Hours_per_Day  Stress_Index
  32   2  Family_Income  Study_Hours_per_Day  Stress_Index
  32   3  Family_Income  Study_Hours_per_Day  Stress_Index
  32   4  Family_Income  Study_Hours_per_Day  Stress_Index
  32   5  Family_Income  Study_Hours_per_Day  Stress_Index
  33   1  Family_Income  Study_Hours_per_Day  Stress_Index
  33   2  Family_Income  Study_Hours_per_Day  Stress_Index
  33   3  Family_Income  Study_Hours_per_Day  Stress_Index
  33   4  Family_Income  Study_Hours_per_Day  Stress_Index
  33   5  Family_Income  Study_Hours_per_Day  Stress_Index
  34   1  Family_Income  Study_Hours_per_Day  Stress_Index
  34   2  Family_Income  Study_Hours_per_Day  Stress_Index
  34   3  Family_Income  Study_Hours_per_Day  Stress_Index
  34   4  Family_Income  Study_Hours_per_Day  Stress_Index
  34   5  Family_Income  Study_Hours_per_Day  Stress_Index
  35   1  Family_Income  Study_Hours_per_Day  Stress_Index
  35   2  Family_Income  Study_Hours_per_Day  Stress_Index
  35   3  Family_Income  Study_Hours_per_Day  Stress_Index
  35   4  Family_Income  Study_Hours_per_Day  Stress_Index
  35   5  Family_Income  Study_Hours_per_Day  Stress_Index
  36   1  Family_Income  Study_Hours_per_Day  Stress_Index
  36   2  Family_Income  Study_Hours_per_Day  Stress_Index
  36   3  Family_Income  Study_Hours_per_Day  Stress_Index
  36   4  Family_Income  Study_Hours_per_Day  Stress_Index
  36   5  Family_Income  Study_Hours_per_Day  Stress_Index
  37   1  Family_Income  Study_Hours_per_Day  Stress_Index
  37   2  Family_Income  Study_Hours_per_Day  Stress_Index
  37   3  Family_Income  Study_Hours_per_Day  Stress_Index
  37   4  Family_Income  Study_Hours_per_Day  Stress_Index
  37   5  Family_Income  Study_Hours_per_Day  Stress_Index
  38   1  Family_Income  Study_Hours_per_Day  Stress_Index
  38   2  Family_Income  Study_Hours_per_Day  Stress_Index
  38   3  Family_Income  Study_Hours_per_Day  Stress_Index
  38   4  Family_Income  Study_Hours_per_Day  Stress_Index
  38   5  Family_Income  Study_Hours_per_Day  Stress_Index
  39   1  Family_Income  Study_Hours_per_Day  Stress_Index
  39   2  Family_Income  Study_Hours_per_Day  Stress_Index
  39   3  Family_Income  Study_Hours_per_Day  Stress_Index
  39   4  Family_Income  Study_Hours_per_Day  Stress_Index
  39   5  Family_Income  Study_Hours_per_Day  Stress_Index
  40   1  Family_Income  Study_Hours_per_Day  Stress_Index
  40   2  Family_Income  Study_Hours_per_Day  Stress_Index
  40   3  Family_Income  Study_Hours_per_Day  Stress_Index
  40   4  Family_Income  Study_Hours_per_Day  Stress_Index
  40   5  Family_Income  Study_Hours_per_Day  Stress_Index
  41   1  Family_Income  Study_Hours_per_Day  Stress_Index
  41   2  Family_Income  Study_Hours_per_Day  Stress_Index
  41   3  Family_Income  Study_Hours_per_Day  Stress_Index
  41   4  Family_Income  Study_Hours_per_Day  Stress_Index
  41   5  Family_Income  Study_Hours_per_Day  Stress_Index
  42   1  Family_Income  Study_Hours_per_Day  Stress_Index
  42   2  Family_Income  Study_Hours_per_Day  Stress_Index
  42   3  Family_Income  Study_Hours_per_Day  Stress_Index
  42   4  Family_Income  Study_Hours_per_Day  Stress_Index
  42   5  Family_Income  Study_Hours_per_Day  Stress_Index
  43   1  Family_Income  Study_Hours_per_Day  Stress_Index
  43   2  Family_Income  Study_Hours_per_Day  Stress_Index
  43   3  Family_Income  Study_Hours_per_Day  Stress_Index
  43   4  Family_Income  Study_Hours_per_Day  Stress_Index
  43   5  Family_Income  Study_Hours_per_Day  Stress_Index
  44   1  Family_Income  Study_Hours_per_Day  Stress_Index
  44   2  Family_Income  Study_Hours_per_Day  Stress_Index
  44   3  Family_Income  Study_Hours_per_Day  Stress_Index
  44   4  Family_Income  Study_Hours_per_Day  Stress_Index
  44   5  Family_Income  Study_Hours_per_Day  Stress_Index
  45   1  Family_Income  Study_Hours_per_Day  Stress_Index
  45   2  Family_Income  Study_Hours_per_Day  Stress_Index
  45   3  Family_Income  Study_Hours_per_Day  Stress_Index
  45   4  Family_Income  Study_Hours_per_Day  Stress_Index
  45   5  Family_Income  Study_Hours_per_Day  Stress_Index
  46   1  Family_Income  Study_Hours_per_Day  Stress_Index
  46   2  Family_Income  Study_Hours_per_Day  Stress_Index
  46   3  Family_Income  Study_Hours_per_Day  Stress_Index
  46   4  Family_Income  Study_Hours_per_Day  Stress_Index
  46   5  Family_Income  Study_Hours_per_Day  Stress_Index
  47   1  Family_Income  Study_Hours_per_Day  Stress_Index
  47   2  Family_Income  Study_Hours_per_Day  Stress_Index
  47   3  Family_Income  Study_Hours_per_Day  Stress_Index
  47   4  Family_Income  Study_Hours_per_Day  Stress_Index
  47   5  Family_Income  Study_Hours_per_Day  Stress_Index
  48   1  Family_Income  Study_Hours_per_Day  Stress_Index
  48   2  Family_Income  Study_Hours_per_Day  Stress_Index
  48   3  Family_Income  Study_Hours_per_Day  Stress_Index
  48   4  Family_Income  Study_Hours_per_Day  Stress_Index
  48   5  Family_Income  Study_Hours_per_Day  Stress_Index
  49   1  Family_Income  Study_Hours_per_Day  Stress_Index
  49   2  Family_Income  Study_Hours_per_Day  Stress_Index
  49   3  Family_Income  Study_Hours_per_Day  Stress_Index
  49   4  Family_Income  Study_Hours_per_Day  Stress_Index
  49   5  Family_Income  Study_Hours_per_Day  Stress_Index
  50   1  Family_Income  Study_Hours_per_Day  Stress_Index
  50   2  Family_Income  Study_Hours_per_Day  Stress_Index
  50   3  Family_Income  Study_Hours_per_Day  Stress_Index
  50   4  Family_Income  Study_Hours_per_Day  Stress_Index
  50   5  Family_Income  Study_Hours_per_Day  Stress_Index
Mostrar código
datos <- complete(tempData, 2)

datos$Dropout <- as.factor(datos$Dropout)

5 Exploración inicial

5.1 Proporción de abandono escolar

Mostrar código
datos %>%
  count(Dropout) %>%
  mutate(prop = n / sum(n))
Mostrar código
ggplot(datos, aes(x = Dropout)) +
  geom_bar() +
  labs(
    title = "Distribución de la variable respuesta",
    x = "Abandono",
    y = "Frecuencia"
  ) +
  theme_minimal()

Mostrar código
GGally::ggpairs(datos)

6 Ajuste del modelo logístico

La regresión logística en R se ajusta con glm() indicando family = binomial.

Mostrar código
modelo_log <- glm(Dropout ~ ., data = datos, family = binomial)
summary(modelo_log)

Call:
glm(formula = Dropout ~ ., family = binomial, data = datos)

Coefficients:
                                Estimate Std. Error z value Pr(>|z|)    
(Intercept)                    1.895e+00  4.353e-01   4.354 1.34e-05 ***
Student_ID                     1.234e-05  9.550e-06   1.292   0.1964    
Age                            1.083e-02  1.286e-02   0.842   0.3996    
GenderMale                    -6.247e-02  5.495e-02  -1.137   0.2556    
Family_Income                 -1.714e-06  1.340e-06  -1.279   0.2008    
Internet_AccessYes            -3.775e-01  8.031e-02  -4.701 2.59e-06 ***
Study_Hours_per_Day           -1.233e-02  2.190e-02  -0.563   0.5736    
Attendance_Rate               -3.093e-02  3.456e-03  -8.950  < 2e-16 ***
Assignment_Delay_Days          1.578e-01  1.995e-02   7.909 2.60e-15 ***
Travel_Time_Minutes            9.643e-03  2.322e-03   4.153 3.28e-05 ***
Part_Time_JobYes               2.216e-01  5.578e-02   3.973 7.09e-05 ***
ScholarshipYes                -2.756e-02  5.769e-02  -0.478   0.6328    
Stress_Index                   1.863e-01  1.722e-02  10.813  < 2e-16 ***
GPA                           -1.089e+00  9.825e-02 -11.083  < 2e-16 ***
Semester_GPA                  -8.243e-01  6.394e-01  -1.289   0.1973    
CGPA                           7.971e-01  6.325e-01   1.260   0.2076    
SemesterYear 2                 1.879e-01  7.844e-02   2.395   0.0166 *  
SemesterYear 3                 1.430e-01  7.836e-02   1.825   0.0679 .  
SemesterYear 4                 1.394e-01  7.850e-02   1.776   0.0757 .  
DepartmentBusiness            -3.567e-02  8.656e-02  -0.412   0.6803    
DepartmentCS                  -7.197e-02  8.678e-02  -0.829   0.4069    
DepartmentEngineering         -6.396e-02  8.685e-02  -0.736   0.4615    
DepartmentScience             -4.990e-02  8.622e-02  -0.579   0.5628    
Parental_EducationHigh School  5.970e-02  6.561e-02   0.910   0.3629    
Parental_EducationMaster      -8.705e-02  7.675e-02  -1.134   0.2567    
Parental_EducationNone         9.656e-02  1.271e-01   0.760   0.4475    
Parental_EducationPhD          9.486e-02  1.338e-01   0.709   0.4782    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 10914  on 9999  degrees of freedom
Residual deviance:  8305  on 9973  degrees of freedom
AIC: 8359

Number of Fisher Scoring iterations: 5

7 Interpretación del output

7.1 Estructura del modelo

El modelo ajustado tiene la forma:

\[\log\left(\frac{p}{1-p}\right) = \beta_0 + \sum_{i =1}^{p} \beta_{i}X_{i}\]

7.2 ¿Qué mirar en el summary()?

7.2.1 Signo del coeficiente

  • si el coeficiente es positivo, al aumentar esa variable aumenta la probabilidad de (Dropout=1)
  • si el coeficiente es negativo, al aumentar esa variable disminuye la probabilidad de (Dropout=1)

7.2.2 Valor p

  • si p-value < 0.05, la variable se considera significativa
  • si p-value > 0.05, no hay evidencia suficiente de efecto estadísticamente significativo

7.2.3 Deviance

  • null deviance: Indica lo “bien” que predice el modelo sin variables explicativas (sólo con el término independiente)

  • residual deviance: Indica lo “bien” que predice el modelo con las variables explicativas.

Un contraste Chi-cuadrado permitirá dilucidar si el modelo con variables explicativas predice significativamente mejor que el que solo tiene un término independiente y su predicción, sea cual sea el valor de las variables explicativas, es siempre la media de los valores de la variable respuesta.

7.2.4 Actualizar modelo con nuevas variables

Si se quiere actualizar un modelo con nuevas variables, basta con usar la función update.

Mostrar código
regresion_update <- update(modelo_log, ~ . + var1 + var2)

7.2.5 Adecuación del modelo

Para evaluar la bondad de ajuste de los modelos se lleva a cabo el contraste de Hosmer-Lemeshow:

Mostrar código
hoslem.test(modelo_log$y, modelo_log$fitted.values)

    Hosmer and Lemeshow goodness of fit (GOF) test

data:  modelo_log$y, modelo_log$fitted.values
X-squared = 2.6468, df = 8, p-value = 0.9545

Al tener p-valor alto, indica un ajuste suficientemente bueno.

Podemos realizar el test de la razón de verosimilitud.

Mostrar código
anova(modelo_log, test = "Chisq")

Las deviances correspondientes a añadir secuencialmente cada variable o factor al modelo que contiene los anteriores permite concluir que dicha inclusión secuencial de tales variables predictoras es significativa respecto a los modelos que no las incluyen.

Para completar, se podría contrastar también el efecto de una variable sobre la respuesta comparando la deviance del modelo con dicha variable y sin ella.

El valor del pseudo \(R^{2}\) de McFadden se obtiene de la siguiente forma:

Mostrar código
null <- glm(Dropout ~ ., data = datos, family = binomial)
1 - logLik(modelo_log) / logLik(null)
'log Lik.' 0 (df=27)

7.2.6 Magnitud

Los coeficientes están en escala log-odds, por lo que no conviene interpretarlos directamente en términos de probabilidad.

8 Odds y Odds Ratio

8.1 Qué son las odds

Las odds son:

[ = ]

Por ejemplo, si (p = 0.8), entonces:

[ = = 4 ]

Eso significa que el evento es 4 veces más probable que el no evento.

8.2 Odds Ratio

Para interpretar mejor los coeficientes, usamos la exponencial:

[ OR = e^{} ]

Mostrar código
exp(coef(modelo_log))
                  (Intercept)                    Student_ID 
                    6.6524242                     1.0000123 
                          Age                    GenderMale 
                    1.0108914                     0.9394417 
                Family_Income            Internet_AccessYes 
                    0.9999983                     0.6855535 
          Study_Hours_per_Day               Attendance_Rate 
                    0.9877490                     0.9695397 
        Assignment_Delay_Days           Travel_Time_Minutes 
                    1.1709353                     1.0096899 
             Part_Time_JobYes                ScholarshipYes 
                    1.2481252                     0.9728139 
                 Stress_Index                           GPA 
                    1.2047265                     0.3365748 
                 Semester_GPA                          CGPA 
                    0.4385574                     2.2191490 
               SemesterYear 2                SemesterYear 3 
                    1.2066783                     1.1537866 
               SemesterYear 4            DepartmentBusiness 
                    1.1496080                     0.9649584 
                 DepartmentCS         DepartmentEngineering 
                    0.9305613                     0.9380458 
            DepartmentScience Parental_EducationHigh School 
                    0.9513250                     1.0615138 
     Parental_EducationMaster        Parental_EducationNone 
                    0.9166313                     1.1013723 
        Parental_EducationPhD 
                    1.0995097 

8.3 Intervalos de confianza de los Odds Ratio

Mostrar código
exp(confint(modelo_log))
                                  2.5 %     97.5 %
(Intercept)                   2.8367054 15.6284808
Student_ID                    0.9999936  1.0000311
Age                           0.9857212  1.0366895
GenderMale                    0.8434886  1.0462454
Family_Income                 0.9999956  1.0000009
Internet_AccessYes            0.5860904  0.8029947
Study_Hours_per_Day           0.9462257  1.0310636
Attendance_Rate               0.9629783  0.9761162
Assignment_Delay_Days         1.1260309  1.2176558
Travel_Time_Minutes           1.0051090  1.0142997
Part_Time_JobYes              1.1188047  1.3922975
ScholarshipYes                0.8685974  1.0890575
Stress_Index                  1.1648349  1.2462120
GPA                           0.2774725  0.4078554
Semester_GPA                  0.1251686  1.5350837
CGPA                          0.6425914  7.6724297
SemesterYear 2                1.0348306  1.4074116
SemesterYear 3                0.9895970  1.3455104
SemesterYear 4                0.9857382  1.3409981
DepartmentBusiness            0.8143275  1.1433794
DepartmentCS                  0.7849432  1.1030681
DepartmentEngineering         0.7911435  1.1120902
DepartmentScience             0.8033606  1.1264837
Parental_EducationHigh School 0.9333331  1.2071267
Parental_EducationMaster      0.7882268  1.0649600
Parental_EducationNone        0.8563089  1.4098258
Parental_EducationPhD         0.8433880  1.4252969

8.4 Tabla ordenada para interpretar

Mostrar código
tabla_or <- tidy(modelo_log) %>%
  mutate(
    odds_ratio = exp(estimate),
    OR_inf = exp(estimate - 1.96 * std.error),
    OR_sup = exp(estimate + 1.96 * std.error)
  )

tabla_or

8.5 Cómo interpretar un OR

  • OR > 1: al aumentar la variable, aumentan las odds de que ocurra el evento
  • OR < 1: al aumentar la variable, disminuyen las odds
  • OR = 1: no hay efecto

Ejemplo de lectura:

  • si OR = 1.50, cada incremento unitario multiplica las odds por 1.50
  • si OR = 0.80, cada incremento unitario reduce las odds un 20%

9 Probabilidades predichas

9.1 Obtener probabilidades

Mostrar código
datos <- datos %>%
  mutate(
    prob_pred = predict(modelo_log, type = "response")
  )

head(datos)

Las probabilidades predichas siempre estarán entre 0 y 1.

9.2 Visualizar probabilidades predichas

Mostrar código
ggplot(datos, aes(x = prob_pred)) +
  geom_histogram(bins = 30) +
  labs(
    title = "Distribución de probabilidades predichas",
    x = "Probabilidad predicha",
    y = "Frecuencia"
  ) +
  theme_minimal()

10 Clasificación

Para convertir probabilidades en clases, elegimos un punto de corte. El más habitual es 0.5.

Mostrar código
datos <- datos %>%
  mutate(
    pred_clase = ifelse(prob_pred >= 0.5, 1, 0),
    pred_factor = factor(pred_clase, levels = c(0,1), labels = c("No", "Sí"))
  )

11 Matriz de confusión

Mostrar código
datos$Dropout <- as.factor(ifelse(datos$Dropout == 0, "No", "Sí"))
confusionMatrix(datos$pred_factor, datos$Dropout, positive = "Sí")
Confusion Matrix and Statistics

          Reference
Prediction   No   Sí
        No 7170 1395
        Sí  476  959
                                          
               Accuracy : 0.8129          
                 95% CI : (0.8051, 0.8205)
    No Information Rate : 0.7646          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.399           
                                          
 Mcnemar's Test P-Value : < 2.2e-16       
                                          
            Sensitivity : 0.4074          
            Specificity : 0.9377          
         Pos Pred Value : 0.6683          
         Neg Pred Value : 0.8371          
             Prevalence : 0.2354          
         Detection Rate : 0.0959          
   Detection Prevalence : 0.1435          
      Balanced Accuracy : 0.6726          
                                          
       'Positive' Class : Sí              
                                          

11.1 Qué mirar en la matriz de confusión

  • Accuracy: porcentaje total de aciertos
  • Sensitivity / Recall: capacidad para detectar los casos positivos
  • Specificity: capacidad para detectar los casos negativos

12 Curva ROC y AUC

La curva ROC representa la capacidad discriminante del modelo para distintos puntos de corte.

Mostrar código
roc_obj <- roc(datos$Dropout, datos$prob_pred)
auc(roc_obj)
Area under the curve: 0.8235
Mostrar código
plot(roc_obj, main = "Curva ROC")
abline(a = 0, b = 1, lty = 2, col = "gray")

12.1 Interpretación del AUC

  • 0.5: el modelo no discrimina

  • 0.6 - 0.7: pobre

  • 0.7 - 0.8: aceptable

  • 0.8 - 0.9: bueno

  • 0.9: excelente

Mostrar código
ROC(form = modelo_log$formula, data = datos, plot = "sp")

Mostrar código
ROC(
  form = modelo_log$formula, data = datos,
  plot = "ROC", las = 1
)

13 Visualización del ajuste en un caso simple

Para ver mejor la forma logística, ajustamos un modelo con una sola variable.

Mostrar código
modelo_simple <- glm(Dropout ~ 1, data = datos,family = binomial)
summary(modelo_simple)

Call:
glm(formula = Dropout ~ 1, family = binomial, data = datos)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept) -1.17807    0.02357  -49.98   <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: 10914  on 9999  degrees of freedom
Residual deviance: 10914  on 9999  degrees of freedom
AIC: 10916

Number of Fisher Scoring iterations: 4
Mostrar código
ggplot(datos, aes(x = Attendance_Rate, y = Dropout)) +
  geom_jitter(height = 0.05, width = 0, alpha = 0.35) +
  stat_smooth(
    method = "glm",
    method.args = list(family = "binomial"),
    se = TRUE
  ) +
  labs(
    title = "Curva logística ajustada",
    x = "Horas de estudio",
    y = "Probabilidad de aprobar"
  ) +
  theme_minimal()

14 Diagnóstico del modelo logístico

En regresión logística no se revisan exactamente los mismos supuestos que en regresión lineal.

Aquí no exigimos:

  • normalidad de residuos
  • homocedasticidad clásica

En cambio, nos interesa revisar:

  • calidad del ajuste
  • observaciones influyentes
  • residuos anómalos
  • capacidad predictiva

14.1 Residuos de deviance

Mostrar código
res_dev <- residuals(modelo_log, type = "deviance")

ggplot(data.frame(
  fitted = fitted(modelo_log),
  resid = res_dev
), aes(x = fitted, y = resid)) +
  geom_point(alpha = 0.6) +
  geom_hline(yintercept = 0, linetype = 2, color = "red") +
  labs(
    title = "Residuos de deviance vs valores ajustados",
    x = "Valores ajustados",
    y = "Residuos de deviance"
  ) +
  theme_minimal()

14.2 Qué mirar aquí

  • residuos repartidos sin patrón claro: mejor
  • puntos muy alejados: posibles observaciones problemáticas
  • patrones extraños: posible mala especificación del modelo

14.3 Observaciones influyentes: distancia de Cook

Mostrar código
cooks <- cooks.distance(modelo_log)

df_cooks <- data.frame(
  index = 1:length(cooks),
  cooks = cooks
)

threshold <- 4 / nrow(datos)

ggplot(df_cooks, aes(x = index, y = cooks)) +
  geom_segment(aes(xend = index, yend = 0), alpha = 0.6) +
  geom_point(
    data = subset(df_cooks, cooks > threshold),
    size = 2
  ) +
  geom_hline(yintercept = threshold, color = "red", linetype = "dashed") +
  labs(
    title = "Distancia de Cook",
    subtitle = "Las observaciones por encima de la línea roja son potencialmente influyentes",
    x = "Observación",
    y = "Cook's distance"
  ) +
  theme_minimal()

14.4 Qué mirar en Cook

  • valores bajos: observaciones sin influencia relevante
  • valores altos: observaciones influyentes
  • puntos por encima de 4/n: candidatos a revisión

15 Bibliografia

Aquesta web està creada por Dante Conti y Sergi Ramírez, (c) 2026