# Ejecutar una unica vez si falta alguna de estas librerias
install.packages(c("devtools", "dplyr", "tidyr", "ggplot2", "pROC", "car",
"knitr", "kableExtra", "gridExtra"))
devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
La empresa busca comprender y anticipar la rotación de sus empleados a partir de información histórica (antigüedad, satisfacción laboral, salario, edad, entre otras). El objetivo de este informe es estimar un modelo de regresión logística que permita calcular la probabilidad de que un empleado rote en el próximo período, identificar qué factores influyen más en esa decisión, y proponer un punto de corte que la empresa pueda usar para decidir en qué casos intervenir de forma proactiva.
Metodología adecuada para este caso: la variable
respuesta (Rotación) es binaria (rota / no
rota), por lo que un modelo de regresión lineal múltiple (MCO) no es
apropiado aquí — podría predecir probabilidades menores a 0 o mayores a
1, y no cumple los supuestos de normalidad y homocedasticidad de los
residuos que exige el MCO. Por eso se usa un modelo de regresión
logística (logit), que modela el logaritmo de las odds
(ln(p/(1-p))) como una combinación lineal de las
covariables, garantizando que la probabilidad estimada siempre quede
entre 0 y 1, y se estima por máxima verosimilitud en lugar de mínimos
cuadrados.
La base rotacion contiene 1470 empleados y 23 variables
explicativas, sin datos faltantes.
La docente del curso precisó el significado y la escala de las
variables de la base rotacion que se listan a continuación.
Esta información se tuvo en cuenta para decidir cómo tratar cada una en
el análisis: las variables con escala de niveles (1, 2, 3, …) son
ordinales y se describen con tablas de frecuencia,
mientras que las que se miden en unidades reales (kilómetros, número de
empleos) son cuantitativas.
| Variable | Descripción | Escala / unidad | Tipo |
|---|---|---|---|
| Rendimiento_Laboral | Calificación del rendimiento del empleado | 1 = bajo, 2 = medio, 3 = alto, 4 = muy alto | Ordinal |
| Distancia_Casa | Distancia entre la casa del empleado y el lugar de trabajo | Kilómetros | Cuantitativa |
| Educación | Nivel educativo alcanzado | 1 = primaria, …, 5 = posgrado | Ordinal |
| Satisfacción_Ambiental | Satisfacción con el ambiente de trabajo | 1 = muy insatisfecho, …, 4 = muy satisfecho | Ordinal |
| Satisfación_Laboral | Satisfacción con el trabajo que desempeña | 1 = muy insatisfecho, …, 4 = muy satisfecho | Ordinal |
| Trabajos_Anteriores | Número de empleos que tuvo la persona antes de ingresar a la empresa | Conteo | Cuantitativa |
| Equilibrio_Trabajo_Vida | Equilibrio percibido entre la vida laboral y la personal | 1 = muy bajo, 2 = bajo, 3 = medio, 4 = alto | Ordinal |
Se seleccionaron 3 variables categóricas y 3 cuantitativas, distintas
de Rotación, que por su naturaleza se esperaría que estén
relacionadas con la decisión de un empleado de cambiar de cargo. También
se descartaron a propósito variables numéricas tipo Likert
(Educación, Satisfacción_Ambiental,
Satisfación_Laboral, Rendimiento_Laboral,
Equilibrio_Trabajo_Vida): aunque están codificadas como
números del 1 al 4 (o 1 al 5), son escalas ordinales,
no cuantitativas continuas, así que no se tratan como tal en este
análisis.
| Variable | Tipo | Hipótesis |
|---|---|---|
| Horas extra | Categórica | Trabajar horas extra genera mayor desgaste y menos tiempo personal, por lo que se espera mayor rotación entre quienes sí las hacen. |
| Viaje de negocios | Categórica | Viajar con mayor frecuencia implica más fatiga y menos estabilidad en el hogar; se espera que a mayor frecuencia de viaje, mayor rotación. |
| Estado civil | Categórica | Los empleados solteros tienen menos cargas familiares que los aten a la estabilidad del cargo; se espera mayor rotación en solteros que en casados. |
| Ingreso mensual | Cuantitativa | A mayor salario, mayor satisfacción económica y mayor costo de oportunidad de irse; se espera una relación negativa con la rotación. |
| Antigüedad en la empresa | Cuantitativa | A mayor antigüedad, mayor apego e inversión acumulada en la organización; se espera una relación negativa con la rotación. |
| Distancia a la casa | Cuantitativa | Un desplazamiento largo al trabajo es un motivo frecuente de cambio de empleo; se espera una relación positiva con la rotación. |
tabla_rot <- rotacion %>% count(rotacion) %>% mutate(Porcentaje = round(100 * n / sum(n), 1))
kable(tabla_rot, col.names = c("Rotación", "n", "%"))
| Rotación | n | % |
|---|---|---|
| No | 1233 | 83.9 |
| Si | 237 | 16.1 |
De los 1470 empleados, 237 (16.1%) rotaron en el período analizado y 1233 (83.9%) no lo hicieron. Las clases están desbalanceadas (la rotación es un evento minoritario), algo que se debe tener en cuenta más adelante al evaluar el modelo: una medida simple como el accuracy puede ser engañosa cuando una clase domina tanto a la otra.
tabla_cuant <- data.frame(
Variable = etq_cuant[vars_cuant],
Media = sapply(vars_cuant, function(v) mean(rotacion[[v]])),
Mediana = sapply(vars_cuant, function(v) median(rotacion[[v]])),
DE = sapply(vars_cuant, function(v) sd(rotacion[[v]])),
Min = sapply(vars_cuant, function(v) min(rotacion[[v]])),
Max = sapply(vars_cuant, function(v) max(rotacion[[v]]))
)
rownames(tabla_cuant) <- NULL
kable(tabla_cuant, digits = 1)
| Variable | Media | Mediana | DE | Min | Max |
|---|---|---|---|---|---|
| Edad | 36.9 | 36 | 9.1 | 18 | 60 |
| Distancia a la casa (km) | 9.2 | 7 | 8.1 | 1 | 29 |
| Ingreso mensual | 6502.9 | 4919 | 4708.0 | 1009 | 19999 |
| Trabajos anteriores | 2.7 | 2 | 2.5 | 0 | 9 |
| % aumento salarial | 15.2 | 14 | 3.7 | 11 | 25 |
| Anios de experiencia | 11.3 | 10 | 7.8 | 0 | 40 |
| Capacitaciones | 2.8 | 3 | 1.3 | 0 | 6 |
| Antiguedad en la empresa (anios) | 7.0 | 5 | 6.1 | 0 | 40 |
| Antiguedad en el cargo (anios) | 4.2 | 3 | 3.6 | 0 | 18 |
| Anios desde la ultima promocion | 2.2 | 1 | 3.2 | 0 | 15 |
| Anios con el mismo jefe | 4.1 | 3 | 3.6 | 0 | 17 |
En promedio los empleados tienen 36.9 años, llevan 7 años en la empresa y viven a 9.2 km del trabajo, con un ingreso mensual promedio de 6503. Todas estas variables muestran una dispersión considerable (desviaciones estándar grandes frente a la media), lo que sugiere una población heterogénea en antigüedad e ingresos.
p1 <- ggplot(rotacion, aes(x = ingreso_mensual)) +
geom_histogram(bins = 30, fill = "#4C72B0", color = "white") +
labs(x = "Ingreso mensual", y = "Frecuencia", title = "Ingreso mensual") +
theme_minimal()
p2 <- ggplot(rotacion, aes(x = antiguedad)) +
geom_histogram(bins = 20, fill = "#55A868", color = "white") +
labs(x = "Antigüedad (años)", y = "Frecuencia", title = "Antigüedad") +
theme_minimal()
p3 <- ggplot(rotacion, aes(x = distancia_casa)) +
geom_histogram(bins = 20, fill = "#C44E52", color = "white") +
labs(x = "Distancia a la casa (km)", y = "Frecuencia", title = "Distancia a la casa") +
theme_minimal()
gridExtra::grid.arrange(p1, p2, p3, ncol = 3)
Las tres variables muestran una distribución sesgada a la derecha (muchos empleados con ingresos, antigüedad y distancias bajas, y una cola de valores altos), típico de este tipo de variables laborales.
for (v in vars_ordinal) {
cat("**", etq_ordinal[[v]], "**\n\n", sep = "")
tab <- round(100 * prop.table(table(rotacion[[v]])), 1)
print(kable(as.data.frame(tab), col.names = c("Nivel", "%")))
cat("\n\n")
}
Nivel educativo
| Nivel | % |
|---|---|
| 1 | 11.6 |
| 2 | 19.2 |
| 3 | 38.9 |
| 4 | 27.1 |
| 5 | 3.3 |
Satisfaccion ambiental
| Nivel | % |
|---|---|
| 1 | 19.3 |
| 2 | 19.5 |
| 3 | 30.8 |
| 4 | 30.3 |
Satisfaccion laboral
| Nivel | % |
|---|---|
| 1 | 19.7 |
| 2 | 19.0 |
| 3 | 30.1 |
| 4 | 31.2 |
Rendimiento laboral
| Nivel | % |
|---|---|
| 3 | 84.6 |
| 4 | 15.4 |
Equilibrio trabajo-vida
| Nivel | % |
|---|---|
| 1 | 5.4 |
| 2 | 23.4 |
| 3 | 60.7 |
| 4 | 10.4 |
Estas cinco variables se presentan solo con su distribución de frecuencias (no con promedios ni desviaciones), porque son escalas ordinales y no variables numéricas continuas.
for (v in vars_cat) {
cat("**", etq_cat[[v]], "**\n\n", sep = "")
tab <- round(100 * prop.table(table(rotacion[[v]])), 1)
print(kable(as.data.frame(tab), col.names = c("Categoría", "%")))
cat("\n\n")
}
Viaje de negocios
| Categoría | % |
|---|---|
| No_Viaja | 10.2 |
| Raramente | 71.0 |
| Frecuentemente | 18.8 |
Departamento
| Categoría | % |
|---|---|
| IyD | 65.4 |
| RH | 4.3 |
| Ventas | 30.3 |
Campo de educacion
| Categoría | % |
|---|---|
| Ciencias | 41.2 |
| Humanidades | 1.8 |
| Mercadeo | 10.8 |
| Otra | 5.6 |
| Salud | 31.6 |
| Tecnicos | 9.0 |
Genero
| Categoría | % |
|---|---|
| F | 40 |
| M | 60 |
Cargo
| Categoría | % |
|---|---|
| Director_Investigación | 5.4 |
| Director_Manofactura | 9.9 |
| Ejecutivo_Ventas | 22.2 |
| Gerente | 6.9 |
| Investigador_Cientifico | 19.9 |
| Recursos_Humanos | 3.5 |
| Representante_Salud | 8.9 |
| Representante_Ventas | 5.6 |
| Tecnico_Laboratorio | 17.6 |
Estado civil
| Categoría | % |
|---|---|
| Soltero | 32.0 |
| Casado | 45.8 |
| Divorciado | 22.2 |
Horas extra
| Categoría | % |
|---|---|
| No | 71.7 |
| Si | 28.3 |
Se destaca que el 28.3% de los empleados trabaja horas extra, que 18.8% viaja frecuentemente por negocios, y que los solteros representan el 32% de la planta — las tres variables categóricas seleccionadas para el modelo.
Se recodificó Rotación como variable binaria
(y = 1 si rotó, y = 0 si no) y se analizó su
relación con cada una de las 6 variables seleccionadas, ajustando un
modelo logístico simple (una sola covariable) por variable.
tab_horas <- rotacion %>% count(horas_extra, rotacion) %>% group_by(horas_extra) %>%
mutate(Porcentaje = round(100*n/sum(n),1))
kable(tab_horas, col.names = c("Horas extra", "Rotación", "n", "%"))
| Horas extra | Rotación | n | % |
|---|---|---|---|
| No | No | 944 | 89.6 |
| No | Si | 110 | 10.4 |
| Si | No | 289 | 69.5 |
| Si | Si | 127 | 30.5 |
kable(summary(modelos_biv$horas_extra)$coefficients, digits = 4)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -2.1496 | 0.1007 | -21.3379 | 0 |
| horas_extraSi | 1.3274 | 0.1466 | 9.0563 | 0 |
El 30.5% de quienes trabajan horas extra rotó, frente a solo 10.4% de quienes no las trabajan. El coeficiente es positivo y altamente significativo (p < 0.001), confirmando la hipótesis: trabajar horas extra aumenta la probabilidad de rotar.
tab_viaje <- rotacion %>% count(viaje_negocios, rotacion) %>% group_by(viaje_negocios) %>%
mutate(Porcentaje = round(100*n/sum(n),1))
kable(tab_viaje, col.names = c("Viaje de negocios", "Rotación", "n", "%"))
| Viaje de negocios | Rotación | n | % |
|---|---|---|---|
| No_Viaja | No | 138 | 92.0 |
| No_Viaja | Si | 12 | 8.0 |
| Raramente | No | 887 | 85.0 |
| Raramente | Si | 156 | 15.0 |
| Frecuentemente | No | 208 | 75.1 |
| Frecuentemente | Si | 69 | 24.9 |
kable(summary(modelos_biv$viaje_negocios)$coefficients, digits = 4)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -2.4423 | 0.3010 | -8.1151 | 0.0000 |
| viaje_negociosRaramente | 0.7044 | 0.3132 | 2.2486 | 0.0245 |
| viaje_negociosFrecuentemente | 1.3389 | 0.3315 | 4.0392 | 0.0001 |
La proporción de rotación aumenta de forma monótona con la frecuencia de viaje: los dos coeficientes (frente a “no viaja”) son positivos y significativos, y el de “Frecuentemente” es mayor que el de “Raramente” — confirma la hipótesis de que viajar más se asocia con mayor rotación.
tab_estado <- rotacion %>% count(estado_civil, rotacion) %>% group_by(estado_civil) %>%
mutate(Porcentaje = round(100*n/sum(n),1))
kable(tab_estado, col.names = c("Estado civil", "Rotación", "n", "%"))
| Estado civil | Rotación | n | % |
|---|---|---|---|
| Soltero | No | 350 | 74.5 |
| Soltero | Si | 120 | 25.5 |
| Casado | No | 589 | 87.5 |
| Casado | Si | 84 | 12.5 |
| Divorciado | No | 294 | 89.9 |
| Divorciado | Si | 33 | 10.1 |
kable(summary(modelos_biv$estado_civil)$coefficients, digits = 4)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -1.0704 | 0.1058 | -10.1190 | 0 |
| estado_civilCasado | -0.8772 | 0.1575 | -5.5708 | 0 |
| estado_civilDivorciado | -1.1166 | 0.2119 | -5.2703 | 0 |
Ambos coeficientes (Casado y Divorciado, frente a Soltero) son negativos y significativos: estar casado o divorciado reduce la probabilidad de rotar frente a estar soltero, tal como se planteó en la hipótesis.
kable(summary(modelos_biv$ingreso_mensual)$coefficients, digits = 6)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -0.929109 | 0.129202 | -7.191125 | 0 |
| ingreso_mensual | -0.000127 | 0.000022 | -5.879336 | 0 |
ggplot(rotacion, aes(x = rotacion, y = ingreso_mensual)) + geom_boxplot(fill = "#4C72B0") +
labs(x = "Rotación", y = "Ingreso mensual") + theme_minimal()
El coeficiente es negativo y significativo (p < 0.001): a mayor ingreso mensual, menor probabilidad de rotar, confirmando la hipótesis.
kable(summary(modelos_biv$antiguedad)$coefficients, digits = 4)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -1.1558 | 0.1114 | -10.3777 | 0 |
| antiguedad | -0.0808 | 0.0159 | -5.0676 | 0 |
ggplot(rotacion, aes(x = rotacion, y = antiguedad)) + geom_boxplot(fill = "#55A868") +
labs(x = "Rotación", y = "Antigüedad (años)") + theme_minimal()
El coeficiente es negativo y significativo: a mayor antigüedad, menor probabilidad de rotar, confirmando la hipótesis.
kable(summary(modelos_biv$distancia_casa)$coefficients, digits = 4)
| Estimate | Std. Error | z value | Pr(>|z|) | |
|---|---|---|---|---|
| (Intercept) | -1.8901 | 0.1114 | -16.9691 | 0.000 |
| distancia_casa | 0.0247 | 0.0083 | 2.9727 | 0.003 |
ggplot(rotacion, aes(x = rotacion, y = distancia_casa)) + geom_boxplot(fill = "#C44E52") +
labs(x = "Rotación", y = "Distancia a la casa (km)") + theme_minimal()
El coeficiente es positivo y significativo: a mayor distancia a la casa, mayor probabilidad de rotar, confirmando la hipótesis.
Resumen: las seis variables resultaron determinantes de la rotación en el análisis bivariado, y en los seis casos el signo del coeficiente coincide con la hipótesis planteada en el punto 1.
Se estimó un único modelo de regresión logística con las 6 covariables seleccionadas:
summary(modelo)
##
## Call:
## glm(formula = y ~ horas_extra + viaje_negocios + estado_civil +
## ingreso_mensual + antiguedad + distancia_casa, family = binomial,
## data = rotacion)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.829e+00 3.650e-01 -5.012 5.38e-07 ***
## horas_extraSi 1.443e+00 1.574e-01 9.171 < 2e-16 ***
## viaje_negociosRaramente 7.007e-01 3.297e-01 2.125 0.033583 *
## viaje_negociosFrecuentemente 1.340e+00 3.515e-01 3.812 0.000138 ***
## estado_civilCasado -9.019e-01 1.707e-01 -5.284 1.27e-07 ***
## estado_civilDivorciado -1.169e+00 2.265e-01 -5.159 2.48e-07 ***
## ingreso_mensual -1.049e-04 2.474e-05 -4.241 2.23e-05 ***
## antiguedad -4.711e-02 1.826e-02 -2.579 0.009898 **
## distancia_casa 3.285e-02 9.243e-03 3.555 0.000378 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1298.6 on 1469 degrees of freedom
## Residual deviance: 1088.7 on 1461 degrees of freedom
## AIC: 1106.7
##
## Number of Fisher Scoring iterations: 5
kable(or_tabla, digits = 4, caption = "Odds ratios (OR) e intervalos de confianza al 95%")
| OR | 2.5 % | 97.5 % | |
|---|---|---|---|
| (Intercept) | 0.1605 | 0.0754 | 0.3182 |
| horas_extraSi | 4.2340 | 3.1151 | 5.7760 |
| viaje_negociosRaramente | 2.0151 | 1.0953 | 4.0295 |
| viaje_negociosFrecuentemente | 3.8186 | 1.9783 | 7.9246 |
| estado_civilCasado | 0.4058 | 0.2896 | 0.5659 |
| estado_civilDivorciado | 0.3108 | 0.1968 | 0.4794 |
| ingreso_mensual | 0.9999 | 0.9998 | 0.9999 |
| antiguedad | 0.9540 | 0.9196 | 0.9880 |
| distancia_casa | 1.0334 | 1.0148 | 1.0522 |
Interpretación de los coeficientes (manteniendo las demás variables constantes):
Las seis variables resultaron significativas (p < 0.05), consistentes en signo con el análisis bivariado y con las hipótesis del punto 1. El pseudo-R\(^2\) de McFadden es 0.162 — razonable para un modelo de ciencias sociales/negocios con solo 6 predictores. Como verificación adicional, los factores de inflación de varianza (VIF) son bajos para todas las variables (GVIF ajustado máximo 1.09, muy por debajo del umbral habitual de 2.24, equivalente a un VIF de 5), por lo que no hay problemas relevantes de colinealidad entre las covariables del modelo.
pROC::ggroc(roc_obj, color = "#4C72B0", size = 1) +
geom_abline(slope = 1, intercept = 1, linetype = "dashed", color = "grey60") +
labs(title = "Curva ROC", x = "Especificidad", y = "Sensibilidad") +
theme_minimal()
El área bajo la curva ROC es AUC = 0.773 (IC 95%: 0.738 – 0.808), lo que indica una capacidad de discriminación aceptable/buena (un modelo sin ningún poder predictivo tendría AUC = 0.5, y uno perfecto, AUC = 1).
Dado el desbalance de clases visto en el punto 2 (solo 16.1% de rotación), usar el punto de corte por defecto (0.5) favorece demasiado a la clase mayoritaria:
kable(matriz_05, caption = "Matriz de confusión — corte 0.5")
| 0 | 1 | |
|---|---|---|
| 0 | 1215 | 196 |
| 1 | 18 | 41 |
Con corte 0.5 el accuracy es 85.4%, pero la sensibilidad (capacidad de detectar a quienes sí rotan) es de apenas 17.3% — el modelo deja pasar a la mayoría de los empleados que efectivamente rotarán. Usando el punto de corte óptimo según el estadístico de Youden (0.193):
kable(matriz_opt, caption = "Matriz de confusión — corte óptimo (Youden)")
| 0 | 1 | |
|---|---|---|
| 0 | 953 | 76 |
| 1 | 280 | 161 |
Con este corte, el accuracy baja a 75.8% pero la sensibilidad sube a 67.9% — se sacrifica algo de exactitud global a cambio de detectar muchos más casos reales de rotación, que es justamente lo que le interesa a la empresa para poder intervenir a tiempo.
Comparar solo dos cortes (0.5 y el óptimo) no es suficiente para elegir bien el umbral: se evaluó cómo cambian la sensibilidad, la especificidad, la exactitud y el valor predictivo positivo (de los empleados marcados para intervención, cuántos realmente rotaban) a lo largo de un rango de cortes posibles, de 0.05 a 0.60.
kable(analisis_corte, digits = 3,
col.names = c("Corte", "Sensibilidad", "Especificidad", "Exactitud", "VPP"),
caption = "Sensibilidad, especificidad, exactitud y VPP según el punto de corte")
| Corte | Sensibilidad | Especificidad | Exactitud | VPP |
|---|---|---|---|---|
| 0.05 | 0.937 | 0.244 | 0.356 | 0.192 |
| 0.10 | 0.823 | 0.517 | 0.566 | 0.247 |
| 0.15 | 0.743 | 0.678 | 0.688 | 0.307 |
| 0.20 | 0.662 | 0.780 | 0.761 | 0.367 |
| 0.25 | 0.561 | 0.858 | 0.810 | 0.432 |
| 0.30 | 0.447 | 0.904 | 0.831 | 0.473 |
| 0.35 | 0.363 | 0.938 | 0.845 | 0.528 |
| 0.40 | 0.287 | 0.957 | 0.849 | 0.562 |
| 0.45 | 0.228 | 0.972 | 0.852 | 0.614 |
| 0.50 | 0.173 | 0.985 | 0.854 | 0.695 |
| 0.55 | 0.131 | 0.992 | 0.853 | 0.756 |
| 0.60 | 0.097 | 0.997 | 0.852 | 0.852 |
analisis_largo <- pivot_longer(analisis_corte,
cols = c("Sensibilidad", "Especificidad", "Exactitud"),
names_to = "Metrica", values_to = "Valor")
ggplot(analisis_largo, aes(x = Corte, y = Valor, color = Metrica)) +
geom_line(linewidth = 1) + geom_point() +
geom_vline(xintercept = umbral_elegido, linetype = "dashed", color = "grey40") +
annotate("text", x = umbral_elegido, y = 0.05, label = "Corte óptimo (Youden)",
hjust = -0.05, size = 3) +
scale_y_continuous(limits = c(0,1)) +
labs(x = "Punto de corte", y = "Valor", color = NULL,
title = "Sensibilidad vs. especificidad según el punto de corte") +
theme_minimal()
El gráfico muestra el típico trade-off: a medida que el corte sube, la especificidad y la exactitud aumentan, pero la sensibilidad cae rápidamente — con cortes altos (0.5 o más) el modelo prácticamente deja de detectar casos de rotación real (sensibilidad por debajo de 17%). Cortes muy bajos (0.05-0.10) maximizan la sensibilidad pero a costa de marcar para intervención a una enorme cantidad de empleados que no iban a rotar (VPP muy bajo, especificidad baja), lo cual no es práctico para la empresa. El corte óptimo de Youden (0.193) está justo en la zona donde sensibilidad y especificidad se cruzan, ofreciendo el mejor balance entre ambas — por eso se elige como punto de corte recomendado en la siguiente sección.
Se evaluaron dos perfiles hipotéticos de empleados con el modelo estimado:
tabla_pred <- data.frame(
Perfil = c("Alto riesgo", "Bajo riesgo"),
Horas_extra = c("Sí", "No"),
Viaje = c("Frecuentemente", "Raramente"),
Estado_civil = c("Soltero", "Casado"),
Ingreso = c(2500, 7000),
Antiguedad = c(2, 12),
Distancia = c(20, 3),
Prob_rotacion = round(c(p_alto, p_bajo), 3)
)
kable(tabla_pred)
| Perfil | Horas_extra | Viaje | Estado_civil | Ingreso | Antiguedad | Distancia | Prob_rotacion |
|---|---|---|---|---|---|---|---|
| Alto riesgo | Sí | Frecuentemente | Soltero | 2500 | 2 | 20 | 0.778 |
| Bajo riesgo | No | Raramente | Casado | 7000 | 12 | 3 | 0.038 |
El primer perfil (empleado soltero, con horas extra, que viaja frecuentemente, ingreso bajo, poca antigüedad y vive lejos) tiene una probabilidad estimada de rotar de 77.8%. El segundo perfil (empleado casado, sin horas extra, que viaja poco, con mejor ingreso, mayor antigüedad y cerca del trabajo) tiene una probabilidad de apenas 3.8%.
Punto de corte propuesto: se recomienda usar el umbral óptimo de Youden (0.193) en lugar de 0.5 como criterio para decidir si se interviene a un empleado. La razón es de costo-beneficio: el costo de “intervenir de más” a un empleado que no iba a rotar (una conversación, un plan de desarrollo) es mucho menor que el costo de no detectar a tiempo a un empleado que sí va a rotar (perder talento clave, costos de reemplazo y capacitación). Con ese criterio, el primer perfil (77.8% > 19.3%) sí se marcaría para intervención, mientras que el segundo (3.8% < 19.3%) no lo requeriría por ahora.
El modelo de regresión logística identificó seis factores significativamente asociados con la rotación de personal, todos en la dirección esperada: trabajar horas extra, viajar frecuentemente por negocios y ser soltero aumentan la probabilidad de rotar, mientras que un mayor ingreso mensual, mayor antigüedad en la empresa y vivir cerca del trabajo la reducen. El modelo tiene una capacidad de discriminación aceptable (AUC aprox. 0.77), suficiente para apoyar decisiones de retención, aunque no para sustituir el juicio humano.
Con base en estos resultados, la empresa podría enfocar su estrategia de retención en:
En conjunto, usar el modelo con el punto de corte propuesto (0.193) le permitiría a Recursos Humanos priorizar sus esfuerzos de retención en el grupo de empleados con mayor probabilidad estimada de rotar, en lugar de aplicar medidas genéricas a toda la planta.