Introducción

En esta actividad se desarrolla un modelo de regresión logística para predecir la probabilidad de rotación de empleados en una organización. Se utilizan variables relacionadas con características laborales y personales de los trabajadores, con el fin de identificar los factores que más influyen en el cambio de cargo y proponer estrategias de retención del talento.


Carga de librerías

# Instalar paquete si es necesario (descomentar la primera vez)
# install.packages("devtools")
# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)

library(paqueteMODELOS)
library(tidyverse)
library(knitr)
library(kableExtra)
library(pROC)
library(caret)
library(gridExtra)
library(naniar)      # para visualizar NAs

data("rotacion")

# Codificar variable respuesta: Si=1, No=0
rotacion$y <- ifelse(rotacion$Rotación == "Si", 1, 0)

0. Exploración Inicial del Dataset

Estructura general

glimpse(rotacion)
## Rows: 1,470
## Columns: 25
## $ Rotación                    <chr> "Si", "No", "Si", "No", "No", "No", "No", …
## $ Edad                        <dbl> 41, 49, 37, 33, 27, 32, 59, 30, 38, 36, 35…
## $ `Viaje de Negocios`         <chr> "Raramente", "Frecuentemente", "Raramente"…
## $ Departamento                <chr> "Ventas", "IyD", "IyD", "IyD", "IyD", "IyD…
## $ Distancia_Casa              <dbl> 1, 8, 2, 3, 2, 2, 3, 24, 23, 27, 16, 15, 2…
## $ Educación                   <dbl> 2, 1, 2, 4, 1, 2, 3, 1, 3, 3, 3, 2, 1, 2, …
## $ Campo_Educación             <chr> "Ciencias", "Ciencias", "Otra", "Ciencias"…
## $ Satisfacción_Ambiental      <dbl> 2, 3, 4, 4, 1, 4, 3, 4, 4, 3, 1, 4, 1, 2, …
## $ Genero                      <chr> "F", "M", "M", "F", "M", "M", "F", "M", "M…
## $ Cargo                       <chr> "Ejecutivo_Ventas", "Investigador_Cientifi…
## $ Satisfación_Laboral         <dbl> 4, 2, 3, 3, 2, 4, 1, 3, 3, 3, 2, 3, 3, 4, …
## $ Estado_Civil                <chr> "Soltero", "Casado", "Soltero", "Casado", …
## $ Ingreso_Mensual             <dbl> 5993, 5130, 2090, 2909, 3468, 3068, 2670, …
## $ Trabajos_Anteriores         <dbl> 8, 1, 6, 1, 9, 0, 4, 1, 0, 6, 0, 0, 1, 0, …
## $ Horas_Extra                 <chr> "Si", "No", "Si", "Si", "No", "No", "Si", …
## $ Porcentaje_aumento_salarial <dbl> 11, 23, 15, 11, 12, 13, 20, 22, 21, 13, 13…
## $ Rendimiento_Laboral         <dbl> 3, 4, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, …
## $ Años_Experiencia            <dbl> 8, 10, 7, 8, 6, 8, 12, 1, 10, 17, 6, 10, 5…
## $ Capacitaciones              <dbl> 0, 3, 3, 3, 3, 2, 3, 2, 2, 3, 5, 3, 1, 2, …
## $ Equilibrio_Trabajo_Vida     <dbl> 1, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3, 2, 3, …
## $ Antigüedad                  <dbl> 6, 10, 0, 8, 2, 7, 1, 1, 9, 7, 5, 9, 5, 2,…
## $ Antigüedad_Cargo            <dbl> 4, 7, 0, 7, 2, 7, 0, 0, 7, 7, 4, 5, 2, 2, …
## $ Años_ultima_promoción       <dbl> 0, 1, 0, 3, 2, 3, 0, 0, 1, 7, 0, 0, 4, 1, …
## $ Años_acargo_con_mismo_jefe  <dbl> 5, 7, 0, 0, 2, 6, 0, 0, 8, 7, 3, 8, 3, 2, …
## $ y                           <dbl> 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …

La base de datos analizada contiene un total de 1,470 observaciones y 25 variables, lo que constituye un tamaño de muestra adecuado para el desarrollo de modelos estadísticos robustos. A partir de la exploración inicial, se identifica una combinación de variables de tipo numérico y categórico, lo que permite analizar el fenómeno de rotación desde múltiples dimensiones. Entre las variables disponibles se incluyen características demográficas (como edad y género), variables laborales (ingreso mensual, antigüedad, horas extra) y factores relacionados con el entorno organizacional (satisfacción laboral, equilibrio trabajo-vida, viajes de negocio).

Esta diversidad de variables sugiere que la rotación de empleados es un fenómeno multifactorial, influenciado tanto por condiciones económicas como por aspectos personales y organizacionales. Además, la presencia de variables categóricas con múltiples niveles implica la necesidad de transformaciones (como variables dummy) para su correcta inclusión en el modelo logístico. En conjunto, la estructura del dataset es adecuada para la estimación de un modelo de regresión logística, ya que permite capturar relaciones complejas entre las variables explicativas y la probabilidad de rotación.

Dimensiones y tipos de variables

data.frame(
  Filas = nrow(rotacion),
  Columnas = ncol(rotacion),
  Variables_numericas = sum(sapply(rotacion, is.numeric)),
  Variables_caracter = sum(sapply(rotacion, is.character))
) %>%
  kable(caption = "Tabla 1. Dimensiones del dataset") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 1. Dimensiones del dataset
Filas Columnas Variables_numericas Variables_caracter
1470 25 17 8

De la Tabla 1, del total de variables, 17 son de tipo numérico y 8 son de tipo categórico, lo cual evidencia una predominancia de variables cuantitativas que permiten capturar relaciones continuas y realizar análisis más detallados mediante técnicas estadísticas.

La presencia de variables numéricas resulta especialmente relevante para la estimación del modelo logístico, ya que estas permiten identificar cambios marginales en la probabilidad de rotación. Por otro lado, las variables categóricas aportan información cualitativa clave sobre las condiciones laborales y personales de los empleados, aunque requieren ser transformadas adecuadamente (por ejemplo, mediante variables indicadoras) para su inclusión en el modelo.

En conjunto, esta combinación de variables favorece un análisis integral del fenómeno de rotación, permitiendo evaluar tanto efectos discretos como continuos sobre la probabilidad de cambio de empleo.

Valores faltantes (NAs)

na_resumen <- rotacion %>%
  summarise(across(everything(), ~ sum(is.na(.)))) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "NAs") %>%
  mutate(Porcentaje = round(NAs / nrow(rotacion) * 100, 1)) %>%
  filter(NAs > 0)

if (nrow(na_resumen) == 0) {
  cat("✅ No se encontraron valores faltantes en el dataset.")
} else {
  na_resumen %>%
    kable(caption = "Tabla 2. Variables con valores faltantes") %>%
    kable_styling(bootstrap_options = "striped", full_width = FALSE)
}
## ✅ No se encontraron valores faltantes en el dataset.

El análisis de valores faltantes indica que no existen datos ausentes (missing values) en ninguna de las variables del dataset, lo cual representa una ventaja significativa para el proceso de modelación. La ausencia de valores faltantes garantiza la integridad de la información y evita la necesidad de aplicar técnicas de imputación o eliminación de registros, las cuales pueden introducir sesgos o pérdida de información.

Detección de Outliers - Variables Cuantitativas

# Variables cuantitativas del dataset completo
vars_num <- rotacion %>%
  select(where(is.numeric)) %>%
  select(-y) %>%  # excluimos la variable respuesta codificada
  names()

# Boxplots para todas las variables numéricas
rotacion %>%
  select(all_of(vars_num)) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Valor") %>%
  ggplot(aes(x = Variable, y = Valor, fill = Variable)) +
  geom_boxplot(outlier.colour = "red", outlier.shape = 16,
               outlier.size = 1.5, alpha = 0.7) +
  facet_wrap(~ Variable, scales = "free", ncol = 4) +
  labs(title = "Gráfico 1. Boxplots - Detección de Outliers (Variables Numéricas)",
       x = "", y = "Valor") +
  theme_minimal() +
  theme(legend.position = "none",
        axis.text.x = element_blank(),
        strip.text = element_text(size = 8, face = "bold"))

A partir del Gráfico 1, se identifican valores atípicos (outliers) en varias de las variables cuantitativas del dataset, especialmente en variables como Ingreso_Mensual, Antigüedad, Años de experiencia y Años con el mismo jefe. Estos valores extremos se ubican por fuera de los límites definidos por el rango intercuartílico (IQR), lo que indica observaciones con comportamientos significativamente diferentes al resto de la población.

Cuantificación de Outliers por variable (método IQR)

outliers_resumen <- rotacion %>%
  select(all_of(vars_num)) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Valor") %>%
  group_by(Variable) %>%
  summarise(
    Q1       = quantile(Valor, 0.25, na.rm = TRUE),
    Q3       = quantile(Valor, 0.75, na.rm = TRUE),
    IQR      = IQR(Valor, na.rm = TRUE),
    Lim_inf  = Q1 - 1.5 * IQR(Valor, na.rm = TRUE),
    Lim_sup  = Q3 + 1.5 * IQR(Valor, na.rm = TRUE),
    N_outliers = sum(Valor < Q1 - 1.5 * IQR(Valor, na.rm = TRUE) |
                     Valor > Q3 + 1.5 * IQR(Valor, na.rm = TRUE),
                     na.rm = TRUE),
    Pct_outliers = round(N_outliers / n() * 100, 1)
  ) %>%
  arrange(desc(N_outliers))

outliers_resumen %>%
  kable(caption = "Tabla 2. Resumen de Outliers por Variable (Método IQR)",
        digits = 2,
        col.names = c("Variable", "Q1", "Q3", "IQR",
                      "Límite Inferior", "Límite Superior",
                      "N Outliers", "% Outliers")) %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE) %>%
  row_spec(which(outliers_resumen$N_outliers > 0),
           background = "#FFF3E0")
Tabla 2. Resumen de Outliers por Variable (Método IQR)
Variable Q1 Q3 IQR Límite Inferior Límite Superior N Outliers % Outliers
Capacitaciones 2 3 1 0.5 4.5 238 16.2
Rendimiento_Laboral 3 3 0 3.0 3.0 226 15.4
Ingreso_Mensual 2911 8379 5468 -5291.0 16581.0 114 7.8
Años_ultima_promoción 0 3 3 -4.5 7.5 107 7.3
Antigüedad 3 9 6 -6.0 18.0 104 7.1
Años_Experiencia 6 15 9 -7.5 28.5 63 4.3
Trabajos_Anteriores 1 4 3 -3.5 8.5 52 3.5
Antigüedad_Cargo 2 7 5 -5.5 14.5 21 1.4
Años_acargo_con_mismo_jefe 2 7 5 -5.5 14.5 14 1.0
Distancia_Casa 2 14 12 -16.0 32.0 0 0.0
Edad 30 43 13 10.5 62.5 0 0.0
Educación 2 4 2 -1.0 7.0 0 0.0
Equilibrio_Trabajo_Vida 2 3 1 0.5 4.5 0 0.0
Porcentaje_aumento_salarial 12 18 6 3.0 27.0 0 0.0
Satisfacción_Ambiental 2 4 2 -1.0 7.0 0 0.0
Satisfación_Laboral 2 4 2 -1.0 7.0 0 0.0

En la Tabla 2, la cuantificación de outliers mediante el método del rango intercuartílico (IQR) permite identificar con mayor precisión en qué variables se concentra la mayor proporción de valores atípicos. En particular, se observa que variables como Capacitaciones (16.2%) y Rendimiento Laboral (15.4%) presentan los porcentajes más altos de outliers, lo cual puede explicarse por la naturaleza discreta y concentrada de estas variables, donde pequeños cambios generan valores extremos relativos.

Asimismo, variables clave como Ingreso Mensual (7.8%), Antigüedad (7.1%) y Años de experiencia (4.3%) también presentan una proporción relevante de valores atípicos, lo que evidencia la existencia de empleados con condiciones laborales significativamente diferentes al promedio, como altos salarios o trayectorias laborales extensas. Estas observaciones son especialmente importantes desde una perspectiva de negocio, ya que pueden corresponder a perfiles estratégicos dentro de la organización.

Por otro lado, variables como Edad, Distancia a casa, Educación y Satisfacción laboral no presentan outliers, lo que indica una distribución más homogénea y estable en estos aspectos. En conjunto, la Tabla 2 confirma que los valores atípicos están concentrados en variables relacionadas con la experiencia, desempeño y condiciones laborales, reforzando su relevancia en el estudio de la rotación.

Desde una perspectiva analítica, la presencia de outliers en este contexto no necesariamente representa errores en los datos, sino que puede reflejar situaciones reales dentro de la organización, como empleados con salarios muy altos, trayectorias laborales extensas o niveles de experiencia significativamente superiores. Este tipo de observaciones resulta particularmente relevante, ya que pueden aportar información valiosa sobre segmentos específicos de empleados que podrían comportarse de manera distinta frente a la rotación.

Adicionalmente, se observa que la mayoría de las variables presentan distribuciones asimétricas, lo que refuerza la existencia de valores extremos y su impacto en la dispersión de los datos. Sin embargo, dado que el modelo de regresión logística es menos sensible a outliers en comparación con modelos lineales tradicionales, se decide no eliminar estos valores, con el fin de preservar la variabilidad natural del dataset y evitar la pérdida de información relevante para la predicción.

En consecuencia, los outliers se consideran parte integral del análisis y serán tenidos en cuenta en la estimación del modelo, ya que pueden contribuir a una mejor comprensión de los factores asociados a la rotación en casos extremos.

Resumen estadístico general

summary(rotacion) 
##    Rotación              Edad       Viaje de Negocios  Departamento      
##  Length:1470        Min.   :18.00   Length:1470        Length:1470       
##  Class :character   1st Qu.:30.00   Class :character   Class :character  
##  Mode  :character   Median :36.00   Mode  :character   Mode  :character  
##                     Mean   :36.92                                        
##                     3rd Qu.:43.00                                        
##                     Max.   :60.00                                        
##  Distancia_Casa     Educación     Campo_Educación    Satisfacción_Ambiental
##  Min.   : 1.000   Min.   :1.000   Length:1470        Min.   :1.000         
##  1st Qu.: 2.000   1st Qu.:2.000   Class :character   1st Qu.:2.000         
##  Median : 7.000   Median :3.000   Mode  :character   Median :3.000         
##  Mean   : 9.193   Mean   :2.913                      Mean   :2.722         
##  3rd Qu.:14.000   3rd Qu.:4.000                      3rd Qu.:4.000         
##  Max.   :29.000   Max.   :5.000                      Max.   :4.000         
##     Genero             Cargo           Satisfación_Laboral Estado_Civil      
##  Length:1470        Length:1470        Min.   :1.000       Length:1470       
##  Class :character   Class :character   1st Qu.:2.000       Class :character  
##  Mode  :character   Mode  :character   Median :3.000       Mode  :character  
##                                        Mean   :2.729                         
##                                        3rd Qu.:4.000                         
##                                        Max.   :4.000                         
##  Ingreso_Mensual Trabajos_Anteriores Horas_Extra       
##  Min.   : 1009   Min.   :0.000       Length:1470       
##  1st Qu.: 2911   1st Qu.:1.000       Class :character  
##  Median : 4919   Median :2.000       Mode  :character  
##  Mean   : 6503   Mean   :2.693                         
##  3rd Qu.: 8379   3rd Qu.:4.000                         
##  Max.   :19999   Max.   :9.000                         
##  Porcentaje_aumento_salarial Rendimiento_Laboral Años_Experiencia
##  Min.   :11.00               Min.   :3.000       Min.   : 0.00   
##  1st Qu.:12.00               1st Qu.:3.000       1st Qu.: 6.00   
##  Median :14.00               Median :3.000       Median :10.00   
##  Mean   :15.21               Mean   :3.154       Mean   :11.28   
##  3rd Qu.:18.00               3rd Qu.:3.000       3rd Qu.:15.00   
##  Max.   :25.00               Max.   :4.000       Max.   :40.00   
##  Capacitaciones  Equilibrio_Trabajo_Vida   Antigüedad     Antigüedad_Cargo
##  Min.   :0.000   Min.   :1.000           Min.   : 0.000   Min.   : 0.000  
##  1st Qu.:2.000   1st Qu.:2.000           1st Qu.: 3.000   1st Qu.: 2.000  
##  Median :3.000   Median :3.000           Median : 5.000   Median : 3.000  
##  Mean   :2.799   Mean   :2.761           Mean   : 7.008   Mean   : 4.229  
##  3rd Qu.:3.000   3rd Qu.:3.000           3rd Qu.: 9.000   3rd Qu.: 7.000  
##  Max.   :6.000   Max.   :4.000           Max.   :40.000   Max.   :18.000  
##  Años_ultima_promoción Años_acargo_con_mismo_jefe       y         
##  Min.   : 0.000        Min.   : 0.000             Min.   :0.0000  
##  1st Qu.: 0.000        1st Qu.: 2.000             1st Qu.:0.0000  
##  Median : 1.000        Median : 3.000             Median :0.0000  
##  Mean   : 2.188        Mean   : 4.123             Mean   :0.1612  
##  3rd Qu.: 3.000        3rd Qu.: 7.000             3rd Qu.:0.0000  
##  Max.   :15.000        Max.   :17.000             Max.   :1.0000

En términos de edad, los empleados tienen en promedio 36.9 años, con una distribución concentrada entre los 30 y 43 años, lo que sugiere una fuerza laboral predominantemente en etapa productiva media. Por su parte, el ingreso mensual presenta una alta dispersión (media de 6,503 frente a una mediana de 4,919), evidenciando una distribución sesgada a la derecha, donde un grupo reducido de empleados percibe salarios significativamente más altos que el resto.

En cuanto a variables relacionadas con la experiencia laboral, se observa que la antigüedad promedio es de 7 años, mientras que la experiencia total alcanza en promedio los 11 años, lo que indica que muchos empleados han tenido trayectorias laborales previas antes de vincularse a la organización. Asimismo, la variable trabajos anteriores muestra una mediana de 2, lo cual refuerza la idea de movilidad laboral en la muestra analizada.

Respecto a variables de percepción, como la satisfacción laboral y la satisfacción ambiental, ambas presentan valores medios cercanos a 3 en una escala de 1 a 4, lo que indica niveles moderados de satisfacción entre los empleados. Sin embargo, la presencia de valores mínimos en estas escalas sugiere que existe un grupo de empleados con baja satisfacción, potencialmente más propenso a la rotación.

Finalmente, la variable respuesta codificada (y) presenta una media de 0.1612, lo que indica que aproximadamente el 16.1% de los empleados rota, confirmando la existencia de un desbalance en la variable objetivo. Este aspecto es relevante para la evaluación del modelo, ya que puede influir en métricas como la exactitud y la sensibilidad.

En conjunto, el análisis descriptivo evidencia heterogeneidad en variables clave como ingreso, experiencia y satisfacción, lo cual es favorable para la estimación del modelo, ya que permite capturar relaciones significativas con la probabilidad de rotación.

1. Selección de Variables e Hipótesis

La selección de variables se realizó con base en su relevancia teórica y su potencial influencia sobre la rotación laboral, considerando tanto factores organizacionales como características individuales de los empleados. Se incluyeron tres variables categóricas y tres cuantitativas, con el fin de capturar diferentes dimensiones del fenómeno y permitir un análisis integral dentro del modelo logístico.

Variables categóricas seleccionadas

Variable Tipo Hipótesis
Horas_Extra Categórica (Si/No) Los empleados que trabajan horas extra tienen mayor desgaste físico y emocional, lo que incrementa la probabilidad de rotar. Se espera una relación positiva: trabajar horas extra → mayor rotación.
Estado_Civil Categórica (Soltero/Casado/Divorciado) Los empleados solteros tienen menores compromisos familiares y mayor movilidad laboral. Se espera que los solteros tengan mayor probabilidad de rotar que los casados.
Viaje_de_Negocios Categórica (No/Raramente/Frecuentemente) Los viajes frecuentes generan fatiga, afectan la vida personal y aumentan el estrés. Se espera que quienes viajan frecuentemente tengan mayor probabilidad de rotación.

En el caso de las variables categóricas, se priorizaron aquellas relacionadas con las condiciones laborales y el contexto personal del empleado. Variables como Horas Extra y Viaje de Negocios permiten evaluar el impacto de la carga laboral y el desgaste asociado al trabajo, mientras que Estado Civil introduce un componente sociodemográfico que puede influir en la estabilidad laboral y las decisiones de permanencia. Estas variables permiten identificar diferencias estructurales entre grupos de empleados en términos de probabilidad de rotación.

Variables cuantitativas seleccionadas

Variable Tipo Hipótesis
Ingreso_Mensual Cuantitativa continua A mayor ingreso mensual, el empleado tiene menos incentivos para cambiar de cargo. Se espera una relación negativa: mayor ingreso → menor rotación.
Antigüedad Cuantitativa continua A mayor antigüedad en la empresa, el empleado tiene mayor arraigo y beneficios acumulados. Se espera una relación negativa: mayor antigüedad → menor rotación.
Satisfación_Laboral Cuantitativa discreta (escala 1-4) Los empleados con baja satisfacción laboral buscan activamente mejores oportunidades. Se espera una relación negativa: mayor satisfacción → menor rotación.

Por su parte, las variables cuantitativas seleccionadas (Ingreso Mensual, Antigüedad y Satisfacción Laboral) permiten analizar efectos graduales sobre la probabilidad de rotación. Estas variables son particularmente relevantes, ya que capturan aspectos económicos, de experiencia y percepción del entorno laboral, los cuales han sido ampliamente identificados en la literatura como determinantes clave de la permanencia en una organización.

Las hipótesis planteadas establecen relaciones esperadas entre cada variable y la rotación, tanto en dirección como en sentido (positivo o negativo), lo que permite posteriormente contrastarlas mediante el análisis bivariado y la estimación del modelo logístico. En conjunto, la selección realizada proporciona una base sólida para evaluar los principales factores asociados a la rotación de empleados.

2. Análisis Univariado

Variable respuesta: Rotación

tabla_rotacion <- rotacion %>%
  count(Rotación) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 1))

tabla_rotacion %>%
  kable(col.names = c("Rotación", "Frecuencia", "Porcentaje (%)"),
        caption = "Tabla 3. Distribución de la variable Rotación") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 3. Distribución de la variable Rotación
Rotación Frecuencia Porcentaje (%)
No 1233 83.9
Si 237 16.1
ggplot(rotacion, aes(x = Rotación, fill = Rotación)) +
  geom_bar(color = "white") +
  scale_fill_manual(values = c("#2196F3", "#FF7043")) +
  geom_text(stat = "count", aes(label = paste0(..count.., "\n(",
            round(..count.. / nrow(rotacion) * 100, 1), "%)")),
            vjust = -0.3, size = 4) +
  labs(title = "Gráfico 2. Distribución de Rotación de Empleados",
       x = "Rotación", y = "Frecuencia") +
  theme_minimal() +
  theme(legend.position = "none")


En la Tabla 3 y el Gráfico 2 se puede observar que la variable respuesta muestra que el 83.9% de los empleados no presenta rotación, mientras que el 16.1% sí rota, evidenciando un desbalance significativo en la variable objetivo. Este comportamiento es común en problemas de clasificación en contextos organizacionales, donde la mayoría de los empleados tiende a permanecer en la empresa, mientras que una proporción menor decide retirarse.

Desde una perspectiva analítica, este desbalance implica que el modelo podría verse influenciado hacia la clase mayoritaria (empleados que no rotan), lo que podría generar una alta exactitud aparente pero una baja capacidad para identificar correctamente los casos de rotación. Por esta razón, resulta fundamental complementar la evaluación del modelo con métricas como la sensibilidad (recall) y el AUC, en lugar de depender únicamente de la exactitud.

Adicionalmente, desde el punto de vista del negocio, la clase minoritaria (empleados que rotan) es la más relevante, ya que representa un costo significativo para la organización en términos de reemplazo, capacitación y pérdida de conocimiento. En este sentido, el análisis sugiere que el modelo debe priorizar la correcta identificación de estos casos, incluso si esto implica aceptar un mayor número de falsos positivos.

Este desbalance justifica la posterior implementación de un análisis de sensibilidad del punto de corte, con el fin de optimizar la capacidad del modelo para detectar empleados en riesgo de rotación.

Variables categóricas

# Función para graficar variables categóricas
plot_cat <- function(var, titulo) {
  rotacion %>%
    count(!!sym(var)) %>%
    mutate(Porcentaje = round(n / sum(n) * 100, 1)) %>%
    ggplot(aes(x = reorder(!!sym(var), -n), y = n, fill = !!sym(var))) +
    geom_bar(stat = "identity", color = "white") +
    geom_text(aes(label = paste0(n, "\n(", Porcentaje, "%)")), vjust = -0.3, size = 3.5) +
    labs(title = titulo, x = var, y = "Frecuencia") +
    theme_minimal() +
    theme(legend.position = "none",
          axis.text.x = element_text(angle = 15, hjust = 1))
}

p1 <- plot_cat("Horas_Extra", "Horas Extra")
p2 <- plot_cat("Estado_Civil", "Estado Civil")
p3 <- plot_cat("Viaje de Negocios", "Viaje de Negocios")

grid.arrange(p1, p2, p3, ncol = 3,
             top = "Gráfico 3. Distribución de Variables Categóricas Seleccionadas")

En el Gráfico 3 se puede observar la distribución de las principales variables categóricas seleccionadas. En el caso de Horas Extra, se evidencia que la mayoría de los empleados (71.7%) no trabaja horas adicionales, mientras que un 28.3% sí lo hace. Esto indica que, aunque no es la condición predominante, existe un grupo considerable de empleados sometidos a una mayor carga laboral, lo cual podría influir en su decisión de rotar.

Por otra parte, en la variable Estado Civil se observa que el grupo más representativo corresponde a los empleados casados (45.8%), seguido por solteros (32%) y divorciados (22.2%). De lo anterior se puede inferir que una proporción importante de empleados cuenta con mayor estabilidad personal, lo que podría estar asociado con una menor propensión a la rotación, en contraste con los empleados solteros.

En cuanto a Viaje de Negocios, se aprecia que el 71% de los empleados viaja raramente, mientras que un 18.8% lo hace frecuentemente y un 10.2% no realiza viajes.

Esto muestra que, aunque la mayoría no está expuesta constantemente a viajes laborales, existe un grupo relevante que sí lo está, lo cual puede generar desgaste y afectar su permanencia en la organización. Del Gráfico 3 se concluye que las variables categóricas presentan una distribución variada entre los empleados, lo que permitirá posteriormente comparar grupos y evaluar su influencia sobre la rotación en el análisis bivariado y el modelo logístico.


Variables cuantitativas

# Estadísticos descriptivos
rotacion %>%
  select(Ingreso_Mensual, Antigüedad, `Satisfación_Laboral`) %>%
  summary() %>%
  kable(caption = "Tabla 4. Estadísticos descriptivos - Variables cuantitativas") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 4. Estadísticos descriptivos - Variables cuantitativas
Ingreso_Mensual Antigüedad Satisfación_Laboral
Min. : 1009 Min. : 0.000 Min. :1.000
1st Qu.: 2911 1st Qu.: 3.000 1st Qu.:2.000
Median : 4919 Median : 5.000 Median :3.000
Mean : 6503 Mean : 7.008 Mean :2.729
3rd Qu.: 8379 3rd Qu.: 9.000 3rd Qu.:4.000
Max. :19999 Max. :40.000 Max. :4.000
# Histogramas
p4 <- ggplot(rotacion, aes(x = Ingreso_Mensual)) +
  geom_histogram(fill = "#42A5F5", color = "white", bins = 30) +
  labs(title = "Ingreso Mensual", x = "Ingreso Mensual", y = "Frecuencia") +
  theme_minimal()

p5 <- ggplot(rotacion, aes(x = Antigüedad)) +
  geom_histogram(fill = "#66BB6A", color = "white", bins = 20) +
  labs(title = "Antigüedad", x = "Años en la empresa", y = "Frecuencia") +
  theme_minimal()

p6 <- ggplot(rotacion, aes(x = `Satisfación_Laboral`)) +
  geom_bar(fill = "#FFA726", color = "white") +
  labs(title = "Satisfacción Laboral", x = "Nivel (1=Bajo, 4=Alto)", y = "Frecuencia") +
  theme_minimal()

grid.arrange(p4, p5, p6, ncol = 3,
             top = "Gráfico 4. Distribución de Variables Cuantitativas Seleccionadas")

En la Tabla 4 se presentan los estadísticos descriptivos, y en el Gráfico 4 se puede observar la distribución de las variables cuantitativas seleccionadas. En el caso del Ingreso Mensual, se aprecia una distribución claramente sesgada hacia la derecha, donde la mayoría de los empleados se concentra en rangos salariales entre aproximadamente $2,000 y $5,000, mientras que un grupo reducido presenta ingresos considerablemente más altos. Esto indica una desigualdad en la distribución salarial, lo cual puede influir en la rotación, ya que empleados con menores ingresos podrían tener mayores incentivos para cambiar de empleo.

En cuanto a la Antigüedad, se observa que la mayor parte de los empleados tiene pocos años dentro de la empresa, con una distribución también asimétrica positiva. De lo anterior se puede inferir que existe una alta concentración de empleados en etapas tempranas de su permanencia laboral, lo que podría estar asociado con una mayor probabilidad de rotación en estos grupos, debido a menor estabilidad o menor arraigo organizacional.

Por otro lado, la variable Satisfacción Laboral muestra una distribución discreta en una escala de 1 a 4, con predominio de los niveles medios y altos. Sin embargo, también se identifican empleados con niveles bajos de satisfacción, lo cual resulta relevante, ya que estos casos podrían estar directamente relacionados con una mayor probabilidad de rotación.

Bajo este contexto, del Gráfico 4 se concluye que las variables cuantitativas presentan variabilidad y patrones diferenciados entre los empleados, lo cual es fundamental para el análisis posterior, ya que permite identificar relaciones potenciales con la rotación en el análisis bivariado y en el modelo logístico.


3. Análisis Bivariado

Se analiza la relación entre cada variable seleccionada y la rotación (y=1 rota, y=0 no rota).

Variables categóricas vs Rotación

plot_biv_cat <- function(var, titulo) {
  rotacion %>%
    group_by(!!sym(var), Rotación) %>%
    summarise(n = n(), .groups = "drop") %>%
    group_by(!!sym(var)) %>%
    mutate(pct = round(n / sum(n) * 100, 1)) %>%
    ggplot(aes(x = !!sym(var), y = pct, fill = Rotación)) +
    geom_bar(stat = "identity", position = "fill", color = "white") +
    scale_fill_manual(values = c("#2196F3", "#FF7043")) +
    scale_y_continuous(labels = scales::percent) +
    labs(title = titulo, x = var, y = "Proporción") +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 15, hjust = 1))
}

p7 <- plot_biv_cat("Horas_Extra", "Rotación por Horas Extra")
p8 <- plot_biv_cat("Estado_Civil", "Rotación por Estado Civil")
p9 <- plot_biv_cat("Viaje de Negocios", "Rotación por Viaje de Negocios")

grid.arrange(p7, p8, p9, ncol = 2,
             top = "Gráfico 5. Rotación según Variables Categóricas")

En el Gráfico 5 se puede observar la relación entre las variables categóricas seleccionadas y la rotación de empleados. En el caso de Horas Extra, se observa una diferencia clara entre los grupos: los empleados que trabajan horas extra presentan una mayor proporción de rotación en comparación con aquellos que no lo hacen. Esto sugiere que una mayor carga laboral podría estar asociada con un incremento en la probabilidad de rotación, lo cual es consistente con la hipótesis planteada.

En cuanto al Estado Civil, se aprecia que los empleados solteros presentan una mayor proporción de rotación frente a los casados y divorciados. De lo anterior se puede inferir que los empleados con menor nivel de compromiso familiar tienden a tener mayor movilidad laboral, lo cual coincide con la hipótesis inicial.

Por otro lado, en la variable Viaje de Negocios, se observa que los empleados que viajan frecuentemente presentan una mayor proporción de rotación, mientras que aquellos que viajan raramente o no viajan tienen menores niveles de rotación. Esto sugiere que la exposición constante a viajes laborales podría generar desgaste o insatisfacción, afectando la permanencia en la organización.

Del Gráfico 5 se concluye que existe una relación visible entre las variables categóricas analizadas y la rotación, lo cual indica que estas variables tienen potencial explicativo dentro del modelo logístico. Estos resultados preliminares serán posteriormente validados mediante pruebas estadísticas de independencia.

Pruebas Chi-cuadrado (independencia)

chi_horas <- chisq.test(table(rotacion$Horas_Extra, rotacion$Rotación))
chi_civil <- chisq.test(table(rotacion$Estado_Civil, rotacion$Rotación))
chi_viaje <- chisq.test(table(rotacion$`Viaje de Negocios`, rotacion$Rotación))

data.frame(
  Variable = c("Horas Extra", "Estado Civil", "Viaje de Negocios"),
  Chi_cuadrado = round(c(chi_horas$statistic, chi_civil$statistic, chi_viaje$statistic), 3),
  p_valor = round(c(chi_horas$p.value, chi_civil$p.value, chi_viaje$p.value), 4),
  Significativa = ifelse(c(chi_horas$p.value, chi_civil$p.value, chi_viaje$p.value) < 0.05, "Sí ✓", "No ✗")
) %>%
  kable(caption = "Tabla 5. Pruebas Chi-cuadrado: Variables categóricas vs Rotación") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 5. Pruebas Chi-cuadrado: Variables categóricas vs Rotación
Variable Chi_cuadrado p_valor Significativa
Horas Extra 87.564 0 Sí ✓
Estado Civil 46.164 0 Sí ✓
Viaje de Negocios 24.182 0 Sí ✓

En la Tabla 5 se presentan los resultados de las pruebas de chi-cuadrado de independencia, las cuales permiten evaluar si existe una relación estadísticamente significativa entre las variables categóricas y la rotación. En todos los casos analizados (Horas Extra, Estado Civil y Viaje de Negocios), se obtienen p-valores cercanos a 0, lo que indica que se rechaza la hipótesis nula de independencia.

En el caso de Horas Extra, el estadístico chi-cuadrado presenta el valor más alto (87.564), lo que sugiere que esta variable tiene una fuerte asociación con la rotación. Esto refuerza la idea de que la carga laboral es un factor determinante en la decisión de permanencia de los empleados.

Para la variable Estado Civil, también se observa una relación significativa (χ² = 46.164), lo que confirma que existen diferencias en la rotación según la situación personal del empleado. De manera similar, Viaje de Negocios presenta un resultado significativo (χ² = 24.182), evidenciando que la frecuencia de viajes laborales está asociada con la rotación.

De la Tabla 5 se concluye que las variables categóricas analizadas no son independientes de la rotación, validando así las hipótesis planteadas previamente y justificando su inclusión en el modelo de regresión logística como variables explicativas relevantes.


Variables cuantitativas vs Rotación

plot_biv_num <- function(var, titulo) {
  ggplot(rotacion, aes(x = Rotación, y = !!sym(var), fill = Rotación)) +
    geom_boxplot(alpha = 0.7, color = "gray40") +
    scale_fill_manual(values = c("#2196F3", "#FF7043")) +
    labs(title = titulo, x = "Rotación", y = var) +
    theme_minimal() +
    theme(legend.position = "none")
}

p10 <- plot_biv_num("Ingreso_Mensual", "Ingreso Mensual vs Rotación")
p11 <- plot_biv_num("Antigüedad", "Antigüedad vs Rotación")
p12 <- plot_biv_num("Satisfación_Laboral", "Satisfacción Laboral vs Rotación")

grid.arrange(p10, p11, p12, ncol = 3,
             top = "Gráfico 6. Variables Cuantitativas según Rotación")

En el Gráfico 6 se puede observar la distribución de las variables cuantitativas según la rotación de los empleados. En el caso del Ingreso Mensual, se observa que los empleados que no rotan presentan, en promedio, ingresos más altos, mientras que aquellos que sí rotan se concentran en niveles salariales más bajos. De esto se puede inferir que el ingreso actúa como un factor de retención, donde menores salarios están asociados con una mayor probabilidad de rotación.

En cuanto a la Antigüedad, se evidencia que los empleados que no rotan tienden a tener mayor tiempo en la empresa, mientras que aquellos que rotan presentan niveles más bajos de antigüedad. Esto sugiere que los empleados con menor permanencia son más propensos a abandonar la organización, posiblemente debido a un menor nivel de arraigo laboral.

Por otro lado, en la variable Satisfacción Laboral, se aprecia que los empleados que no rotan presentan niveles más altos de satisfacción, mientras que aquellos que rotan se concentran en niveles más bajos. Esto refuerza la idea de que la percepción del entorno laboral es un factor clave en la decisión de permanencia.

Finalmente, del Gráfico 6 se concluye que existen diferencias claras entre los grupos analizados, lo que indica que las variables cuantitativas tienen un alto potencial explicativo y podrían influir significativamente en la probabilidad de rotación dentro del modelo logístico.

Pruebas t de Student (diferencia de medias)

t_ingreso  <- t.test(Ingreso_Mensual ~ Rotación, data = rotacion)
t_antig    <- t.test(Antigüedad ~ Rotación, data = rotacion)
t_sat      <- t.test(`Satisfación_Laboral` ~ Rotación, data = rotacion)

data.frame(
  Variable    = c("Ingreso Mensual", "Antigüedad", "Satisfacción Laboral"),
  Media_No    = round(c(t_ingreso$estimate[1], t_antig$estimate[1], t_sat$estimate[1]), 2),
  Media_Si    = round(c(t_ingreso$estimate[2], t_antig$estimate[2], t_sat$estimate[2]), 2),
  p_valor     = round(c(t_ingreso$p.value, t_antig$p.value, t_sat$p.value), 4),
  Significativa = ifelse(c(t_ingreso$p.value, t_antig$p.value, t_sat$p.value) < 0.05, "Sí ✓", "No ✗")
) %>%
  kable(caption = "Tabla 6. Prueba t: Variables cuantitativas vs Rotación",
        col.names = c("Variable", "Media (No rota)", "Media (Sí rota)", "p-valor", "Significativa")) %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 6. Prueba t: Variables cuantitativas vs Rotación
Variable Media (No rota) Media (Sí rota) p-valor Significativa
Ingreso Mensual 6832.74 4787.09 0e+00 Sí ✓
Antigüedad 7.37 5.13 0e+00 Sí ✓
Satisfacción Laboral 2.78 2.47 1e-04 Sí ✓

En la Tabla 6 se presentan los resultados de la prueba t de Student, la cual permite evaluar si existen diferencias significativas en las medias de las variables cuantitativas entre los empleados que rotan y los que no. En todos los casos analizados (Ingreso Mensual, Antigüedad y Satisfacción Laboral), se obtienen p-valores inferiores a 0.05, lo que indica que las diferencias observadas son estadísticamente significativas.

En el caso del Ingreso Mensual, se observa que los empleados que no rotan tienen un ingreso promedio considerablemente mayor (6832.74) en comparación con aquellos que sí rotan (4787.09). Esto sugiere que el nivel salarial es un factor determinante en la retención del talento.

Para la Antigüedad, se evidencia que los empleados que permanecen en la organización tienen, en promedio, más años en la empresa (7.37) frente a los que rotan (5.13). Esto refuerza la idea de que el arraigo laboral reduce la probabilidad de rotación.

En cuanto a la Satisfacción Laboral, también se presentan diferencias significativas, donde los empleados que no rotan muestran mayores niveles de satisfacción (2.78) en comparación con aquellos que sí rotan (2.47). Esto indica que la percepción del entorno laboral influye directamente en la decisión de permanencia.

Bajo este enfoque, de la Tabla 6 se concluye que estos resultados confirman estadísticamente lo observado en el Gráfico 6, validando que las variables cuantitativas analizadas están significativamente asociadas con la rotación y son relevantes para su inclusión en el modelo logístico.


4. Estimación del Modelo Logit

# Preparar variables
rotacion$Horas_Extra_bin   <- ifelse(rotacion$Horas_Extra == "Si", 1, 0)
rotacion$Viaje_Frecuente   <- factor(rotacion$`Viaje de Negocios`)
rotacion$Estado_Civil_f    <- factor(rotacion$Estado_Civil)

# Dividir en train (70%) y test (30%)
set.seed(123)
n <- nrow(rotacion)
idx_train <- sample(1:n, size = floor(0.7 * n))
train <- rotacion[idx_train, ]
test  <- rotacion[-idx_train, ]

# Estimar modelo
modelo_logit <- glm(
  y ~ Horas_Extra_bin + Estado_Civil_f + Viaje_Frecuente +
      Ingreso_Mensual + Antigüedad + `Satisfación_Laboral`,
  family = binomial(link = "logit"),
  data = train
)

summary(modelo_logit)
## 
## Call:
## glm(formula = y ~ Horas_Extra_bin + Estado_Civil_f + Viaje_Frecuente + 
##     Ingreso_Mensual + Antigüedad + Satisfación_Laboral, family = binomial(link = "logit"), 
##     data = train)
## 
## Coefficients:
##                            Estimate Std. Error z value Pr(>|z|)    
## (Intercept)               9.667e-03  3.590e-01   0.027 0.978519    
## Horas_Extra_bin           1.404e+00  1.933e-01   7.260 3.86e-13 ***
## Estado_Civil_fDivorciado -4.766e-01  2.895e-01  -1.646 0.099773 .  
## Estado_Civil_fSoltero     9.593e-01  2.055e-01   4.669 3.03e-06 ***
## Viaje_FrecuenteNo_Viaja  -1.240e+00  4.191e-01  -2.959 0.003089 ** 
## Viaje_FrecuenteRaramente -7.413e-01  2.160e-01  -3.432 0.000599 ***
## Ingreso_Mensual          -1.363e-04  3.222e-05  -4.229 2.35e-05 ***
## Antigüedad               -3.703e-02  2.184e-02  -1.696 0.089950 .  
## Satisfación_Laboral      -3.375e-01  8.378e-02  -4.028 5.62e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 896.03  on 1028  degrees of freedom
## Residual deviance: 733.51  on 1020  degrees of freedom
## AIC: 751.51
## 
## Number of Fisher Scoring iterations: 6

La tabla de resultados anterior presenta la estimación del modelo de regresión logística, donde los coeficientes indican el efecto de cada variable sobre el logaritmo de las probabilidades (log-odds) de rotación. En general, se observa que varias variables resultan estadísticamente significativas, lo que confirma su relevancia en la explicación del fenómeno.

En el caso de Horas Extra, el coeficiente es positivo y altamente significativo (β = 1.404, p < 0.001), lo que indica que trabajar horas adicionales incrementa la probabilidad de rotación. Esto implica que los empleados que realizan horas extra tienen mayores probabilidades de abandonar la organización en comparación con aquellos que no lo hacen.

Para la variable Estado Civil, se observa que ser soltero tiene un efecto positivo y significativo (β = 0.959, p < 0.001), lo que sugiere una mayor probabilidad de rotación frente a la categoría base (casados). Por otro lado, la categoría divorciado no resulta significativa al 5%, aunque muestra una tendencia negativa, lo que indica que su efecto no es concluyente dentro del modelo.

En cuanto a Viaje de Negocios, las categorías No viaja y Raramente presentan coeficientes negativos y significativos, lo que indica una menor probabilidad de rotación en comparación con la categoría de referencia (viaja frecuentemente). Esto refuerza la idea de que los viajes frecuentes están asociados con un mayor riesgo de rotación.

Respecto a las variables cuantitativas, el Ingreso Mensual presenta un coeficiente negativo y significativo (β = -0.000136, p < 0.001), lo que indica que a medida que aumenta el salario, disminuye la probabilidad de rotación. De manera similar, la Satisfacción Laboral muestra un efecto negativo y significativo (β = -0.3375, p < 0.001), evidenciando que mayores niveles de satisfacción reducen la probabilidad de que el empleado abandone la empresa.

Por su parte, la Antigüedad presenta un coeficiente negativo pero con significancia marginal (p ≈ 0.09), lo que sugiere que, aunque existe una tendencia a que mayor antigüedad reduzca la rotación, este efecto no es completamente concluyente al nivel tradicional del 5%.

En este sentido, los resultados del modelo confirman que factores como la carga laboral, el nivel salarial, la satisfacción y ciertas condiciones personales influyen significativamente en la probabilidad de rotación, siendo coherentes con los hallazgos del análisis exploratorio y bivariado.

Tabla de coeficientes e interpretación

coef_df <- data.frame(
  Variable    = names(coef(modelo_logit)),
  Estimado    = round(coef(modelo_logit), 5),
  Odds_Ratio  = round(exp(coef(modelo_logit)), 4),
  p_valor     = round(summary(modelo_logit)$coefficients[, 4], 4),
  Significativa = ifelse(summary(modelo_logit)$coefficients[, 4] < 0.05, "Sí ✓", "No ✗")
)

coef_df %>%
  kable(caption = "Tabla 7. Coeficientes del Modelo Logit y Odds Ratio",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 7. Coeficientes del Modelo Logit y Odds Ratio
Variable Estimado Odds_Ratio p_valor Significativa
(Intercept) 0.00967 1.0097 0.9785 No ✗
Horas_Extra_bin 1.40367 4.0701 0.0000 Sí ✓
Estado_Civil_fDivorciado -0.47655 0.6209 0.0998 No ✗
Estado_Civil_fSoltero 0.95928 2.6098 0.0000 Sí ✓
Viaje_FrecuenteNo_Viaja -1.23993 0.2894 0.0031 Sí ✓
Viaje_FrecuenteRaramente -0.74132 0.4765 0.0006 Sí ✓
Ingreso_Mensual -0.00014 0.9999 0.0000 Sí ✓
Antigüedad -0.03703 0.9636 0.0899 No ✗
Satisfación_Laboral -0.33749 0.7136 0.0001 Sí ✓

En la Tabla 7 se pueden interpretar los efectos de cada variable a través de los odds ratio, los cuales indican cómo cambia la probabilidad de rotación ante variaciones en cada variable, manteniendo las demás constantes. En este caso, se identifican varias variables con efectos significativos sobre la rotación.

En particular, la variable Horas Extra presenta un odds ratio de 4.07, lo que indica que los empleados que trabajan horas extra tienen aproximadamente 4 veces más probabilidad de rotar en comparación con aquellos que no lo hacen. Este resultado evidencia un fuerte impacto de la carga laboral sobre la permanencia en la organización.

Para el Estado Civil, se observa que los empleados solteros tienen un odds ratio de 2.61, lo que implica que son más del doble de propensos a rotar frente a los casados (categoría de referencia). En contraste, la categoría divorciado no resulta estadísticamente significativa, por lo que su efecto no es concluyente dentro del modelo.

En cuanto a Viaje de Negocios, los empleados que no viajan (OR = 0.29) o que viajan raramente (OR = 0.48) presentan una menor probabilidad de rotación en comparación con aquellos que viajan frecuentemente. Esto indica que la frecuencia de viajes laborales incrementa el riesgo de rotación.

Respecto a las variables cuantitativas, el Ingreso Mensual presenta un odds ratio ligeramente menor a 1 (0.9999), lo que indica que incrementos en el salario reducen la probabilidad de rotación, aunque el efecto marginal es pequeño por unidad. De forma similar, la Satisfacción Laboral (OR = 0.71) muestra que mayores niveles de satisfacción disminuyen significativamente la probabilidad de rotación.

Por su parte, la Antigüedad presenta un efecto negativo (OR = 0.96), lo que sugiere una reducción en la probabilidad de rotación a medida que aumenta el tiempo en la empresa; sin embargo, este efecto no resulta estadísticamente significativo al nivel del 5%.

En consecuencia, de la Tabla 7 se concluye que factores como la carga laboral, la satisfacción, el salario y ciertas condiciones personales influyen de manera importante en la rotación, destacándose especialmente el impacto de las horas extra y el estado civil como variables con mayor efecto dentro del modelo.


5. Evaluación del Modelo

Matriz de confusión (punto de corte = 0.5)

valor_pred  <- predict(modelo_logit, newdata = test, type = "response")
clase_pred  <- ifelse(valor_pred > 0.5, "Si", "No")
clase_pred  <- factor(clase_pred, levels = c("No", "Si"))
test$Rotacion_f <- factor(test$Rotación, levels = c("No", "Si"))

mc <- confusionMatrix(clase_pred, test$Rotacion_f, positive = "Si")

# Extraer valores
VP <- mc$table["Si", "Si"]
FP <- mc$table["Si", "No"]
FN <- mc$table["No", "Si"]
VN <- mc$table["No", "No"]

# Celdas HTML
celda <- function(titulo, subtitulo, n, color) {
  paste0(
    "<div style='background-color:", color, ";color:white;padding:25px 15px;",
    "border-radius:8px;text-align:center;line-height:1.6'>",
    "<b style='font-size:1.1em'>", titulo, "</b><br>",
    "<span style='font-size:0.85em'>", subtitulo, "</span><br><br>",
    "<span style='font-size:2.5em;font-weight:bold'>", n, "</span>",
    "</div>"
  )
}

VP_html <- celda("Verdaderos Positivos (VP)", "ACIERTO tipo 1", VP, "#4CAF50")
FP_html <- celda("Falsos Positivos (FP)",     "ERROR tipo 1",   FP, "#F44336")
FN_html <- celda("Falsos Negativos (FN)",     "ERROR tipo 2",   FN, "#F44336")
VN_html <- celda("Verdaderos Negativos (VN)", "ACIERTO tipo 2", VN, "#4CAF50")

# Construir tabla como data.frame HTML
matriz_df <- data.frame(
  Real_Si = c(VP_html, FN_html),
  Real_No = c(FP_html, VN_html),
  check.names = FALSE
)
rownames(matriz_df) <- c("Predicción: Sí", "Predicción: No")

kable(matriz_df,
      format    = "html",
      escape    = FALSE,
      col.names = c("Real: Sí", "Real: No"),
      caption   = "Tabla 8a. Matriz de Confusión del Modelo Logístico") %>%
  kable_styling(bootstrap_options = "bordered",
                full_width = FALSE, position = "center") %>%
  add_header_above(c(" " = 1, "Valor Real" = 2),
                   bold = TRUE, background = "#37474F", color = "white") %>%
  column_spec(1, bold = TRUE, background = "#ECEFF1", width = "9em") %>%
  row_spec(0, bold = TRUE, background = "#37474F", color = "white")
Tabla 8a. Matriz de Confusión del Modelo Logístico
Valor Real
Real: Sí Real: No
Predicción: Sí

Verdaderos Positivos (VP)
ACIERTO tipo 1

15

Falsos Positivos (FP)
ERROR tipo 1

8

Predicción: No

Falsos Negativos (FN)
ERROR tipo 2

60

Verdaderos Negativos (VN)
ACIERTO tipo 2

358

# --- Tabla de métricas ---
data.frame(
  Indicador = c("Exactitud (Accuracy)", "Tasa de Error",
                "Sensibilidad (Recall)", "Especificidad",
                "Precisión", "Valor Pred. Negativo"),
  Valor = round(c(mc$overall["Accuracy"],
                  1 - mc$overall["Accuracy"],
                  mc$byClass["Sensitivity"],
                  mc$byClass["Specificity"],
                  mc$byClass["Pos Pred Value"],
                  mc$byClass["Neg Pred Value"]), 3),
  Interpretación = c(
    "Proporción total de clasificaciones correctas",
    "Proporción total de clasificaciones incorrectas",
    "Capacidad de detectar empleados que SÍ rotan",
    "Capacidad de detectar empleados que NO rotan",
    "Confiabilidad cuando predice rotación",
    "Confiabilidad cuando predice no rotación"
  ),
  Preferencia = c("Alto ↑", "Bajo ↓", "Alto ↑", "Alto ↑", "Alto ↑", "Alto ↑")
) %>%
  kable(caption   = "Tabla 8b. Métricas de Evaluación del Modelo",
        row.names = FALSE, align = "lccc") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "bordered"),
                full_width = FALSE, position = "center") %>%
  column_spec(1, bold = TRUE, width = "10em") %>%
  column_spec(2, bold = TRUE, color = "#1565C0") %>%
  column_spec(3, width = "18em") %>%
  row_spec(0, bold = TRUE, background = "#37474F", color = "white") %>%
  row_spec(3, background = "#FFEBEE") %>%
  add_header_above(c(" " = 1, "Resultado" = 1, "Descripción" = 1, "Objetivo" = 1),
                   bold = TRUE, background = "#546E7A", color = "white")
Tabla 8b. Métricas de Evaluación del Modelo
Resultado
Descripción
Objetivo
Indicador Valor Interpretación Preferencia
Exactitud (Accuracy) 0.846 Proporción total de clasificaciones correctas Alto ↑
Tasa de Error 0.154 Proporción total de clasificaciones incorrectas Bajo ↓
Sensibilidad (Recall) 0.200 Capacidad de detectar empleados que SÍ rotan Alto ↑
Especificidad 0.978 Capacidad de detectar empleados que NO rotan Alto ↑
Precisión 0.652 Confiabilidad cuando predice rotación Alto ↑
Valor Pred. Negativo 0.856 Confiabilidad cuando predice no rotación Alto ↑

En la Tabla 8a se pueden observar las métricas de desempeño del modelo logístico obtenidas a partir de la matriz de confusión. Se observa que el modelo alcanza una exactitud (accuracy) de 84.6%, lo cual en principio indica un buen nivel de clasificación. No obstante, este resultado debe analizarse con cautela debido al desbalance presente en la variable respuesta, donde la mayoría de los empleados no rota.

Al profundizar en las métricas de la Tabla 8b, se evidencia que la sensibilidad (recall) es de apenas 20%, lo que indica que el modelo tiene una baja capacidad para identificar correctamente a los empleados que sí rotan. Esto implica que una proporción importante de casos reales de rotación no está siendo detectada, lo cual representa una limitación crítica desde el punto de vista del negocio.

En contraste, la especificidad (97.8%) es bastante alta, lo que significa que el modelo clasifica correctamente a la gran mayoría de los empleados que no rotan. Esta diferencia entre sensibilidad y especificidad evidencia que el modelo está sesgado hacia la clase mayoritaria, lo cual explica su alta exactitud general.

Por su parte, la precisión (65.2%) indica que, cuando el modelo predice que un empleado va a rotar, acierta en una proporción moderada. Asimismo, el valor predictivo negativo (85.6%) muestra que las predicciones de no rotación son bastante confiables. Sin embargo, el valor de balanced accuracy (58.9%) sugiere un desempeño limitado cuando se consideran ambas clases de manera equilibrada.

Los resultados de la Tabla 8a y Tabla 8b evidencian que aunque el modelo presenta un buen desempeño global, no es adecuado para detectar eventos de rotación bajo el punto de corte de 0.5.Por lo cual, es necesario ajustar el punto de corte con el fin de mejorar la sensibilidad del modelo y lograr una mejor identificación de empleados en riesgo de rotación.


Análisis de sensibilidad del punto de corte

cortes    <- seq(0.1, 0.9, by = 0.05)
resultados <- map_dfr(cortes, function(p) {
  pred_c <- factor(ifelse(valor_pred > p, "Si", "No"), levels = c("No", "Si"))
  cm     <- confusionMatrix(pred_c, test$Rotacion_f, positive = "Si")
  data.frame(
    Corte        = p,
    Exactitud    = cm$overall["Accuracy"],
    Sensibilidad = cm$byClass["Sensitivity"],
    Especificidad= cm$byClass["Specificity"]
  )
})

resultados %>%
  pivot_longer(cols = c(Exactitud, Sensibilidad, Especificidad),
               names_to = "Metrica", values_to = "Valor") %>%
  ggplot(aes(x = Corte, y = Valor, color = Metrica)) +
  geom_line(size = 1.2) +
  geom_vline(xintercept = 0.5, linetype = "dashed", color = "gray50") +
  scale_color_manual(values = c("#2196F3", "#FF7043", "#4CAF50")) +
  labs(title = "Gráfico 7. Sensibilidad del Modelo según Punto de Corte",
       x = "Punto de corte (p)", y = "Valor del indicador",
       color = "Métrica") +
  theme_minimal()

En el Gráfico 7 se puede observar cómo varía la exactitud, sensibilidad y especificidad según el punto de corte elegido. Un corte bajo favorece la sensibilidad (detectar más rotaciones reales), mientras que un corte alto favorece la especificidad. En contextos de RR.HH., puede preferirse un corte menor a 0.5 para no perder casos de rotación que deben intervenirse.

Del Gráfico 7 se observa que, a medida que el punto de corte aumenta, la especificidad se incrementa, mientras que la sensibilidad disminuye de manera considerable. Por el contrario, al reducir el punto de corte, la sensibilidad mejora, pero a costa de una menor especificidad.

En particular, alrededor del punto de corte tradicional de 0.5, el modelo presenta una alta especificidad pero una sensibilidad baja, lo cual confirma los resultados observados previamente en la Tabla 8. Esto implica que el modelo es eficiente para identificar empleados que no rotan, pero tiene dificultades para detectar aquellos que sí lo hacen.

De lo anterior se puede inferir que el punto de corte de 0.5 no es el más adecuado en este contexto, ya que prioriza la clasificación de la clase mayoritaria. En este sentido, al considerar valores de corte más bajos (por ejemplo, entre 0.2 y 0.4), se logra un mejor equilibrio entre sensibilidad y especificidad, incrementando la capacidad del modelo para identificar empleados en riesgo de rotación.

En un contexto de gestión de talento humano donde el costo de no detectar un empleado que va a rotar es alto, resulta más conveniente utilizar un punto de corte menor a 0.5, priorizando la sensibilidad del modelo. Esto permite implementar acciones preventivas de manera más efectiva, incluso si se incrementa el número de falsos positivos.


Curva ROC y AUC

curva_ROC <- roc(test$y, valor_pred)
auc_val   <- round(auc(curva_ROC), 4)

ggroc(curva_ROC, colour = "#FF7F00", size = 1.2) +
  geom_abline(slope = 1, intercept = 1, linetype = "dashed", color = "gray60") +
  ggtitle(paste0("Gráfico 8. Curva ROC  (AUC = ", auc_val, ")")) +
  xlab("Especificidad") +
  ylab("Sensibilidad") +
  theme_minimal()

En el Gráfico 8 se puede observar la curva ROC, la cual permite evaluar la capacidad del modelo para discriminar entre empleados que rotan y los que no, considerando todos los posibles puntos de corte. Se observa que la curva se encuentra por encima de la línea diagonal, lo que indica que el modelo tiene un desempeño mejor que una clasificación aleatoria.

Del Gráfico 8 se obtiene que el valor del AUC (Área Bajo la Curva) es 0.7474, lo que sugiere una capacidad discriminativa aceptable del modelo. En términos prácticos, esto significa que existe aproximadamente un 74.7% de probabilidad de que el modelo asigne una mayor probabilidad de rotación a un empleado que realmente rota frente a uno que no lo hace.

En este sentido, el modelo logra diferenciar adecuadamente entre ambas clases, aunque todavía presenta margen de mejora para alcanzar un nivel de precisión más alto. Este resultado es consistente con los análisis previos de la Tabla 8 y el Gráfico 7, donde se evidenció un buen desempeño general, pero con limitaciones en la detección de la clase minoritaria.

Finalmente, estos resultados confirman que el modelo tiene un desempeño adecuado para ser utilizado como herramienta de apoyo en la toma de decisiones, especialmente si se ajusta el punto de corte para priorizar la identificación de empleados en riesgo de rotación.


6. Predicciones

Se realiza la predicción para un empleado hipotético con las siguientes características:

empleado_hipotetico <- data.frame(
  Horas_Extra_bin    = 1,           # Trabaja horas extra
  Estado_Civil_f     = factor("Soltero",
                               levels = levels(rotacion$Estado_Civil_f)),
  Viaje_Frecuente    = factor("Frecuentemente",
                               levels = levels(rotacion$Viaje_Frecuente)),
  Ingreso_Mensual    = 2500,        # Ingreso mensual bajo
  Antigüedad         = 2,           # 2 años en la empresa
  `Satisfación_Laboral` = 1,        # Satisfacción baja
  check.names = FALSE
)

prob_rotacion <- predict(modelo_logit, newdata = empleado_hipotetico, type = "response")
decision      <- ifelse(prob_rotacion > 0.3, "⚠️ INTERVENIR", "✅ Sin riesgo inmediato")

data.frame(
  Característica = c("Horas Extra", "Estado Civil", "Viaje de Negocios",
                     "Ingreso Mensual", "Antigüedad", "Satisfacción Laboral",
                     "Probabilidad de Rotación", "Decisión (corte=0.30)"),
  Valor = c("Sí", "Soltero", "Frecuentemente", "$2,500", "2 años", "1 (Baja)",
            paste0(round(prob_rotacion * 100, 1), "%"), decision)
) %>%
  kable(caption = "Tabla 9. Predicción para empleado hipotético",
        col.names = c("Característica", "Valor")) %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE) %>%
  row_spec(7:8, bold = TRUE, background = "#FFF9C4")
Tabla 9. Predicción para empleado hipotético
Característica Valor
Horas Extra
Estado Civil Soltero
Viaje de Negocios Frecuentemente
Ingreso Mensual $2,500
Antigüedad 2 años
Satisfacción Laboral 1 (Baja)
Probabilidad de Rotación 83.5%
Decisión (corte=0.30) ⚠️ INTERVENIR

Criterio de intervención: Se usa un punto de corte de 0.30 (en lugar de 0.50) porque en un contexto de gestión humana es más costoso no intervenir a un empleado que sí va a rotar (falso negativo) que intervenir innecesariamente a uno que no iba a rotar (falso positivo). Así se prioriza la sensibilidad del modelo, tal como se analizó en el Gráfico 7.

En la Tabla 9 se presenta la predicción realizada para un empleado hipotético con características asociadas a un alto riesgo de rotación, como la realización de horas extra, bajo ingreso mensual, poca antigüedad y baja satisfacción laboral. A partir del modelo logístico, se obtiene una probabilidad de rotación del 83.5%, lo que indica un riesgo elevado de que el empleado abandone la organización.

Este resultado es coherente con los hallazgos obtenidos en el análisis previo, donde variables como las horas extra, el nivel salarial, la antigüedad y la satisfacción laboral mostraron una influencia significativa sobre la rotación (ver Tabla 7). En particular, la combinación de múltiples factores de riesgo en un mismo perfil incrementa considerablemente la probabilidad estimada por el modelo.

En este sentido, al aplicar un punto de corte de 0.30, el modelo clasifica al empleado como un caso que requiere intervención. Esta decisión se justifica debido a que, en contextos de gestión del talento humano, el costo de no identificar a un empleado que efectivamente va a rotar (falso negativo) es mayor que el de intervenir preventivamente en un caso que finalmente no rota (falso positivo).

Bajo este enfoque, el modelo no solo permite estimar probabilidades, sino también apoyar la toma de decisiones estratégicas, facilitando la identificación temprana de empleados en riesgo y la implementación de acciones preventivas orientadas a su retención.


7. Conclusiones

Con base en el análisis exploratorio, bivariado y la estimación del modelo de regresión logística, se obtienen las siguientes conclusiones:

En primer lugar, los resultados evidencian que la rotación de empleados es un fenómeno multifactorial, en el cual intervienen tanto variables laborales como personales. El análisis permitió identificar que factores como la carga laboral, el nivel salarial, la satisfacción y ciertas condiciones individuales influyen de manera significativa en la probabilidad de abandono.

En cuanto a las variables explicativas, se encontró que Horas Extra, Ingreso Mensual, Satisfacción Laboral y Estado Civil (soltero) presentan efectos estadísticamente significativos dentro del modelo (ver Tabla 7). En particular, trabajar horas extra incrementa considerablemente el riesgo de rotación, mientras que mayores niveles de ingreso y satisfacción laboral actúan como factores protectores. Estos resultados no solo son consistentes con las hipótesis planteadas, sino también con el análisis bivariado y las pruebas estadísticas realizadas en las Tablas 5 y 6.

Asimismo, variables como la Antigüedad muestran una relación negativa con la rotación, aunque con significancia marginal, lo que sugiere que, si bien existe una tendencia a que empleados con mayor tiempo en la empresa permanezcan, este efecto puede depender de otros factores complementarios.

Desde el punto de vista del desempeño del modelo, se obtuvo un AUC de 0.7474 (ver Gráfico 8), lo que indica una capacidad discriminativa aceptable. Sin embargo, el análisis de las Tabla 8a y Tabla 8b evidenció que, bajo un punto de corte tradicional (0.5), el modelo presenta baja sensibilidad (20%), lo que limita su capacidad para identificar correctamente a los empleados que efectivamente rotan. Esto resulta especialmente crítico dado el desbalance de la variable respuesta.

En este sentido, el análisis de sensibilidad del Gráfico 7 permitió establecer que valores inferiores a 0.5 (por ejemplo, 0.3) ofrecen un mejor equilibrio entre métricas, priorizando la detección de casos de rotación. Esto es clave en contextos organizacionales, donde el costo de no intervenir a tiempo es significativamente mayor que el de realizar acciones preventivas innecesarias.

Adicionalmente, la aplicación del modelo al caso hipotético de la Tabla 9 evidenció su utilidad práctica, al identificar con alta probabilidad (83.5%) un perfil de empleado en riesgo, lo que demuestra su potencial como herramienta de apoyo en la toma de decisiones estratégicas en gestión del talento humano.

Finalmente, a partir de los hallazgos obtenidos, se proponen las siguientes estrategias orientadas a reducir la rotación:

  • Gestión de la carga laboral: Regular y monitorear las horas extra para evitar el desgaste de los empleados.

  • Política salarial competitiva: Ajustar los niveles de ingreso para mejorar la retención, especialmente en perfiles vulnerables.

  • Fortalecimiento del clima organizacional: Implementar acciones que incrementen la satisfacción laboral, como reconocimiento, beneficios y flexibilidad.

  • Estrategias de fidelización: Diseñar programas que aumenten el sentido de pertenencia, especialmente en empleados con menor antigüedad.

  • Optimización de viajes laborales: Reducir la frecuencia o mejorar las condiciones asociadas a los viajes de negocio.

  • Segmentación de empleados en riesgo: Utilizar el modelo para identificar perfiles críticos (como empleados solteros con alta carga laboral) y aplicar intervenciones focalizadas.

En conclusión, el modelo desarrollado no solo permite comprender los factores que influyen en la rotación, sino también constituye una herramienta valiosa para la toma de decisiones basada en datos, facilitando la implementación de estrategias preventivas que contribuyan a la retención del talento en la organización.