Carga de datos
# Instalar solo si hace falta
packs <- c("paqueteMODELOS", "dplyr", "ggplot2", "pROC", "broom", "knitr", "scales", "forcats")
instalar <- packs[!packs %in% installed.packages()[, "Package"]]
if(length(instalar) > 0) install.packages(instalar)
library(paqueteMODELOS)
library(dplyr)
library(ggplot2)
library(pROC)
library(broom)
library(knitr)
library(scales)
library(forcats)
library(tidyr)
data("rotacion")
# Variable binaria para el modelo
rotacion <- rotacion %>%
mutate(
Rotacion_bin = ifelse(Rotación == "Si", 1, 0),
Horas_Extra = as.factor(Horas_Extra),
Departamento = as.factor(Departamento),
Estado_Civil = as.factor(Estado_Civil),
Rotación = as.factor(Rotación)
)
El objetivo de este análisis es comprender los factores que influyen en la rotación de empleados y estimar la probabilidad de que un trabajador cambie de cargo en el siguiente período. Para ello, se realiza un proceso que incluye selección de variables, análisis univariado, análisis bivariado, estimación de un modelo de regresión logística, evaluación predictiva mediante curva ROC y AUC, y un ejercicio de predicción para un individuo hipotético.
La variable respuesta es Rotación, codificada como 1 si el empleado rota y 0 si no rota. A partir de esta variable se analizan seis covariables potencialmente explicativas: tres categóricas y tres cuantitativas, elegidas por su relevancia conceptual en la gestión del talento humano.
En esta sección se carga la base de datos rotacion del paquete paqueteMODELOS, se verifica su estructura y se realiza una primera lectura general del número de registros, variables y proporción de empleados con rotación. Esto permite contextualizar el análisis antes de formular hipótesis y construir el modelo.
glimpse(rotacion)
## Rows: 1,470
## Columns: 25
## $ Rotación <fct> Si, No, Si, No, No, No, No, 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 <fct> Ventas, IyD, IyD, 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 <fct> Soltero, Casado, Soltero, Casado, 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 <fct> Si, No, Si, Si, No, No, Si, No, No, No, No…
## $ 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, …
## $ Rotacion_bin <dbl> 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
n_obs <- nrow(rotacion)
n_var <- ncol(rotacion)
rot_si <- sum(rotacion$Rotación == "Si")
rot_no <- sum(rotacion$Rotación == "No")
prop_si <- mean(rotacion$Rotación == "Si")
De acuerdo con el enunciado, se deben seleccionar tres variables categóricas y tres variables cuantitativas distintas de la variable respuesta. La selección debe ir acompañada de una justificación conceptual y de una hipótesis sobre el tipo de relación esperada entre cada variable y la rotación.
Se espera que los empleados que trabajan horas extra tengan una mayor probabilidad de rotación. La lógica detrás de esta hipótesis es que una carga laboral adicional puede aumentar el desgaste, el estrés y la insatisfacción laboral.
Se espera que la rotación varíe entre departamentos. Esto puede deberse a diferencias en la presión laboral, el estilo de supervisión, el tipo de funciones o las oportunidades de crecimiento dentro de cada área.
Se espera que los empleados solteros presenten una mayor probabilidad de rotación, al tener potencialmente mayor flexibilidad para cambiar de rol o empleo frente a quienes tienen mayores responsabilidades familiares.
Se espera una relación negativa entre la edad y la rotación. En términos generales, los trabajadores más jóvenes suelen mostrar mayor movilidad laboral que aquellos con mayor edad y trayectoria.
Se espera una relación negativa entre el ingreso mensual y la rotación. Una mejor remuneración puede representar un incentivo para permanecer en el cargo.
Se espera una relación negativa entre la antigüedad en el cargo y la rotación. Una mayor permanencia en el mismo rol puede reflejar adaptación, experiencia y estabilidad.
El análisis univariado permite caracterizar cada variable por separado. Para las variables cualitativas se utilizan tablas de frecuencia y gráficos de barras; para las cuantitativas se usan medidas resumen y gráficos de distribución. También se incluye la interpretación de la variable respuesta rotación, tal como exige el enunciado.
tab_rot <- rotacion %>%
count(Rotación) %>%
mutate(Proporción = n / sum(n))
kable(tab_rot, digits = 3, caption = "Distribución de la variable Rotación")
| Rotación | n | Proporción |
|---|---|---|
| No | 1233 | 0.839 |
| Si | 237 | 0.161 |
ggplot(rotacion, aes(x = Rotación, fill = Rotación)) +
geom_bar(width = 0.65, alpha = 0.9) +
geom_text(stat = "count", aes(label = after_stat(count)), vjust = -0.4, size = 4) +
scale_y_continuous(expand = expansion(mult = c(0, .08))) +
labs(
title = "Distribución de la rotación de empleados",
x = "Rotación",
y = "Frecuencia"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "none")
La distribución de la variable rotación evidencia que la mayoría de los empleados no cambia de cargo dentro del período analizado. En particular, el 83.9% de los empleados permanece en su posición actual, mientras que el 16.1% presenta rotación.
Este resultado sugiere que la organización presenta un nivel relativamente alto de estabilidad laboral. Sin embargo, la proporción de empleados que sí rotan no es despreciable, lo que justifica el desarrollo de un modelo predictivo que permita identificar de manera anticipada a aquellos individuos con mayor probabilidad de cambio.
Adicionalmente, se observa un desbalance en la variable respuesta, lo cual es relevante en el contexto del modelamiento, ya que podría influir en la capacidad del modelo para identificar correctamente los casos de rotación.
kable(as.data.frame(table(rotacion$Horas_Extra)), caption = "Frecuencias de Horas_Extra")
| Var1 | Freq |
|---|---|
| No | 1054 |
| Si | 416 |
kable(as.data.frame(table(rotacion$Departamento)), caption = "Frecuencias de Departamento")
| Var1 | Freq |
|---|---|
| IyD | 961 |
| RH | 63 |
| Ventas | 446 |
kable(as.data.frame(table(rotacion$Estado_Civil)), caption = "Frecuencias de Estado_Civil")
| Var1 | Freq |
|---|---|
| Casado | 673 |
| Divorciado | 327 |
| Soltero | 470 |
g1 <- ggplot(rotacion, aes(x = Horas_Extra, fill = Horas_Extra)) +
geom_bar(alpha = 0.9) +
labs(title = "Distribución de Horas_Extra", x = NULL, y = "Frecuencia") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
g2 <- ggplot(rotacion, aes(x = fct_infreq(Departamento), fill = Departamento)) +
geom_bar(alpha = 0.9) +
labs(title = "Distribución de Departamento", x = NULL, y = "Frecuencia") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
g3 <- ggplot(rotacion, aes(x = Estado_Civil, fill = Estado_Civil)) +
geom_bar(alpha = 0.9) +
labs(title = "Distribución de Estado_Civil", x = NULL, y = "Frecuencia") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
print(g1)
print(g2)
print(g3)
En relación con la variable Horas_Extra, se observa que la mayoría de los empleados no realiza horas adicionales (1054 casos), mientras que una proporción menor sí lo hace (416 casos). Esto indica que, en general, la carga laboral adicional no es una condición predominante en la organización, aunque existe un grupo relevante expuesto a este factor.
Para la variable Departamento, se evidencia una alta concentración de empleados en el área de I+D (961 casos), seguida por Ventas (446 casos) y en menor proporción Recursos Humanos (63 casos). Esta distribución desigual es importante, ya que podría influir en los resultados posteriores, especialmente en el análisis bivariado, debido a la diferencia en tamaños de grupo.
En cuanto al Estado Civil, la mayor proporción corresponde a empleados casados (673), seguida de solteros (470) y divorciados (327). Esta variable presenta una distribución relativamente equilibrada en comparación con otras, lo que facilita su análisis en relación con la rotación.
En conjunto, estas variables permiten caracterizar el contexto laboral y personal de los empleados, lo cual resulta fundamental para comprender posibles patrones asociados a la rotación en etapas posteriores del análisis.
resumen_cuant <- rotacion %>%
summarise(
Edad_media = mean(Edad, na.rm = TRUE),
Edad_sd = sd(Edad, na.rm = TRUE),
Edad_min = min(Edad, na.rm = TRUE),
Edad_max = max(Edad, na.rm = TRUE),
Ingreso_media = mean(Ingreso_Mensual, na.rm = TRUE),
Ingreso_sd = sd(Ingreso_Mensual, na.rm = TRUE),
Ingreso_min = min(Ingreso_Mensual, na.rm = TRUE),
Ingreso_max = max(Ingreso_Mensual, na.rm = TRUE),
Antiguedad_media = mean(Antigüedad_Cargo, na.rm = TRUE),
Antiguedad_sd = sd(Antigüedad_Cargo, na.rm = TRUE),
Antiguedad_min = min(Antigüedad_Cargo, na.rm = TRUE),
Antiguedad_max = max(Antigüedad_Cargo, na.rm = TRUE)
)
kable(resumen_cuant, digits = 2, caption = "Medidas resumen de variables cuantitativas")
| Edad_media | Edad_sd | Edad_min | Edad_max | Ingreso_media | Ingreso_sd | Ingreso_min | Ingreso_max | Antiguedad_media | Antiguedad_sd | Antiguedad_min | Antiguedad_max |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 36.92 | 9.14 | 18 | 60 | 6502.93 | 4707.96 | 1009 | 19999 | 4.23 | 3.62 | 0 | 18 |
p1 <- ggplot(rotacion, aes(x = Edad)) +
geom_histogram(bins = 20, alpha = 0.9) +
labs(title = "Distribución de Edad", x = "Edad", y = "Frecuencia") +
theme_minimal(base_size = 12)
p2 <- ggplot(rotacion, aes(x = Ingreso_Mensual)) +
geom_histogram(bins = 25, alpha = 0.9) +
labs(title = "Distribución de Ingreso_Mensual", x = "Ingreso mensual", y = "Frecuencia") +
theme_minimal(base_size = 12)
p3 <- ggplot(rotacion, aes(x = Antigüedad_Cargo)) +
geom_histogram(bins = 20, alpha = 0.9) +
labs(title = "Distribución de Antigüedad_Cargo", x = "Antigüedad en el cargo", y = "Frecuencia") +
theme_minimal(base_size = 12)
print(p1)
print(p2)
print(p3)
La variable Edad presenta una media de aproximadamente 36.9 años, con valores que oscilan entre 18 y 60 años. La distribución muestra una mayor concentración en edades intermedias, lo que indica que la organización cuenta principalmente con una fuerza laboral adulta, en etapas productivas consolidadas.
En el caso del Ingreso_Mensual, se observa una alta dispersión, con valores que van desde aproximadamente 1000 hasta cerca de 20000. Esta variabilidad sugiere la existencia de diferentes niveles jerárquicos o roles dentro de la organización, lo cual puede tener implicaciones importantes en la rotación, especialmente en términos de incentivos económicos.
Por su parte, la Antigüedad en el cargo presenta una distribución sesgada hacia valores bajos, lo que indica que una proporción considerable de empleados tiene poco tiempo en su posición actual. Esto podría reflejar dinámicas de movilidad interna o reciente incorporación de personal.
En conjunto, estas variables muestran heterogeneidad en las condiciones laborales y personales de los empleados, lo que justifica su inclusión en el modelo como posibles factores explicativos de la rotación.
En este punto se estudia la relación entre la variable respuesta Rotación y cada una de las variables seleccionadas. Para las variables categóricas se utiliza la prueba chi-cuadrado de independencia. Para las cuantitativas se realiza comparación de medias entre empleados que rotan y empleados que no rotan. Este paso es clave para identificar variables determinantes y contrastar las hipótesis planteadas.
chi_horas <- chisq.test(table(rotacion$Rotación, rotacion$Horas_Extra))
chi_depto <- chisq.test(table(rotacion$Rotación, rotacion$Departamento))
chi_estado <- chisq.test(table(rotacion$Rotación, rotacion$Estado_Civil))
tabla_chi <- tibble::tibble(
Variable = c("Horas_Extra", "Departamento", "Estado_Civil"),
`Chi-cuadrado` = c(chi_horas$statistic, chi_depto$statistic, chi_estado$statistic),
`p-valor` = c(chi_horas$p.value, chi_depto$p.value, chi_estado$p.value)
)
kable(tabla_chi, digits = 4, caption = "Pruebas chi-cuadrado para variables categóricas")
| Variable | Chi-cuadrado | p-valor |
|---|---|---|
| Horas_Extra | 87.5643 | 0.0000 |
| Departamento | 10.7960 | 0.0045 |
| Estado_Civil | 46.1637 | 0.0000 |
b1 <- ggplot(rotacion, aes(x = Horas_Extra, fill = Rotación)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Rotación según Horas_Extra", x = NULL, y = "Proporción") +
theme_minimal(base_size = 12)
b2 <- ggplot(rotacion, aes(x = fct_infreq(Departamento), fill = Rotación)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Rotación según Departamento", x = NULL, y = "Proporción") +
theme_minimal(base_size = 12)
b3 <- ggplot(rotacion, aes(x = Estado_Civil, fill = Rotación)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Rotación según Estado_Civil", x = NULL, y = "Proporción") +
theme_minimal(base_size = 12)
print(b1)
print(b2)
print(b3)
Para evaluar la relación entre la variable respuesta Rotación y las variables categóricas seleccionadas, se aplicó la prueba de independencia chi-cuadrado. En todos los casos analizados se obtuvieron p-valores inferiores a 0.05, lo que indica evidencia estadísticamente significativa de asociación entre estas variables y la rotación de empleados.
En el caso de Horas_Extra, se obtiene un estadístico chi-cuadrado de 87.56 con un p-valor cercano a cero, lo que indica una fuerte relación con la rotación. A partir del gráfico, se observa que los empleados que realizan horas extra presentan una mayor proporción de rotación en comparación con aquellos que no lo hacen, lo que confirma la hipótesis planteada.
Para la variable Departamento, el resultado también es significativo (p-valor = 0.0045), lo que indica que la rotación no se distribuye de manera uniforme entre las áreas. En particular, el departamento de Ventas presenta una mayor proporción de rotación en comparación con I+D y Recursos Humanos, lo que respalda la hipótesis inicial.
En cuanto al Estado Civil, se observa una relación significativa (chi-cuadrado = 46.16, p-valor cercano a cero). Los empleados solteros presentan una mayor proporción de rotación frente a los casados y divorciados, lo cual es consistente con la hipótesis planteada.
En conjunto, los resultados evidencian que las variables categóricas analizadas influyen significativamente en la rotación, y que existe coherencia entre los hallazgos empíricos y las hipótesis definidas previamente.
tt_edad <- t.test(Edad ~ Rotación, data = rotacion)
tt_ingreso <- t.test(Ingreso_Mensual ~ Rotación, data = rotacion)
tt_ant <- t.test(Antigüedad_Cargo ~ Rotación, data = rotacion)
tabla_t <- tibble::tibble(
Variable = c("Edad", "Ingreso_Mensual", "Antigüedad_Cargo"),
`Estadístico t` = c(tt_edad$statistic, tt_ingreso$statistic, tt_ant$statistic),
`p-valor` = c(tt_edad$p.value, tt_ingreso$p.value, tt_ant$p.value)
)
kable(tabla_t, digits = 4, caption = "Pruebas de comparación de medias")
| Variable | Estadístico t | p-valor |
|---|---|---|
| Edad | 5.8291 | 0 |
| Ingreso_Mensual | 7.4826 | 0 |
| Antigüedad_Cargo | 6.8471 | 0 |
q1 <- ggplot(rotacion, aes(x = Rotación, y = Edad, fill = Rotación)) +
geom_boxplot(alpha = 0.85) +
labs(title = "Edad según Rotación", x = NULL, y = "Edad") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
q2 <- ggplot(rotacion, aes(x = Rotación, y = Ingreso_Mensual, fill = Rotación)) +
geom_boxplot(alpha = 0.85) +
labs(title = "Ingreso_Mensual según Rotación", x = NULL, y = "Ingreso mensual") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
q3 <- ggplot(rotacion, aes(x = Rotación, y = Antigüedad_Cargo, fill = Rotación)) +
geom_boxplot(alpha = 0.85) +
labs(title = "Antigüedad_Cargo según Rotación", x = NULL, y = "Antigüedad en el cargo") +
theme_minimal(base_size = 12) +
theme(legend.position = "none")
print(q1)
print(q2)
print(q3)
Para evaluar la relación entre las variables cuantitativas y la rotación, se realizaron pruebas de comparación de medias (prueba t) entre los empleados que rotan y aquellos que no lo hacen. En todos los casos analizados se obtuvieron p-valores cercanos a cero, lo que indica diferencias estadísticamente significativas entre los grupos.
En el caso de la Edad, se obtiene un estadístico t de 5.83 con un p-valor prácticamente nulo, lo que evidencia diferencias significativas entre los grupos. Este resultado sugiere que la edad influye en la rotación, siendo consistente con la hipótesis planteada de que los empleados más jóvenes tienden a rotar con mayor frecuencia.
Para el Ingreso_Mensual, se observa un estadístico t de 7.48 con un p-valor cercano a cero, indicando una diferencia significativa entre quienes rotan y quienes no. Este resultado respalda la hipótesis de que menores niveles de ingreso se asocian con una mayor probabilidad de rotación, evidenciando el papel de los incentivos económicos en la permanencia laboral.
En cuanto a la Antigüedad en el cargo, se obtiene un estadístico t de 6.85 con un p-valor prácticamente nulo, lo que confirma diferencias significativas entre los grupos. Esto sugiere que los empleados con menor antigüedad presentan mayor probabilidad de rotación, en línea con la hipótesis de que una mayor estabilidad en el cargo reduce la intención de cambio.
En conjunto, los resultados evidencian que las tres variables cuantitativas analizadas son determinantes en la rotación, y muestran coherencia con las hipótesis planteadas, lo que justifica su inclusión en el modelo de regresión logística.
La regresión logística permite modelar la probabilidad de rotación a partir de las seis covariables seleccionadas. En este contexto, el signo del coeficiente muestra la dirección de la relación y el p-valor indica si la covariable tiene un efecto estadísticamente significativo sobre la respuesta.
modelo <- glm(
Rotacion_bin ~ Horas_Extra + Departamento + Estado_Civil +
Edad + Ingreso_Mensual + Antigüedad_Cargo,
data = rotacion,
family = binomial
)
summary(modelo)
##
## Call:
## glm(formula = Rotacion_bin ~ Horas_Extra + Departamento + Estado_Civil +
## Edad + Ingreso_Mensual + Antigüedad_Cargo, family = binomial,
## data = rotacion)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -9.608e-01 3.514e-01 -2.734 0.006260 **
## Horas_ExtraSi 1.480e+00 1.579e-01 9.367 < 2e-16 ***
## DepartamentoRH 6.411e-01 3.569e-01 1.796 0.072415 .
## DepartamentoVentas 6.194e-01 1.671e-01 3.706 0.000211 ***
## Estado_CivilDivorciado -3.254e-01 2.301e-01 -1.414 0.157282
## Estado_CivilSoltero 7.956e-01 1.706e-01 4.662 3.13e-06 ***
## Edad -2.479e-02 1.002e-02 -2.475 0.013314 *
## Ingreso_Mensual -8.730e-05 2.648e-05 -3.297 0.000976 ***
## Antigüedad_Cargo -9.936e-02 2.715e-02 -3.659 0.000253 ***
## ---
## 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: 1087.6 on 1461 degrees of freedom
## AIC: 1105.6
##
## Number of Fisher Scoring iterations: 5
coef_modelo <- tidy(modelo) %>%
mutate(
odds_ratio = exp(estimate),
significativo = ifelse(p.value < 0.05, "Sí", "No")
)
kable(coef_modelo, digits = 4, caption = "Coeficientes del modelo logístico")
| term | estimate | std.error | statistic | p.value | odds_ratio | significativo |
|---|---|---|---|---|---|---|
| (Intercept) | -0.9608 | 0.3514 | -2.7339 | 0.0063 | 0.3826 | Sí |
| Horas_ExtraSi | 1.4795 | 0.1579 | 9.3674 | 0.0000 | 4.3909 | Sí |
| DepartamentoRH | 0.6411 | 0.3569 | 1.7965 | 0.0724 | 1.8986 | No |
| DepartamentoVentas | 0.6194 | 0.1671 | 3.7059 | 0.0002 | 1.8578 | Sí |
| Estado_CivilDivorciado | -0.3254 | 0.2301 | -1.4143 | 0.1573 | 0.7223 | No |
| Estado_CivilSoltero | 0.7956 | 0.1706 | 4.6623 | 0.0000 | 2.2158 | Sí |
| Edad | -0.0248 | 0.0100 | -2.4753 | 0.0133 | 0.9755 | Sí |
| Ingreso_Mensual | -0.0001 | 0.0000 | -3.2973 | 0.0010 | 0.9999 | Sí |
| Antigüedad_Cargo | -0.0994 | 0.0272 | -3.6595 | 0.0003 | 0.9054 | Sí |
coef_plot <- tidy(modelo, conf.int = TRUE) %>%
filter(term != "(Intercept)") %>%
mutate(
OR = exp(estimate),
OR_low = exp(conf.low),
OR_high = exp(conf.high)
)
ggplot(coef_plot, aes(x = reorder(term, OR), y = OR)) +
geom_point(size = 2.8) +
geom_errorbar(aes(ymin = OR_low, ymax = OR_high), width = 0.15) +
geom_hline(yintercept = 1, linetype = 2) +
coord_flip() +
labs(
title = "Odds ratios estimados del modelo logístico",
x = "Covariables",
y = "Odds Ratio"
) +
theme_minimal(base_size = 12)
Se estimó un modelo de regresión logística con el objetivo de explicar la probabilidad de rotación de los empleados a partir de las variables seleccionadas. Los resultados muestran que la mayoría de las covariables incluidas son estadísticamente significativas (p-valor < 0.05), lo que indica que tienen un efecto relevante sobre la rotación.
En el caso de Horas_Extra, se observa un coeficiente positivo (1.48) y altamente significativo, con un odds ratio de 4.39. Esto implica que los empleados que realizan horas extra tienen aproximadamente 4.4 veces más probabilidad de rotar en comparación con aquellos que no lo hacen, manteniendo constantes las demás variables. Este resultado confirma lo encontrado en el análisis bivariado y refuerza la hipótesis planteada.
Para la variable Departamento, se observa que pertenecer al área de Ventas tiene un efecto positivo y significativo (odds ratio ≈ 1.86), lo que indica una mayor probabilidad de rotación frente al grupo base (I+D). Por otro lado, el departamento de Recursos Humanos no resulta estadísticamente significativo (p-valor = 0.072), lo que sugiere que su efecto no es concluyente en el modelo.
En relación con el Estado Civil, se evidencia que ser soltero incrementa significativamente la probabilidad de rotación (odds ratio ≈ 2.22), mientras que la categoría divorciado no presenta un efecto significativo. Esto confirma parcialmente la hipótesis planteada en el análisis previo.
En cuanto a las variables cuantitativas, la Edad presenta un coeficiente negativo y significativo, lo que indica que a mayor edad disminuye la probabilidad de rotación. De manera similar, el Ingreso_Mensual y la Antigüedad en el cargo también presentan efectos negativos y significativos, lo que sugiere que mayores niveles de ingreso y mayor estabilidad en el cargo reducen la probabilidad de rotación.
En conjunto, los resultados muestran que tanto factores organizacionales (horas extra, departamento) como personales (estado civil, edad) y económicos (ingreso) influyen significativamente en la rotación, consolidando un modelo coherente con los análisis previos.
Para evaluar el desempeño predictivo del modelo se utiliza la curva ROC y el área bajo la curva (AUC). Esta evaluación permite determinar qué tan bien el modelo logra discriminar entre empleados que rotan y empleados que no rotan.
prob <- predict(modelo, type = "response")
roc_obj <- roc(rotacion$Rotacion_bin, prob)
auc_val <- as.numeric(auc(roc_obj))
kable(data.frame(AUC = round(auc_val, 4)), caption = "Área bajo la curva ROC")
| AUC |
|---|
| 0.7724 |
plot(
roc_obj,
main = "Curva ROC del modelo logístico",
col = "#2563eb",
lwd = 3
)
abline(a = 0, b = 1, lty = 2, col = "gray50")
La curva ROC (Receiver Operating Characteristic) permite evaluar la capacidad del modelo para discriminar entre empleados que rotan y aquellos que no lo hacen, considerando diferentes puntos de corte en la probabilidad estimada.
A partir de la gráfica, se observa que la curva se encuentra claramente por encima de la línea diagonal de referencia (clasificación aleatoria), lo que indica que el modelo tiene una capacidad predictiva superior al azar.
La forma de la curva muestra una buena combinación entre sensibilidad y especificidad, especialmente en rangos intermedios, lo que sugiere que el modelo logra identificar adecuadamente una proporción importante de empleados que rotan sin generar un número excesivo de falsos positivos.
En términos generales, el comportamiento de la curva indica que el modelo presenta un desempeño adecuado para fines predictivos, siendo una herramienta útil para apoyar decisiones relacionadas con la gestión del talento y la prevención de la rotación.
Además de estimar probabilidades, es necesario definir un punto de corte para decidir cuándo un empleado debe ser considerado en riesgo de rotación. Como parte del criterio de evaluación, se compara el comportamiento del modelo bajo distintos umbrales.
evaluar_corte <- function(corte, y_real, prob){
pred <- ifelse(prob >= corte, 1, 0)
TP <- sum(pred == 1 & y_real == 1)
TN <- sum(pred == 0 & y_real == 0)
FP <- sum(pred == 1 & y_real == 0)
FN <- sum(pred == 0 & y_real == 1)
sensibilidad <- TP / (TP + FN)
especificidad <- TN / (TN + FP)
exactitud <- (TP + TN) / length(y_real)
data.frame(
Corte = corte,
Sensibilidad = sensibilidad,
Especificidad = especificidad,
Exactitud = exactitud
)
}
cortes <- bind_rows(
evaluar_corte(0.40, rotacion$Rotacion_bin, prob),
evaluar_corte(0.50, rotacion$Rotacion_bin, prob),
evaluar_corte(0.60, rotacion$Rotacion_bin, prob)
)
kable(cortes, digits = 3, caption = "Análisis de sensibilidad del punto de corte")
| Corte | Sensibilidad | Especificidad | Exactitud |
|---|---|---|---|
| 0.4 | 0.304 | 0.958 | 0.852 |
| 0.5 | 0.177 | 0.981 | 0.852 |
| 0.6 | 0.080 | 0.994 | 0.847 |
cortes_long <- cortes %>%
pivot_longer(
cols = c(Sensibilidad, Especificidad, Exactitud),
names_to = "Métrica",
values_to = "Valor"
)
ggplot(cortes_long, aes(x = factor(Corte), y = Valor, group = Métrica, color = Métrica)) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(
title = "Comparación de métricas por punto de corte",
x = "Punto de corte",
y = "Valor"
) +
theme_minimal(base_size = 12)
El análisis de sensibilidad permite evaluar cómo cambian las métricas de clasificación del modelo al modificar el punto de corte utilizado para convertir probabilidades en decisiones binarias. En este caso, se analizaron tres umbrales: 0.4, 0.5 y 0.6.
Se observa que al aumentar el punto de corte, la sensibilidad disminuye de manera considerable (de 0.304 a 0.080), lo que implica que el modelo pierde capacidad para identificar correctamente a los empleados que rotan. Por el contrario, la especificidad aumenta (de 0.958 a 0.994), lo que indica una mejor identificación de los empleados que no rotan.
La exactitud se mantiene relativamente estable alrededor de 0.85 para los tres puntos de corte, lo que sugiere que esta métrica por sí sola no es suficiente para determinar el mejor umbral, especialmente en presencia de desbalance en la variable respuesta.
En este contexto, el punto de corte de 0.4 resulta más adecuado, ya que ofrece un mejor equilibrio entre sensibilidad y especificidad, permitiendo identificar una mayor proporción de empleados en riesgo de rotación sin sacrificar significativamente la precisión general del modelo.
Desde una perspectiva organizacional, es preferible priorizar la detección temprana de posibles casos de rotación, incluso a costa de algunos falsos positivos, dado que esto permite implementar estrategias preventivas de retención de talento.
En este apartado se estima la probabilidad de rotación para un empleado hipotético. Este ejercicio muestra cómo aplicar el modelo a un caso concreto y cómo usar el punto de corte para apoyar una decisión de intervención.
nuevo <- data.frame(
Horas_Extra = factor("Si", levels = levels(rotacion$Horas_Extra)),
Departamento = factor("Ventas", levels = levels(rotacion$Departamento)),
Estado_Civil = factor("Soltero", levels = levels(rotacion$Estado_Civil)),
Edad = 30,
Ingreso_Mensual = 3000,
Antigüedad_Cargo = 1
)
prob_nuevo <- predict(modelo, newdata = nuevo, type = "response")
prob_nuevo
## 1
## 0.6960767
corte_recomendado <- 0.40
decision <- ifelse(prob_nuevo >= corte_recomendado, "Intervenir", "No intervenir")
data.frame(
Probabilidad_rotacion = round(prob_nuevo, 4),
Corte_usado = corte_recomendado,
Decision = decision
) %>%
kable(caption = "Predicción para el individuo hipotético")
| Probabilidad_rotacion | Corte_usado | Decision |
|---|---|---|
| 0.6961 | 0.4 | Intervenir |
A partir del modelo estimado, se calculó la probabilidad de rotación para un individuo hipotético con características específicas. El resultado obtenido fue una probabilidad de 0.6961, lo que indica que existe un alto riesgo de que este empleado cambie de cargo en el próximo período.
Al comparar esta probabilidad con el punto de corte definido (0.4), se observa que el valor estimado supera ampliamente el umbral, por lo que el modelo clasifica a este empleado como un caso que requiere intervención.
Esta decisión es consistente con el análisis de sensibilidad realizado previamente, en el cual se estableció que un punto de corte más bajo permite identificar una mayor proporción de empleados en riesgo, lo cual es deseable en contextos organizacionales donde la prevención de la rotación es prioritaria.
En términos prácticos, este resultado sugiere que el empleado debería ser objeto de seguimiento o intervención por parte del área de recursos humanos, mediante estrategias como revisión de carga laboral, incentivos económicos o acompañamiento en su desarrollo profesional.
El análisis realizado permitió identificar los principales factores asociados a la rotación de empleados, combinando un enfoque descriptivo, inferencial y predictivo. En primer lugar, el análisis univariado evidenció que la organización presenta una alta estabilidad laboral, con una proporción de rotación del 16.1%, aunque con un desbalance importante en la variable respuesta.
El análisis bivariado mostró que todas las variables categóricas seleccionadas (horas extra, departamento y estado civil) tienen una relación significativa con la rotación, destacándose especialmente el efecto de las horas extra. De igual forma, las variables cuantitativas (edad, ingreso mensual y antigüedad en el cargo) presentaron diferencias significativas entre los grupos, confirmando su relevancia en el fenómeno estudiado.
A nivel multivariado, el modelo de regresión logística permitió identificar qué variables mantienen su efecto al controlar por las demás. En particular, las horas extra, el departamento de ventas, el estado civil (soltero), la edad, el ingreso mensual y la antigüedad en el cargo resultaron significativos. En contraste, algunas categorías como recursos humanos y estado civil divorciado no mostraron efectos concluyentes.
En términos de magnitud, las horas extra se consolidan como el factor más influyente, aumentando considerablemente la probabilidad de rotación. Por su parte, variables como el ingreso y la antigüedad actúan como factores protectores, reduciendo dicha probabilidad.
La evaluación del modelo mediante la curva ROC evidenció una capacidad predictiva adecuada, mientras que el análisis de sensibilidad mostró que un punto de corte de 0.4 permite un mejor balance entre detección de casos y precisión general. Finalmente, la predicción realizada para un individuo hipotético confirmó la utilidad práctica del modelo para identificar empleados en riesgo y orientar decisiones de intervención.
A partir de los resultados obtenidos, es posible proponer estrategias concretas orientadas a reducir la rotación de empleados, enfocándose en los factores que demostraron mayor impacto en el modelo.
En primer lugar, dado que las horas extra se identifican como el factor con mayor efecto sobre la rotación, se recomienda implementar políticas que regulen la carga laboral, redistribuyan tareas o aumenten la dotación de personal en áreas con alta demanda. Reducir el exceso de trabajo puede disminuir el desgaste y mejorar la satisfacción laboral.
En segundo lugar, el hecho de que el departamento de ventas presente mayor probabilidad de rotación sugiere la necesidad de intervenciones focalizadas en esta área. Esto podría incluir revisión de metas, esquemas de incentivos, clima laboral y acompañamiento por parte de liderazgo.
En relación con el ingreso mensual, se evidencia que mejores niveles salariales contribuyen a la permanencia. Por tanto, se recomienda evaluar la competitividad salarial y diseñar esquemas de compensación más atractivos, especialmente para perfiles con mayor riesgo de rotación.
Asimismo, la antigüedad en el cargo se comporta como un factor protector, lo que indica la importancia de fortalecer procesos de adaptación y retención en las etapas iniciales del empleado. Programas de onboarding, mentoría y seguimiento pueden ser claves en este punto.
Finalmente, variables como la edad y el estado civil reflejan características individuales que pueden orientar estrategias segmentadas, permitiendo diseñar acciones diferenciadas según perfiles de riesgo.
En conjunto, la implementación de estas estrategias, apoyadas en modelos predictivos como el desarrollado en este análisis, permitiría a la organización anticiparse a la rotación, optimizar la gestión del talento humano y promover un entorno laboral más estable y sostenible.