En una organización, se busca comprender y prever los factores que influyen en la rotación de empleados entre distintos cargos. La empresa ha recopilado datos históricos sobre el empleo de sus trabajadores, incluyendo variables como la antigüedad en el cargo actual, el nivel de satisfacción laboral, el salario actual, edad y otros factores relevantes. La gerencia planea desarrollar un modelo de regresión logística que permita estimar la probabilidad de que un empleado cambie de cargo en el próximo período y determinar cuales factores indicen en mayor proporción a estos cambios.
Con esta información, la empresa podrá tomar medidas proactivas para retener a su talento clave, identificar áreas de mejora en la gestión de recursos humanos y fomentar un ambiente laboral más estable y tranquilo. La predicción de la probabilidad de rotación de empleados ayudará a la empresa a tomar decisiones estratégicas informadas y a mantener un equipo de trabajo comprometido y satisfecho en sus roles actuales.
A continuación se describen los pasos que la gerencia ha propuesto para el análisis:
skim(df)
| Name | df |
| Number of rows | 1470 |
| Number of columns | 24 |
| _______________________ | |
| Column type frequency: | |
| character | 12 |
| numeric | 12 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| Viaje de Negocios | 0 | 1 | 8 | 14 | 0 | 3 | 0 |
| Departamento | 0 | 1 | 2 | 6 | 0 | 3 | 0 |
| Educación | 0 | 1 | 8 | 17 | 0 | 5 | 0 |
| Campo_Educación | 0 | 1 | 4 | 11 | 0 | 6 | 0 |
| Satisfacción_Ambiental | 0 | 1 | 10 | 16 | 0 | 4 | 0 |
| Genero | 0 | 1 | 1 | 1 | 0 | 2 | 0 |
| Cargo | 0 | 1 | 7 | 23 | 0 | 9 | 0 |
| Satisfación_Laboral | 0 | 1 | 10 | 15 | 0 | 4 | 0 |
| Estado_Civil | 0 | 1 | 6 | 10 | 0 | 3 | 0 |
| Horas_Extra | 0 | 1 | 2 | 2 | 0 | 2 | 0 |
| Rendimiento_Laboral | 0 | 1 | 4 | 8 | 0 | 2 | 0 |
| Equilibrio_Trabajo_Vida | 0 | 1 | 4 | 8 | 0 | 4 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| Rotación | 0 | 1 | 0.16 | 0.37 | 0 | 0 | 0 | 0 | 1 | ▇▁▁▁▂ |
| Edad | 0 | 1 | 36.92 | 9.14 | 18 | 30 | 36 | 43 | 60 | ▂▇▇▃▂ |
| Distancia_Casa | 0 | 1 | 9.19 | 8.11 | 1 | 2 | 7 | 14 | 29 | ▇▅▂▂▂ |
| Ingreso_Mensual | 0 | 1 | 6502.93 | 4707.96 | 1009 | 2911 | 4919 | 8379 | 19999 | ▇▅▂▁▂ |
| Trabajos_Anteriores | 0 | 1 | 2.69 | 2.50 | 0 | 1 | 2 | 4 | 9 | ▇▃▂▂▁ |
| Porcentaje_aumento_salarial | 0 | 1 | 15.21 | 3.66 | 11 | 12 | 14 | 18 | 25 | ▇▅▃▂▁ |
| Años_Experiencia | 0 | 1 | 11.28 | 7.78 | 0 | 6 | 10 | 15 | 40 | ▇▇▂▁▁ |
| Capacitaciones | 0 | 1 | 2.80 | 1.29 | 0 | 2 | 3 | 3 | 6 | ▂▇▇▂▃ |
| Antigüedad | 0 | 1 | 7.01 | 6.13 | 0 | 3 | 5 | 9 | 40 | ▇▂▁▁▁ |
| Antigüedad_Cargo | 0 | 1 | 4.23 | 3.62 | 0 | 2 | 3 | 7 | 18 | ▇▃▂▁▁ |
| Años_ultima_promoción | 0 | 1 | 2.19 | 3.22 | 0 | 0 | 1 | 3 | 15 | ▇▁▁▁▁ |
| Años_acargo_con_mismo_jefe | 0 | 1 | 4.12 | 3.57 | 0 | 2 | 3 | 7 | 17 | ▇▂▅▁▁ |
Se seleccionan las variables más relevantes para el cálculo de la rotación del cargo:
Viaje de Negocios: Los viajes pueden ser un incentivo si permiten crecimiento profesional, aprendizaje y networking. Sin embargo, si son muy frecuentes y afectan la vida personal, pueden generar desgaste. Evaluar esta variable ayuda a medir el nivel de satisfacción del empleado con este componente.
Horas_Extra: Trabajar horas adicionales puede indicar compromiso, pero si es excesivo, afecta el equilibrio vida-trabajo y genera desgaste laboral. Medir esta variable ayuda a saber si el empleado está sobrecargado o si se siente recompensado por el tiempo extra.
Satisfacción_Ambiental: Si el entorno es incómodo o inseguro, puede generar desmotivación, ausentismo e incluso problemas de salud, aumentando el riesgo de que el empleado busque otro empleo.
Ingreso_Mensual: El salario es uno de los factores principales de retención. Ingresos competitivos motivan a los empleados a quedarse, mientras que salarios bajos pueden impulsar la búsqueda de mejores oportunidades.
Años_ultima_promoción: La percepción de crecimiento y desarrollo profesional es fundamental. Si han pasado muchos años desde la última promoción, el empleado podría sentir estancamiento y considerar otras opciones. Empresas que ofrecen crecimiento continuo tienden a retener mejor su talento.
Antigüedad_Cargo: Si el empleado ha estado muchos años en el mismo cargo sin ascenso ni cambios de responsabilidades, puede sentir estancamiento profesional, lo que aumenta el riesgo de rotación.
# Crear tabla de frecuencias
conteo <- table(df$Rotación)
total <- sum(conteo)
porcentaje <- round((conteo / total) * 100, 1) # porcentaje con 1 decimal
# Crear barplot y guardar posiciones
bp <- barplot(
conteo,
main = "Distribución Variable Rotación",
col = c("skyblue", "orange"),
xlab = "Rotación",
ylab = "Número de empleados",
ylim = c(0, max(conteo) * 1.2) # deja espacio para el texto arriba
)
# Agregar texto con totales y porcentajes
text(
x = bp,
y = conteo,
labels = paste0(conteo, " (", porcentaje, "%)"), # "número (porcentaje%)"
pos = 3,
cex = 0.8,
col = "black"
)
par(mfrow = c(1, 3), oma = c(0, 0, 3, 0))
hist(rotacion$Ingreso_Mensual,
main = "Ingreso Mensual",
xlab = "Ingreso",
col = "skyblue")
# Histograma de Años Última Promoción
hist(rotacion$Años_ultima_promoción,
main = "Años Última Promoción",
xlab = "Años",
col = "orange")
# Histograma de Antigüedad en el Cargo
hist(rotacion$Antigüedad_Cargo,
main = "Antigüedad en el Cargo",
xlab = "Años",
col = "lightgreen")
mtext("Histograma variables cualitativas", outer = TRUE, cex = 1.5, font = 2)
par(mfrow = c(1, 2), oma = c(0, 0, 3, 0))
datos_num <- df[, c("Años_ultima_promoción", "Antigüedad_Cargo")]
boxplot(df$Ingreso_Mensual,
names = "Ingreso Mensual", # <<< aquí agregamos la etiqueta
col = "skyblue",
notch = TRUE,
outline = TRUE,
cex.axis = 0.7,
cex.lab = 0.8,
las = 2,
main = "Ingreso mensual")
datos_num <- df[, c("Años_ultima_promoción", "Antigüedad_Cargo")]
# Boxplots múltiples
boxplot(datos_num,
names = c("Años ultima promoción", "Antigüedad Cargo"),
col = c( "orange","lightgreen"),
notch = TRUE,
outline = TRUE,
cex.axis = 0.7,
cex.lab = 0.8,
las = 1,
main = "Variables de tiempo")
# Boxplot de ingreso mensual con etiqueta en X
# Título general
mtext("Boxplots de variables cuantitativas", outer = TRUE, cex = 1.5, font = 2)
conteo2 <- table(df$`Viaje de Negocios`)
total2 <- sum(conteo2)
porcentaje2 <- round((conteo2 / total2) * 100, 1)
# Crear etiquetas con valor y porcentaje
etiquetas <- paste0(names(conteo2), " (", conteo2, ", ", porcentaje2, "%)")
# Graficar gráfico de pastel
pie(conteo2,
labels = etiquetas,
col = c("skyblue", "orange", "lightgreen"),
main = "Distribución variable Viaje de Negocios")
# Calcular conteos y porcentajes
conteo3 <- table(df$Horas_Extra)
total3 <- sum(conteo3)
porcentaje3 <- round((conteo3 / total3) * 100, 1)
# Crear etiquetas con valor y porcentaje
etiquetas <- paste0(names(conteo3), " (", conteo3, ", ", porcentaje3, "%)")
# Graficar gráfico de pastel
pie(conteo3,
labels = etiquetas,
col = c("skyblue", "orange"),
main = "Distribución de Horas Extras")
conteo3 <- table(df$Satisfacción_Ambiental)
total3 <- sum(conteo3)
porcentaje3 <- round((conteo3 / total3) * 100, 1)
# Crear barplot y guardar posiciones en 'bp'
bp <- barplot(conteo3,
col = c("skyblue", "orange","lightgreen", "lightyellow"),
xlab = "Satisfacción Ambiental",
ylab = "Número de empleados",
ylim = c(0, max(conteo3) * 1.2),
main = "Distribución variable Satisfacción Ambiental")
# Agregar conteo y porcentaje encima de cada barra
text(x = bp,
y = conteo3,
labels = paste0(conteo3, " (", porcentaje3, "%)"),
pos = 3,
cex = 0.8,
col = "black")
Observaciones:
La variable predictora presenta una distribución desbalanceada (84% en la categoría mayoritaria frente a 16% en la minoritaria). Este desbalance puede generar sesgos en el modelo predictivo, ya que el algoritmo tenderá a aprender más de la categoría mayoritaria y a subestimar la importancia de la minoritaria. Para mitigar este efecto, es recomendable aplicar una técnica de re-muestreo que permita equilibrar las clases y mejorar la capacidad del modelo para generalizar y detectar correctamente ambas categorías.
El 71% de los empleados reporta realizar horas extra para cumplir con sus responsabilidades laborales. Aunque estas horas suelen estar remuneradas, su alta frecuencia puede generar fatiga, afectar el equilibrio trabajo–vida personal y convertirse en un factor de riesgo para la rotación de personal, al impactar la satisfacción laboral y la motivación a largo plazo.
La satisfacción ambiental presenta una distribución relativamente equilibrada entre empleados satisfechos (30.8%) y muy satisfechos (30.3%), sumando más del 61% de percepciones positivas. Sin embargo, un 38.8% de los empleados manifiesta insatisfacción (19.5% insatisfechos y 19.3% muy insatisfechos), lo que representa un grupo considerable que podría afectar el clima organizacional y el compromiso laboral.
El 71% de los empleados reporta que rara vez ha realizado un viaje laboral. Este porcentaje representa la mayoría de la población, lo que indica que la oportunidad de viajar no es exclusiva de un grupo reducido de empleados, sino que es una experiencia relativamente común y accesible dentro de la organización.
la mayoría de empleados gana en el rango bajo (entre 2,000 y 6,000). Hay algunos empleados con ingresos muy altos (colas largas a la derecha), lo que puede indicar puestos directivos o excepciones salariales.
La distribución en la variable “Años Última Promoción” esta altamente concentrada en valores bajos (0 a 2 años). Esto indica que la mayoría de las promociones han ocurrido recientemente o que una gran parte de empleados no ha recibido promoción desde su ingreso.
La variable “Antigüedad en el Cargo” posee una distribución asimétrica, con mayoría de empleados entre 0 y 5 años de antigüedad. Pocos empleados tienen más de 10 años en el cargo, lo que podría indicar que las posiciones tienden a renovarse o que hay movilidad interna.
3.1 Ingresos mensuales por rotación
aggregate(Ingreso_Mensual ~ Rotación, data = df,
FUN = function(x) c(media = mean(x), sd = sd(x), mediana = median(x)))
Rotación Ingreso_Mensual.media Ingreso_Mensual.sd Ingreso_Mensual.mediana
1 0 6832.740 4818.208 5204.000
2 1 4787.093 3640.210 3202.000
boxplot(Ingreso_Mensual ~ Rotación, data = df,
main = "Ingresos mensuales por rotación",
xlab = "Rotación (0=No, 1=Sí)",
ylab = "Ingresos mensuales",
col = c("skyblue", "orange"))
shapiro.test(df$Ingreso_Mensual[df$Rotación==0])
Shapiro-Wilk normality test
data: df$Ingreso_Mensual[df$Rotación == 0]
W = 0.83413, p-value < 2.2e-16
shapiro.test(df$Ingreso_Mensual[df$Rotación==1])
Shapiro-Wilk normality test
data: df$Ingreso_Mensual[df$Rotación == 1]
W = 0.7799, p-value < 2.2e-16
wilcox.test(Ingreso_Mensual ~ Rotación, data = df)
Wilcoxon rank sum test with continuity correction
data: Ingreso_Mensual by Rotación
W = 191601, p-value = 2.951e-14
alternative hypothesis: true location shift is not equal to 0
Observaciones:
No cumple el supuesto de normalidad, por lo que no es recomendable usar un t-test (prueba paramétrica), la alternativa es la pueba U Mann–Whitney.
Los empleados que no rotaron presentaron una mediana de ingresos
mensuales significativamente mayor (Mdn = 5,204) en comparación con los
empleados que rotaron (Mdn = 3,202). La prueba de Mann–Whitney indicó
que esta diferencia es estadísticamente significativa, W = 191,601, p
< 0.001, lo que sugiere que menores ingresos están asociados con
mayor probabilidad de rotación.
3.2 Años ultima promoción por rotación
aggregate(Años_ultima_promoción ~ Rotación, data = df,
FUN = function(x) c(media = mean(x), sd = sd(x), mediana = median(x)))
Rotación Años_ultima_promoción.media Años_ultima_promoción.sd
1 0 2.234388 3.234762
2 1 1.945148 3.153077
Años_ultima_promoción.mediana
1 1.000000
2 1.000000
boxplot(Años_ultima_promoción ~ Rotación, data = df,
main = "Años ultima promoción por rotación",
xlab = "Rotación (0=No, 1=Sí)",
ylab = "Años ultima promoción",
col = c("skyblue", "orange"))
shapiro.test(df$Años_ultima_promoción[df$Rotación==0])
Shapiro-Wilk normality test
data: df$Años_ultima_promoción[df$Rotación == 0]
W = 0.711, p-value < 2.2e-16
shapiro.test(df$Años_ultima_promoción[df$Rotación==1])
Shapiro-Wilk normality test
data: df$Años_ultima_promoción[df$Rotación == 1]
W = 0.66041, p-value < 2.2e-16
wilcox.test(Años_ultima_promoción ~ Rotación, data = df)
Wilcoxon rank sum test with continuity correction
data: Años_ultima_promoción by Rotación
W = 157847, p-value = 0.04118
alternative hypothesis: true location shift is not equal to 0
Observaciones:
3.3 Antigüedad Cargo por
rotación
aggregate(Antigüedad_Cargo ~ Rotación, data = df,
FUN = function(x) c(media = mean(x), sd = sd(x), mediana = median(x)))
Rotación Antigüedad_Cargo.media Antigüedad_Cargo.sd Antigüedad_Cargo.mediana
1 0 4.484185 3.649402 3.000000
2 1 2.902954 3.174827 2.000000
boxplot(Antigüedad_Cargo ~ Rotación, data = df,
main = "Antigüedad Cargo por rotación",
xlab = "Rotación (0=No, 1=Sí)",
ylab = "Antigüedad Cargo",
col = c("skyblue", "orange"))
shapiro.test(df$Antigüedad_Cargo[df$Rotación==0])
Shapiro-Wilk normality test
data: df$Antigüedad_Cargo[df$Rotación == 0]
W = 0.9067, p-value < 2.2e-16
shapiro.test(df$Antigüedad_Cargo[df$Rotación==1])
Shapiro-Wilk normality test
data: df$Antigüedad_Cargo[df$Rotación == 1]
W = 0.81847, p-value = 6.261e-16
wilcox.test(Antigüedad_Cargo ~ Rotación, data = df)
Wilcoxon rank sum test with continuity correction
data: Antigüedad_Cargo by Rotación
W = 187007, p-value = 4.43e-12
alternative hypothesis: true location shift is not equal to 0
Observaciones:
3.4 Viaje de Negocios por rotación
table(df$`Viaje de Negocios`,df$Rotación)
0 1
Frecuentemente 208 69
No_Viaja 138 12
Raramente 887 156
prop.table(table(df$`Viaje de Negocios`,df$Rotación), margin = 1)
0 1
Frecuentemente 0.7509025 0.2490975
No_Viaja 0.9200000 0.0800000
Raramente 0.8504314 0.1495686
chisq.test(table(df$`Viaje de Negocios`,df$Rotación))
Pearson's Chi-squared test
data: table(df$`Viaje de Negocios`, df$Rotación)
X-squared = 24.182, df = 2, p-value = 5.609e-06
# o si hay celdas con conteos bajos:
fisher.test(table(df$`Viaje de Negocios`,df$Rotación))
Fisher's Exact Test for Count Data
data: table(df$`Viaje de Negocios`, df$Rotación)
p-value = 7.454e-06
alternative hypothesis: two.sided
Observaciones:
3.5 Horas Extras por rotación
table(df$Horas_Extra,df$Rotación)
0 1
No 944 110
Si 289 127
prop.table(table(df$Horas_Extra,df$Rotación), margin = 1)
0 1
No 0.8956357 0.1043643
Si 0.6947115 0.3052885
chisq.test(table(df$Horas_Extra,df$Rotación))
Pearson's Chi-squared test with Yates' continuity correction
data: table(df$Horas_Extra, df$Rotación)
X-squared = 87.564, df = 1, p-value < 2.2e-16
# o si hay celdas con conteos bajos:
fisher.test(table(df$Horas_Extra,df$Rotación))
Fisher's Exact Test for Count Data
data: table(df$Horas_Extra, df$Rotación)
p-value < 2.2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.799096 5.078460
sample estimates:
odds ratio
3.767353
Observaciones:
3.6 Satisfacción Ambiental por rotación
table(df$Satisfacción_Ambiental,df$Rotación)
0 1
Insatisfecho 244 43
Muy insatisfecho 212 72
Muy satisfecho 386 60
Satisfecho 391 62
prop.table(table(df$Satisfacción_Ambiental,df$Rotación), margin = 1)
0 1
Insatisfecho 0.8501742 0.1498258
Muy insatisfecho 0.7464789 0.2535211
Muy satisfecho 0.8654709 0.1345291
Satisfecho 0.8631347 0.1368653
chisq.test(table(df$Satisfacción_Ambiental,df$Rotación))
Pearson's Chi-squared test
data: table(df$Satisfacción_Ambiental, df$Rotación)
X-squared = 22.504, df = 3, p-value = 5.123e-05
# o si hay celdas con conteos bajos:
fisher.test(table(df$Satisfacción_Ambiental,df$Rotación))
Fisher's Exact Test for Count Data
data: table(df$Satisfacción_Ambiental, df$Rotación)
p-value = 0.0001245
alternative hypothesis: two.sided
Observaciones:
df$Rotación <- as.factor(df$Rotación)
df$Horas_Extra <- as.factor(df$Horas_Extra)
df$`Viaje de Negocios` <- as.factor(df$`Viaje de Negocios`)
df$Satisfacción_Ambiental <- as.factor(df$Satisfacción_Ambiental)
modelo_logit <- glm(Rotación ~ `Viaje de Negocios` + Horas_Extra +
Satisfacción_Ambiental + Ingreso_Mensual +
Años_ultima_promoción + Antigüedad_Cargo,
data =df,
family = binomial,weights = ifelse(df$Rotación == 1, 2, 1), )
# Resumen del modelo
summary(modelo_logit)
Call:
glm(formula = Rotación ~ `Viaje de Negocios` + Horas_Extra +
Satisfacción_Ambiental + Ingreso_Mensual + Años_ultima_promoción +
Antigüedad_Cargo, family = binomial, data = df, weights = ifelse(df$Rotación ==
1, 2, 1))
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.1182237 0.2073635 -0.570 0.569
`Viaje de Negocios`No_Viaja -1.3525099 0.2689874 -5.028 4.95e-07
`Viaje de Negocios`Raramente -0.5888057 0.1432803 -4.109 3.97e-05
Horas_ExtraSi 1.4851664 0.1259733 11.790 < 2e-16
Satisfacción_AmbientalMuy insatisfecho 0.8965583 0.1858571 4.824 1.41e-06
Satisfacción_AmbientalMuy satisfecho -0.2264860 0.1816254 -1.247 0.212
Satisfacción_AmbientalSatisfecho -0.0834388 0.1788658 -0.466 0.641
Ingreso_Mensual -0.0001226 0.0000181 -6.774 1.25e-11
Años_ultima_promoción 0.1377873 0.0255799 5.387 7.18e-08
Antigüedad_Cargo -0.1658890 0.0248239 -6.683 2.35e-11
(Intercept)
`Viaje de Negocios`No_Viaja ***
`Viaje de Negocios`Raramente ***
Horas_ExtraSi ***
Satisfacción_AmbientalMuy insatisfecho ***
Satisfacción_AmbientalMuy satisfecho
Satisfacción_AmbientalSatisfecho
Ingreso_Mensual ***
Años_ultima_promoción ***
Antigüedad_Cargo ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2016.8 on 1469 degrees of freedom
Residual deviance: 1659.9 on 1460 degrees of freedom
AIC: 1679.9
Number of Fisher Scoring iterations: 5
# Calcular Odds Ratios (para interpretar mejor los coeficientes)
exp(coef(modelo_logit))
(Intercept) `Viaje de Negocios`No_Viaja
0.8884973 0.2585904
`Viaje de Negocios`Raramente Horas_ExtraSi
0.5549897 4.4157000
Satisfacción_AmbientalMuy insatisfecho Satisfacción_AmbientalMuy satisfecho
2.4511525 0.7973305
Satisfacción_AmbientalSatisfecho Ingreso_Mensual
0.9199473 0.9998774
Años_ultima_promoción Antigüedad_Cargo
1.1477314 0.8471403
# Intervalos de confianza para los Odds Ratios
exp(confint(modelo_logit))
Waiting for profiling to be done...
2.5 % 97.5 %
(Intercept) 0.5908882 1.3330544
`Viaje de Negocios`No_Viaja 0.1499573 0.4317836
`Viaje de Negocios`Raramente 0.4192164 0.7354009
Horas_ExtraSi 3.4551418 5.6628159
Satisfacción_AmbientalMuy insatisfecho 1.7071781 3.5393285
Satisfacción_AmbientalMuy satisfecho 0.5587295 1.1394338
Satisfacción_AmbientalSatisfecho 0.6485588 1.3083438
Ingreso_Mensual 0.9998410 0.9999120
Años_ultima_promoción 1.0916117 1.2069147
Antigüedad_Cargo 0.8062411 0.8887028
Observaciones:
El modelo de regresión logística identificó varios factores que influyen significativamente en la probabilidad de rotación de empleados:
Horas Extra es el predictor más relevante: los empleados que realizan horas extra presentan 4,5 veces más oportunidad de rotar que quienes no las realizan, lo que sugiere que la sobrecarga laboral es un factor de riesgo crítico.
Años desde la última promoción tienen un efecto positivo moderado: cada año adicional sin promoción incrementa la oportunidad de rotación en 15 %, lo que evidencia la importancia de planes de desarrollo y ascensos.
Satisfacción Ambiental es determinante únicamente en casos de muy baja satisfacción: empleados muy insatisfechos tienen 2,4 veces más oportunidad de rotar que los insatisfechos. Sin embargo, niveles altos de satisfacción no mostraron un efecto estadísticamente significativo.
Ingreso mensual y la antiguedad en el cargo no mostraron un efecto significativo en este modelo.
Viajes de Negocios actúan como un factor protector cuando son pocos o inexistentes. Los empleados que raramente viajan tienen 0.54 veces la posibilidad de rotar que quienes no viajan.
# ----- 1. Probabilidades predichas -----
prob_pred <- predict(modelo_logit, type = "response")
# ----- 2. Curva ROC y AUC -----
roc_obj <- roc(df$Rotación, prob_pred)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_obj, col = "blue", lwd = 2, main = "Curva ROC")
auc(roc_obj)
Area under the curve: 0.7797
# ----- 3. Predicción binaria usando un umbral (0.5 por defecto) -----
pred_clase <- ifelse(prob_pred >= 0.5, 1, 0)
# ----- 4. Tabla de confusión -----
confusionMatrix(as.factor(pred_clase), as.factor(df$Rotación), positive = "1")
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 1131 147
1 102 90
Accuracy : 0.8306
95% CI : (0.8104, 0.8495)
No Information Rate : 0.8388
P-Value [Acc > NIR] : 0.812818
Kappa : 0.3217
Mcnemar's Test P-Value : 0.005297
Sensitivity : 0.37975
Specificity : 0.91727
Pos Pred Value : 0.46875
Neg Pred Value : 0.88498
Prevalence : 0.16122
Detection Rate : 0.06122
Detection Prevalence : 0.13061
Balanced Accuracy : 0.64851
'Positive' Class : 1
Observaciones:
Matriz de confución
TN (1131): empleados que no rotaron y el modelo predijo correctamente.
TP (90): empleados que rotaron y el modelo detectó correctamente.
FP (102): empleados que no rotaron pero el modelo los marcó como si fueran a rotar (falsas alarmas).
FN (147): empleados que sí rotaron pero el modelo no los detectó (falsos negativos).
nuevo_empleado1 <- data.frame(
`Viaje de Negocios` = factor("Raramente", levels = levels(df$`Viaje de Negocios`)),
Horas_Extra = factor("No", levels = levels(df$Horas_Extra)),
Satisfacción_Ambiental = factor("Muy insatisfecho",levels = levels(df$Satisfacción_Ambiental)),
Ingreso_Mensual = 10000, # valor numérico aproximado
Años_ultima_promoción = 4,
Antigüedad_Cargo = 7)
colnames(nuevo_empleado1)[1] <- "Viaje de Negocios"
kable(nuevo_empleado1, caption = "Tabla de Empleado 1", align = "c")
| Viaje de Negocios | Horas_Extra | Satisfacción_Ambiental | Ingreso_Mensual | Años_ultima_promoción | Antigüedad_Cargo |
|---|---|---|---|---|---|
| Raramente | No | Muy insatisfecho | 10000 | 4 | 7 |
prob_rotacion <- predict(modelo_logit, newdata = nuevo_empleado1, type = "response")
prob_rotacion
1
0.1615642
nuevo_empleado2 <- data.frame(
`Viaje de Negocios` = factor("Raramente", levels = levels(df$`Viaje de Negocios`)),
Horas_Extra = factor("Si", levels = levels(df$Horas_Extra)),
Satisfacción_Ambiental = factor("Muy insatisfecho",levels = levels(df$Satisfacción_Ambiental)),
Ingreso_Mensual = 10000, # valor numérico aproximado
Años_ultima_promoción = 4,
Antigüedad_Cargo = 7)
colnames(nuevo_empleado2)[1] <- "Viaje de Negocios"
kable(nuevo_empleado2, caption = "Tabla de Empleado 2", align = "c")
| Viaje de Negocios | Horas_Extra | Satisfacción_Ambiental | Ingreso_Mensual | Años_ultima_promoción | Antigüedad_Cargo |
|---|---|---|---|---|---|
| Raramente | Si | Muy insatisfecho | 10000 | 4 | 7 |
prob_rotacion <- predict(modelo_logit, newdata = nuevo_empleado2,type = "response")
prob_rotacion
1
0.4597203
nuevo_empleado3 <- data.frame(
`Viaje de Negocios` = factor("Raramente", levels = levels(df$`Viaje de Negocios`)),
Horas_Extra = factor("Si", levels = levels(df$Horas_Extra)),
Satisfacción_Ambiental = factor("Muy insatisfecho",levels = levels(df$Satisfacción_Ambiental)),
Ingreso_Mensual = 5000, # valor numérico aproximado
Años_ultima_promoción = 4,
Antigüedad_Cargo = 7)
colnames(nuevo_empleado3)[1] <- "Viaje de Negocios"
kable(nuevo_empleado3, caption = "Tabla de Empleado 3", align = "c")
| Viaje de Negocios | Horas_Extra | Satisfacción_Ambiental | Ingreso_Mensual | Años_ultima_promoción | Antigüedad_Cargo |
|---|---|---|---|---|---|
| Raramente | Si | Muy insatisfecho | 5000 | 4 | 7 |
prob_rotacion <- predict(modelo_logit, newdata = nuevo_empleado3,type = "response")
prob_rotacion
1
0.611014
Observaciones:
Empleado 1 (16%)
Baja probabilidad de rotación.
Aunque está muy insatisfecho con el ambiente, no hace horas extra y tiene un salario relativamente alto, lo que podría estar funcionando como factor de retención.
No requiere intervención urgente, pero conviene mejorar el ambiente laboral para prevenir problemas futuros.
Empleado 2 (46%)
Probabilidad moderada de rotación.
La diferencia principal frente al Empleado 1 es que hace horas extra, lo que aumenta el riesgo.
Recomendación: evaluar su carga de trabajo y compensación para evitar desgaste.
Empleado 3 (61%)
Alta probabilidad de rotación.
Además de hacer horas extra y estar insatisfecho, tiene un ingreso más bajo, lo que es un factor de riesgo fuerte.
Debe priorizarse para intervención: revisión salarial, plan de desarrollo profesional y mejora de condiciones laborales.
7.1 Usar el modelo de regresión logística para identificar empleados con probabilidad ≥ 0.5 y diseñar intervenciones personalizadas.
7.2 Las horas extras son la variable más relevante, con 4,5 veces más de oportunidad de rotar que quienes no las realizan; se propone optimizar carga laboral y procesos internos para evitar sobrecarga.
7.3 Espacios de bienestar como pausas activas, ergonomía, programas de salud mental pueden contribuir a que la variable satisfacción laboral disminuya a su nivel más bajo, aumentando la posibilidad de rotar (2,4 veces más oportunidad de rotar).
7.4 Monitorear la variable años desde la última promoción, con el fin de otorgar ascenso a los empleados más calificados y evitar que, cada año que pase, se aumente en 15% la posibilidad de rotar.
7.5 Aunque en el modelo el ingreso salarial no es una variable con un peso significativo, al comparar la simulación del empleado 2 y 3, revela que esta variable requiere atención y vigilancia.