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.
# 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)## 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.
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)| 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.
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.
# 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.
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")| 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.
## 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.
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.
| 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.
| 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.
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)| 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.
# 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.
# 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)| 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.
Se analiza la relación entre cada variable seleccionada y la rotación (y=1 rota, y=0 no rota).
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.
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)| 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.
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.
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)| 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.
# 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.
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)| 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.
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")| Real: Sí | Real: No | |
|---|---|---|
| Predicción: Sí |
Verdaderos Positivos (VP) |
Falsos Positivos (FP) |
| Predicción: No |
Falsos Negativos (FN) |
Verdaderos Negativos (VN) |
# --- 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")| 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.
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 <- 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.
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")| Característica | Valor |
|---|---|
| Horas Extra | Sí |
| 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.
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.