El objetivo de esta actividad es construir un modelo que permita comprender las razones por las cuales los empleados deciden cambiar de cargo y, al mismo tiempo, estimar la probabilidad de que dicha rotación ocurra. Para ello, se utilizará la técnica estadística de regresión logística, adecuada para predecir resultados binarios. En este caso, la variable de interés será la rotación de cargo, codificada en dos categorías: sí rota y no rota.
Inicialmente, se prepara el espacio de trabajo. Esto implica instalar y cargar los paquetes que permiten llevar a cabo la actividad.
##
## ── R CMD build ─────────────────────────────────────────────────────────────────
## ✔ checking for file 'C:\Users\angel\AppData\Local\Temp\Rtmpg3Apg8\remotesae846051da7\Centromagis-paqueteMODELOS-3b06257/DESCRIPTION'
## ─ preparing 'paqueteMODELOS':
## checking DESCRIPTION meta-information ... ✔ checking DESCRIPTION meta-information
## ─ checking for LF line-endings in source and make files and shell scripts
## ─ checking for empty or unneeded directories
## ─ building 'paqueteMODELOS_0.1.0.tar.gz'
##
##
A continuación se presenta una primera visualización de la estructura del conjunto de datos, donde se observa que contiene 1.470 registros y 24 variables:
## Rows: 1,470
## Columns: 24
## $ 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, …
#Organizar para entender con facilidad
variables <- data.frame(
Variable = c("Rotación", "Edad", "Viaje de Negocios", "Departamento",
"Distancia_Casa", "Educación", "Campo_Educación",
"Satisfacción_Ambiental", "Género", "Cargo",
"Satisfacción_Laboral", "Estado_Civil", "Ingreso_Mensual",
"Trabajos_Anteriores", "Horas_Extra", "Porcentaje_Aumento_Salarial",
"Rendimiento_Laboral", "Años_Experiencia", "Capacitaciones",
"Equilibrio_Trabajo_Vida", "Antigüedad", "Antigüedad_Cargo",
"Años_Última_Promoción", "Años_Acargo_Con_Mismo_Jefe"),
Tipo = c("Categórica (dicotómica, variable respuesta)",
"Cuantitativa (numérica continua)",
"Categórica (ordinal: Raramente, Frecuentemente, Nunca)",
"Categórica (nominal)",
"Cuantitativa (numérica discreta, km)",
"Categórica ordinal (1–5, nivel educativo)",
"Categórica (nominal)",
"Categórica ordinal (1–4)",
"Categórica (nominal: M/F)",
"Categórica (nominal)",
"Categórica ordinal (1–4)",
"Categórica (nominal)",
"Cuantitativa (numérica continua, $)",
"Cuantitativa (numérica discreta)",
"Categórica dicotómica (Sí/No)",
"Cuantitativa (porcentaje)",
"Categórica ordinal (1–4)",
"Cuantitativa (numérica continua)",
"Cuantitativa (numérica discreta)",
"Categórica ordinal (1–4)",
"Cuantitativa (años en la empresa)",
"Cuantitativa (años en el cargo)",
"Cuantitativa (años desde la última promoción)",
"Cuantitativa (años con el mismo jefe)"))
kable(variables, caption = "Clasificación de las variables de la base de datos Rotación")| Variable | Tipo |
|---|---|
| Rotación | Categórica (dicotómica, variable respuesta) |
| Edad | Cuantitativa (numérica continua) |
| Viaje de Negocios | Categórica (ordinal: Raramente, Frecuentemente, Nunca) |
| Departamento | Categórica (nominal) |
| Distancia_Casa | Cuantitativa (numérica discreta, km) |
| Educación | Categórica ordinal (1–5, nivel educativo) |
| Campo_Educación | Categórica (nominal) |
| Satisfacción_Ambiental | Categórica ordinal (1–4) |
| Género | Categórica (nominal: M/F) |
| Cargo | Categórica (nominal) |
| Satisfacción_Laboral | Categórica ordinal (1–4) |
| Estado_Civil | Categórica (nominal) |
| Ingreso_Mensual | Cuantitativa (numérica continua, $) |
| Trabajos_Anteriores | Cuantitativa (numérica discreta) |
| Horas_Extra | Categórica dicotómica (Sí/No) |
| Porcentaje_Aumento_Salarial | Cuantitativa (porcentaje) |
| Rendimiento_Laboral | Categórica ordinal (1–4) |
| Años_Experiencia | Cuantitativa (numérica continua) |
| Capacitaciones | Cuantitativa (numérica discreta) |
| Equilibrio_Trabajo_Vida | Categórica ordinal (1–4) |
| Antigüedad | Cuantitativa (años en la empresa) |
| Antigüedad_Cargo | Cuantitativa (años en el cargo) |
| Años_Última_Promoción | Cuantitativa (años desde la última promoción) |
| Años_Acargo_Con_Mismo_Jefe | Cuantitativa (años con el mismo jefe) |
La clasificación de variables permite identificar con claridad la variable respuesta (Rotación), distinguir entre las predictoras numéricas y las categóricas, y precisar que algunas variables ordinales (como Educación, Satisfacción Laboral y Rendimiento Laboral) pueden ser tratadas como cuantitativas discretas dentro del modelo logístico, con el fin de facilitar su inclusión en el análisis y la interpretación de resultados.
# estandariza nombres
rotacion <- rotacion %>% clean_names()
# Conteo de NA por variable
na_por_variable <- sapply(rotacion, function(x) sum(is.na(x)))
na_por_variable <- sort(na_por_variable, decreasing = TRUE)
na_tabla <- data.frame(
variable = names(na_por_variable),
na_conteo = as.integer(na_por_variable),
na_porcentaje = round(100 * na_por_variable / nrow(rotacion), 2)
)
kable(na_tabla, caption = "Número y porcentaje de valores faltantes por variable")| variable | na_conteo | na_porcentaje | |
|---|---|---|---|
| rotacion | rotacion | 0 | 0 |
| edad | edad | 0 | 0 |
| viaje_de_negocios | viaje_de_negocios | 0 | 0 |
| departamento | departamento | 0 | 0 |
| distancia_casa | distancia_casa | 0 | 0 |
| educacion | educacion | 0 | 0 |
| campo_educacion | campo_educacion | 0 | 0 |
| satisfaccion_ambiental | satisfaccion_ambiental | 0 | 0 |
| genero | genero | 0 | 0 |
| cargo | cargo | 0 | 0 |
| satisfacion_laboral | satisfacion_laboral | 0 | 0 |
| estado_civil | estado_civil | 0 | 0 |
| ingreso_mensual | ingreso_mensual | 0 | 0 |
| trabajos_anteriores | trabajos_anteriores | 0 | 0 |
| horas_extra | horas_extra | 0 | 0 |
| porcentaje_aumento_salarial | porcentaje_aumento_salarial | 0 | 0 |
| rendimiento_laboral | rendimiento_laboral | 0 | 0 |
| anos_experiencia | anos_experiencia | 0 | 0 |
| capacitaciones | capacitaciones | 0 | 0 |
| equilibrio_trabajo_vida | equilibrio_trabajo_vida | 0 | 0 |
| antiguedad | antiguedad | 0 | 0 |
| antiguedad_cargo | antiguedad_cargo | 0 | 0 |
| anos_ultima_promocion | anos_ultima_promocion | 0 | 0 |
| anos_acargo_con_mismo_jefe | anos_acargo_con_mismo_jefe | 0 | 0 |
La base de datos no muestra datos faltantes.
# Duplicados en la base imputada
duplicados <- rotacion[duplicated(rotacion), ]
cat("Número de registros duplicados:", nrow(duplicados), "\n")## Número de registros duplicados: 0
La base de datos no muestra registros duplicados.
Dentro de la selección de las 3 variables cuantitativas y 3 variables cualitativas, que permitan influir en la decisión de un empleado a rotar, plantearemos las siguientes
Con el fin de preparar la variable de respuesta para la estimación del modelo logístico, se realizó un proceso de codificación binaria. En este paso, la variable Rotación fue normalizada para garantizar uniformidad en sus valores (“Sí” / “No”), y posteriormente se creó una nueva columna denominada rotacion_num, donde “Sí” corresponde a 1 y “No” a 0.
# Normalizar valores de la variable rotacion y crear binaria
rotacion <- rotacion %>%
mutate(
rotacion = str_to_title(str_squish(rotacion)), # "Si" / "No"
rotacion_num = if_else(rotacion == "Si", 1L, 0L)
)
# Verificación presentable
tab <- table("Rotación" = rotacion$rotacion,
"Rotacion_num" = rotacion$rotacion_num)
kable(as.data.frame.matrix(tab),
caption = "Matriz de homologación de la variable Rotación")| 0 | 1 | |
|---|---|---|
| No | 1233 | 0 |
| Si | 0 | 237 |
La Matriz de homologación de la variable Rotación confirma que la conversión se ejecutó correctamente: los 1.233 casos sin rotación fueron codificados como 0 y los 237 casos con rotación fueron codificados como 1. De esta manera, se asegura la compatibilidad de la variable respuesta con la regresión logística y se mantiene la integridad de la información original.
Ingreso mensual
(ingreso_mensual)
Antigüedad en el cargo
(antiguedad_cargo)
Satisfacción laboral
(satisfaccion_laboral)
Notas:
Aunque la variable Satisfacción Laboral está definida en una escala ordinal de 1 a 4, en este análisis se la considera como cuantitativa. Esta decisión se justifica porque los valores reflejan un orden natural de menor a mayor satisfacción y se asume que los incrementos entre categorías son comparables.
La variable Antigüedad en el Cargo corresponde a una medida de tiempo expresada en años completos. Al ser un conteo de unidades, se clasifica como variable cuantitativa discreta, pues toma valores numéricos enteros y permite analizar cómo la permanencia en el puesto se relaciona con la probabilidad de rotación.
horas_extra)
estado_civil)
viaje_de_negocios)
Notas:
Estas variables son relevantes porque reflejan factores de carga laboral, estabilidad personal y balance vida-trabajo, los cuales la literatura sugiere que están asociados con la decisión de permanecer o salir de la organización. Aunque Horas Extra, Estado Civil y Viaje de Negocios son cualitativas, se pueden incluir en un modelo estadístico (p. ej. regresión logística) mediante codificación dummy.
variables <- data.frame(
Variable = c("Ingreso mensual", "Antigüedad en el cargo", "Satisfacción laboral",
"Horas extra", "Estado civil", "Viaje de negocios"),
Tipo = c("Cuantitativa continua", "Cuantitativa discreta (años).", "Escala ordinal (1–4), tratada como cuantitativa discreta.",
"Categórica dicotómica (Sí/No)", "Categórica nominal (Casado, Soltero, Divorciado)", "Categórica ordinal (Raramente, Frecuentemente, Nunca)"),
Justificacion = c(
"Factor clave de satisfacción laboral; ingresos bajos motivan a buscar nuevas oportunidades",
"Una permanencia prolongada sin ascensos puede generar desmotivación.",
"Nivel de satisfacción con el trabajo, asociado a permanencia o búsqueda de cambio.",
"Carga laboral adicional que puede generar agotamiento y afectar la vida personal.",
"Situación personal que puede influir en la percepción de estabilidad y flexibilidad.",
"La frecuencia de viajes puede generar estrés y afectar el equilibrio personal."
),
Hipotesis = c(
"Negativa: a mayor ingreso, menor probabilidad de rotación.",
"Positiva: a mayor antigüedad, mayor probabilidad de rotación.",
"Negativa: a mayor satisfacción, menor probabilidad de rotación.",
"Los empleados que trabajan horas extra tienen mayor probabilidad de rotar frente a quienes no lo hacen.",
"Solteros presentan mayor probabilidad de rotación que casados o divorciados.",
"Frecuentes más propensos a rotar que quienes viajan rara vez o nunca."
)
)
kable(variables, caption = "Resumen de variables seleccionadas") | Variable | Tipo | Justificacion | Hipotesis |
|---|---|---|---|
| Ingreso mensual | Cuantitativa continua | Factor clave de satisfacción laboral; ingresos bajos motivan a buscar nuevas oportunidades | Negativa: a mayor ingreso, menor probabilidad de rotación. |
| Antigüedad en el cargo | Cuantitativa discreta (años). | Una permanencia prolongada sin ascensos puede generar desmotivación. | Positiva: a mayor antigüedad, mayor probabilidad de rotación. |
| Satisfacción laboral | Escala ordinal (1–4), tratada como cuantitativa discreta. | Nivel de satisfacción con el trabajo, asociado a permanencia o búsqueda de cambio. | Negativa: a mayor satisfacción, menor probabilidad de rotación. |
| Horas extra | Categórica dicotómica (Sí/No) | Carga laboral adicional que puede generar agotamiento y afectar la vida personal. | Los empleados que trabajan horas extra tienen mayor probabilidad de rotar frente a quienes no lo hacen. |
| Estado civil | Categórica nominal (Casado, Soltero, Divorciado) | Situación personal que puede influir en la percepción de estabilidad y flexibilidad. | Solteros presentan mayor probabilidad de rotación que casados o divorciados. |
| Viaje de negocios | Categórica ordinal (Raramente, Frecuentemente, Nunca) | La frecuencia de viajes puede generar estrés y afectar el equilibrio personal. | Frecuentes más propensos a rotar que quienes viajan rara vez o nunca. |
En esta sección se realiza un análisis univariado, cuyo propósito es examinar cada variable de manera individual para comprender su distribución, características principales y posibles patrones. Este paso permite identificar tendencias generales en los datos y constituye la base para explorar relaciones más complejas en las etapas posteriores del análisis.
# Tabla de frecuencias
tabla_rotacion <- table(rotacion$rotacion)
cat("Frecuencia de Rotación de Empleados\n")## Frecuencia de Rotación de Empleados
##
## No Si
## 1233 237
# Tabla de proporciones
prop_rotacion <- prop.table(tabla_rotacion) * 100
cat("Proporciones de Rotación de Empleados (%)\n")## Proporciones de Rotación de Empleados (%)
##
## No Si
## 83.88 16.12
# Gráfico de barras con porcentajes
ggplot(rotacion, aes(x = rotacion, fill = rotacion)) +
geom_bar() +
geom_text(stat = "count", aes(label = paste0(round(..count../sum(..count..) * 100,1), "%")),
vjust = -0.5) +
scale_fill_brewer(palette = "Set2") +
labs(title = "Distribución de la variable Rotación",
x = "Rotación", y = "Número de empleados") +
theme_minimal()La variable Rotación presenta un comportamiento claramente desbalanceado. Del total de 1.470 empleados, 1.233 (83,9%) no cambiaron de cargo, mientras que únicamente 237 (16,1%) sí realizaron un cambio. Esta distribución indica que la mayoría de los empleados tienden a permanecer en sus puestos, y solo una fracción menor experimenta rotación.
Es importante tener en cuenta este desbalance en la variable de respuesta al momento de ajustar el modelo logístico, ya que puede influir en la capacidad predictiva y en la interpretación de los resultados.
# Resumen estadístico de las variables cuantitativas
summary(rotacion[, c("ingreso_mensual", "antiguedad_cargo", "satisfacion_laboral")])## ingreso_mensual antiguedad_cargo satisfacion_laboral
## Min. : 1009 Min. : 0.000 Min. :1.000
## 1st Qu.: 2911 1st Qu.: 2.000 1st Qu.:2.000
## Median : 4919 Median : 3.000 Median :3.000
## Mean : 6503 Mean : 4.229 Mean :2.729
## 3rd Qu.: 8379 3rd Qu.: 7.000 3rd Qu.:4.000
## Max. :19999 Max. :18.000 Max. :4.000
# Histograma del Ingreso Mensual
ggplot(rotacion, aes(x = ingreso_mensual)) +
geom_histogram(binwidth = 1000, fill = "blue", color = "white") +
labs(title = "Distribución del Ingreso Mensual", x = "Ingreso ($)", y = "Frecuencia")# Histograma de la Antigüedad en el Cargo
ggplot(rotacion, aes(x = antiguedad_cargo)) +
geom_histogram(binwidth = 1, fill = "green", color = "white") +
labs(title = "Distribución de la Antigüedad en el Cargo", x = "Años en el cargo", y = "Frecuencia")# Histograma de Satisfacción Laboral
ggplot(rotacion, aes(x = satisfacion_laboral)) +
geom_histogram(binwidth = 1, fill = "purple", color = "white") +
labs(title = "Distribución de la Satisfacción Laboral",
x = "Nivel de satisfacción (1=Muy baja, 4=Muy alta)",
y = "Frecuencia")Interpretración:
## Frecuencia de empleados por Horas Extra
##
## No Si
## 1054 416
##
## Frecuencia de empleados por Estado Civil
##
## Casado Divorciado Soltero
## 673 327 470
# Tabla de frecuencias para Viaje de Negocios
cat("\nFrecuencia de empleados por Viaje de Negocios\n")##
## Frecuencia de empleados por Viaje de Negocios
##
## Frecuentemente No_Viaja Raramente
## 277 150 1043
# Gráfico para Horas Extra
ggplot(rotacion, aes(x = horas_extra, fill = horas_extra)) +
geom_bar() +
labs(title = "Distribución de Horas Extra",
x = "Horas Extra",
y = "Cantidad") +
theme_minimal()# Gráfico para Estado Civil
ggplot(rotacion, aes(x = estado_civil, fill = estado_civil)) +
geom_bar() +
labs(title = "Distribución por Estado Civil",
x = "Estado Civil",
y = "Cantidad") +
theme_minimal()# Gráfico para Viaje de Negocios
ggplot(rotacion, aes(x = viaje_de_negocios, fill = viaje_de_negocios)) +
geom_bar() +
labs(title = "Frecuencia de Viajes de Negocios",
x = "Frecuencia de viaje",
y = "Cantidad") +
theme_minimal()Interpretación:
En esta sección se analiza la relación entre la variable respuesta Rotación y las variables predictoras seleccionadas. Para las variables cuantitativas se utilizan diagramas de caja (boxplots), que permiten comparar la distribución de los valores según los grupos de rotación (Sí/No). Para las variables categóricas se emplean gráficos de barras proporcionales, con el fin de observar la proporción de empleados que rotan en cada categoría.
Este análisis exploratorio busca identificar patrones iniciales que puedan anticipar comportamientos relevantes en el modelo de regresión.
# Ingreso Mensual vs. Rotación (Boxplot)
ggplot(rotacion, aes(x = rotacion, y = ingreso_mensual, fill = rotacion)) +
geom_boxplot() +
labs(title = "Ingreso Mensual según Rotación", y = "Ingreso ($)") +
theme_minimal()Interpretación:
Se observa que el ingreso mensual mediano y promedio de los empleados que rotaron es considerablemente menor en comparación con el de aquellos que permanecieron en la empresa. Esto indica que los salarios más bajos están asociados con una mayor probabilidad de rotación, lo cual confirma la hipótesis inicial: a mayor ingreso, menor probabilidad de rotación.
Se presentan algunos datos atípicos en el límite superior.
# Antigüedad en el Cargo vs. Rotación (Boxplot)
ggplot(rotacion, aes(x = rotacion, y = antiguedad_cargo, fill = rotacion)) +
geom_boxplot() +
labs(title = "Antigüedad en el Cargo según Rotación", y = "Años en el Cargo")Interpretación: Se observa que los empleados que rotaron presentan, en promedio, una menor antigüedad en el cargo en comparación con quienes permanecieron en la empresa. Este resultado es contrario a la hipótesis inicial, que planteaba que una mayor antigüedad podía incrementar la probabilidad de rotación por desmotivación o falta de ascensos. Se presentan algunos datos atípicos en el límite superior.
# Satisfaccion laboral vs. Rotación (Boxplot)
ggplot(rotacion, aes(x = rotacion, y = satisfacion_laboral, fill = rotacion)) +
geom_boxplot() +
labs(title = "Satisfacción Laboral según Rotación",
y = "Nivel de Satisfacción (1 = Muy baja, 4 = Muy alta)") +
theme_minimal()
Interpretación: El gráfico muestra que los empleados
que no rotaron tienden a tener niveles de satisfacción laboral más altos
(mediana alrededor de 3), mientras que los que sí rotaron presentan
niveles de satisfacción más bajos (mediana en 2).Esto confirma la
hipótesis inicial: a mayor satisfacción laboral, menor probabilidad de
rotación.
# Horas Extra vs. Rotación (Gráfico de proporciones)
ggplot(rotacion, aes(x = horas_extra, fill = rotacion)) +
geom_bar(position = "fill") +
labs(title = "Proporción de Rotación según Horas Extra", y = "Proporción") +
scale_y_continuous(labels = scales::percent)Interpretación:
La gráfica muestra que la proporción de empleados que rotan es mayor entre quienes realizan horas extra, en comparación con aquellos que no las realizan.Este hallazgo confirma la hipótesis planteada: una mayor carga laboral (expresada en horas extra) incrementa la probabilidad de rotación, posiblemente porque el desequilibrio entre la vida laboral y personal genera insatisfacción y búsqueda de otras oportunidades.
# Estado Civil vs. Rotación
ggplot(rotacion, aes(x = estado_civil, fill = rotacion)) +
geom_bar(position = "fill") +
labs(title = "Proporción de Rotación según Estado Civil", y = "Proporción") +
scale_y_continuous(labels = scales::percent)Interpretación:
La gráfica muestra que los empleados solteros presentan la mayor proporción de rotación, en comparación con los casados y divorciados.Este resultado confirma la hipótesis inicial: la situación personal y familiar puede influir en la estabilidad laboral, siendo los solteros más proclives a cambiar de empleo, probablemente debido a una mayor flexibilidad para asumir riesgos o explorar nuevas oportunidades.
# Viaje de Negocios vs. Rotación (Gráfico de proporciones)
ggplot(rotacion, aes(x = viaje_de_negocios, fill = rotacion)) +
geom_bar(position = "fill") +
labs(title = "Proporción de Rotación según Viaje de Negocios",
x = "Frecuencia de Viaje",
y = "Proporción") +
scale_y_continuous(labels = scales::percent) +
theme_minimal()Interpretación:
Se observa que los empleados que viajan frecuentemente presentan una proporción más alta de rotación en comparación con quienes no viajan o lo hacen raramente. Esto respalda la hipótesis de que los viajes de negocios frecuentes pueden generar mayor desgaste y afectar el equilibrio personal, aumentando la probabilidad de rotación. Por el contrario, los empleados que no viajan muestran la proporción más baja de rotación, lo que sugiere una mayor estabilidad laboral en este grupo.
# Variables seleccionadas
vars <- c("ingreso_mensual",
"antiguedad_cargo",
"satisfacion_laboral",
"horas_extra",
"estado_civil",
"viaje_de_negocios")
# Funcion para ajustar cada modelo bivariado
ajusta_logit_bivariado <- function(var){
f <- as.formula(paste("rotacion_num ~", var))
m <- glm(f, data = rotacion, family = binomial()) # <-- base original (sin ROSE)
broom::tidy(m, conf.int = TRUE, conf.level = 0.95, exponentiate = TRUE) %>%
dplyr::filter(term != "(Intercept)") %>%
dplyr::mutate(variable = var) %>%
dplyr::select(variable, term,
OR = estimate, IC95_inf = conf.low, IC95_sup = conf.high,
p.value)
}
tabla_bivariado <- dplyr::bind_rows(lapply(vars, ajusta_logit_bivariado)) %>%
dplyr::arrange(variable, desc(OR))
knitr::kable(tabla_bivariado, digits = 3,
caption = "Modelos logisticos bivariados (OR, IC95% y p-valor)")| variable | term | OR | IC95_inf | IC95_sup | p.value |
|---|---|---|---|---|---|
| antiguedad_cargo | antiguedad_cargo | 0.864 | 0.823 | 0.905 | 0.000 |
| estado_civil | estado_civilSoltero | 2.404 | 1.769 | 3.281 | 0.000 |
| estado_civil | estado_civilDivorciado | 0.787 | 0.508 | 1.194 | 0.271 |
| horas_extra | horas_extraSi | 3.771 | 2.832 | 5.032 | 0.000 |
| ingreso_mensual | ingreso_mensual | 1.000 | 1.000 | 1.000 | 0.000 |
| satisfacion_laboral | satisfacion_laboral | 0.778 | 0.686 | 0.881 | 0.000 |
| viaje_de_negocios | viaje_de_negociosRaramente | 0.530 | 0.386 | 0.734 | 0.000 |
| viaje_de_negocios | viaje_de_negociosNo_Viaja | 0.262 | 0.131 | 0.485 | 0.000 |
Interpretación:
Los resultados del análisis bivariado muestran que varias de las variables seleccionadas presentan una asociación estadísticamente significativa con la rotación de empleados:
Ingreso mensual (OR ≈ 1.000, p < 0.001): aunque el valor del OR parece cercano a 1, al interpretarlo en miles de pesos se confirma que mayores ingresos reducen la probabilidad de rotación. Esto coincide con la hipótesis inicial de que los salarios bajos son un factor de riesgo.
Antigüedad en el cargo (OR = 0.864, p < 0.001): por cada año adicional en el cargo, la probabilidad de rotación disminuye en un 13,6%. Este resultado contradice la hipótesis planteada inicialmente, que proponía que una permanencia prolongada podría incrementar la rotación.
Satisfacción laboral (OR = 0.778, p < 0.001): cada punto adicional en la escala de satisfacción reduce en un 22% la probabilidad de rotar, lo que confirma la hipótesis inicial.
Horas extra (OR = 3.771, p < 0.001): trabajar horas adicionales incrementa en casi 4 veces la probabilidad de rotación, mostrando un efecto altamente significativo.Confirma la hipótesis inicial.
Estado civil: los empleados solteros presentan más del doble de probabilidad de rotar que los casados (OR = 2.404, p < 0.001), mientras que los divorciados no muestran diferencias significativas (p = 0.271).Coincide en gran parte, salvo que los divorciados no muestran diferencias.
Viajes de negocios: quienes viajan frecuentemente tienen casi el doble de probabilidad de rotación frente a quienes viajan raramente (OR = 1.886, p < 0.001). En contraste, los que no viajan tienen una probabilidad significativamente menor de rotar (OR = 0.494, p = 0.025).En línea con lo esperado.
En conjunto, estos hallazgos confirman la mayoría de las hipótesis planteadas en la etapa exploratoria (ingresos, satisfacción laboral, horas extra, estado civil y viajes de negocios), aunque evidencian que la antigüedad en el cargo opera de manera inversa a lo esperado: en lugar de aumentar la probabilidad de rotación, parece favorecer la permanencia.
Ahora, con las variables seleccionadas las combinaremos en un único modelo buscando predecir la rotación. Es importante que para ejecutar el modelo logístico las clases se encuentren balancedadas.
Con el análisis anterior habíamos evidenciado que la variable respuesta Rotación presentaba un desbalance, por lo cual antes de ejecutar el Modelo realizamos ese balanceo.
Adicionalmente, las variables predictoras categóricas se definen como factores con niveles ordenados y coherentes para que el modelo las use bien.
# Categóricas como factor con niveles consistentes
rotacion$horas_extra <- factor(rotacion$horas_extra, levels = c("No","Si"))
rotacion$estado_civil <- factor(rotacion$estado_civil, levels = c("Casado","Divorciado","Soltero"))
rotacion$viaje_de_negocios <- factor(rotacion$viaje_de_negocios, levels = c("Raramente","Frecuentemente","No_Viaja"))
# Balanceo de Rotacion
set.seed(123)
rotacion_balanceada <- ROSE(
rotacion_num ~ ingreso_mensual + antiguedad_cargo +
satisfacion_laboral + horas_extra + estado_civil + viaje_de_negocios,
data = rotacion, seed = 123
)$data
# Verificar balance
knitr::kable(as.data.frame(table(rotacion_balanceada$rotacion_num)),
col.names = c("Clase","Frecuencia"),
caption = "Distribución de la variable respuesta después de ROSE")| Clase | Frecuencia |
|---|---|
| 0 | 746 |
| 1 | 724 |
# Ajuste del modelo logístico
modelo_logistico <- glm(
rotacion_num ~ ingreso_mensual + antiguedad_cargo +
satisfacion_laboral + horas_extra + estado_civil + viaje_de_negocios,
data = rotacion_balanceada,
family = binomial()
)
# Extraer resultados ordenados
resumen <- tidy(modelo_logistico)
# Mostrar como tabla
kable(resumen, digits = 4, caption = "Resumen del modelo de regresión logística")| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| (Intercept) | 0.3613 | 0.1968 | 1.8356 | 0.0664 |
| ingreso_mensual | -0.0001 | 0.0000 | -4.8133 | 0.0000 |
| antiguedad_cargo | -0.0857 | 0.0183 | -4.6891 | 0.0000 |
| satisfacion_laboral | -0.2917 | 0.0510 | -5.7174 | 0.0000 |
| horas_extraSi | 1.6307 | 0.1276 | 12.7846 | 0.0000 |
| estado_civilDivorciado | -0.2686 | 0.1661 | -1.6168 | 0.1059 |
| estado_civilSoltero | 0.9287 | 0.1364 | 6.8066 | 0.0000 |
| viaje_de_negociosFrecuentemente | 0.7517 | 0.1464 | 5.1360 | 0.0000 |
| viaje_de_negociosNo_Viaja | -0.7452 | 0.2428 | -3.0688 | 0.0021 |
La variable respuesta rotacion_num quedó balanceada:“No”: 746 y “Sí”: 724
ingreso_mensual (Estimate = -0.0001 , p < 0.001 Significativo): coeficiente negativo → a mayor ingreso, menor probabilidad de rotación.
antiguedad_cargo (Estimate = -0.0857 , p < 0.001 Significativo): coeficiente negativo.A mayor antigüedad, menor probabilidad de rotación (Cambió respecto a la hipótesis que habíamos planteado inicialmente).
satisfaccion_laboral (Estimate = -0.2917 , p < 0.001 Significativo): coeficiente negativo. A mayor satisfacción, menos rotación.
horas_extra (Estimate = 1.6307, p < 0.001 Altamente significativo): positivo. Trabajar horas extra aumenta la probabilidad de rotación.
estado_civil (Soltero:Estimate = 0.9287, p < 0.001 → Muy significativo, Divorciado Estimate = -0.2686, p = 0.106 → No significativo): Los solteros tienen más probabilidad de rotación que casados.
viaje_de_negocios (Frecuentemente (Estimate = 0.751, p < 0.001)y No viaja (Estimate = -0.745, p = 0.002) fueron significativos): Ambos influyen en la probabilidad de rotación frente a la categoría de referencia.
Interpretación:
Por cada incremento de $1.000 en el salario, la probabilidad de rotación disminuye aproximadamente entre un 7 y 8%.
Por cada año adicional en el cargo la probabilidad de rotar disminuye un 8.5%. Este resultado contradice la hipótesis inicial (que planteaba que mayor antigüedad aumentaría la rotación), sugiriendo que los empleados con más años en el cargo tienden a permanecer en la organización.
Por cada punto de satisfacción laboral adidiconal, la probabilidad de rotación disminuye aproximadamente 30%
Un empleado que trabaja horas extra tiene entre 4 y 5 veces más probabilidad de rotar que uno que no lo hace.
Ser soltero multiplica las probabilidades de rotar aproximadamente 3 veces en comparación con alguien casado.
Viajar frecuentemente multiplica en torno a 2 veces la probabilidad de rotar en comparación con viajar raramente.
verificación de multicolinealidad (VIF):
Antes de evaluar el poder predictivo del modelo, es necesario verificar si las variables predictoras presentan problemas de multicolinealidad, ya que esto podría afectar la estabilidad y la interpretación de los coeficientes.
## GVIF Df GVIF^(1/(2*Df))
## ingreso_mensual 1.114548 1 1.055722
## antiguedad_cargo 1.093444 1 1.045679
## satisfacion_laboral 1.032446 1 1.016094
## horas_extra 1.041251 1 1.020417
## estado_civil 1.031807 2 1.007859
## viaje_de_negocios 1.020456 2 1.005075
Se verificó la presencia de multicolinealidad mediante el Factor de Inflación de la Varianza (VIF). Los valores obtenidos fueron cercanos a 1 para todas las variables predictoras, lo que indica que no existe colinealidad problemática. Por lo tanto, las variables seleccionadas pueden ser incluidas simultáneamente en el modelo de regresión logística sin riesgo de redundancia entre ellas.
El propósito principal de los modelos es lograr predecir adecuadamente la rotación de empleados. Para evaluar este desempeño, utilizamos la Curva ROC y el AUC:
Curva ROC: permite distinguir entre empleados que rotan y los que no. En un modelo perfecto, la curva se aproximaría a la esquina superior izquierda del gráfico, indicando alta sensibilidad y especificidad.
AUC (Área bajo la curva ROC): mide el poder discriminatorio del modelo. Un valor cercano a 0.5 indica que el modelo no tiene capacidad predictiva (equivalente al azar). Un valor cercano a 1.0 indica un modelo perfecto. De forma práctica, un AUC > 0.7 se considera aceptable, y un AUC > 0.8 se considera bueno.
# Predecir probabilidades con el modelo logístico
probabilidades <- predict(modelo_logistico, type = "response")
# Crear el objeto ROC (usamos la verdad y las probabilidades)
roc_obj <- roc(rotacion_balanceada$rotacion_num, probabilidades)
#Calcular el AUC
auc_valor <- auc(roc_obj)
print(paste("El valor del AUC es:", round(auc_valor, 3)))## [1] "El valor del AUC es: 0.798"
# Graficar la curva ROC
plot(roc_obj,
main = "Curva ROC del Modelo Logístico",
col = "blue", lwd = 2)
# Línea de referencia (modelo al azar)
abline(a = 0, b = 1, lty = 2, col = "gray")
# Agregar leyenda con el valor de AUC
legend("bottomright",
legend = paste("AUC =", round(auc_valor, 2)),
col = "blue", lwd = 2)
Interpretación: La curva azul se aleja claramente de la
diagonal (línea gris), lo que indica que el modelo sí logra diferenciar
entre empleados que rotan y los que no. El modelo logístico obtuvo un
AUC = 0.80, lo que indica una capacidad predictiva muy buena.
Para hacer este ejercicio vamos a tomar 2 casos extremos del análisis descriptivo EDA.
*Un perfil de empleado con bajo riesgo de rotación (ej. alto salario, alta satisfacción, casado, sin horas extra, rara vez viaja).
*Un perfil de empleado con alto riesgo de rotación (ej. bajo salario, baja satisfacción, soltero, trabaja horas extra, viaja frecuentemente).
ingreso_mensual = 6000,
antiguedad_cargo = 10,
satisfacion_laboral = 4,
horas_extra = “No”, estado_civil = “Casado”, viaje_de_negocios =
“Raramente”
ingreso_mensual = 1200,
antiguedad_cargo = 1,
satisfacion_laboral = 1,
horas_extra = “Si”, estado_civil = “Soltero”, viaje_de_negocios =
“Frecuentemente”
# Caso 2: Alto riesgo de rotación
empleado_inestable <- data.frame(
ingreso_mensual = 1200, # salario bajo
antiguedad_cargo = 1, # poco tiempo en el cargo
satisfacion_laboral = 1, # insatisfecho
horas_extra = "Si",
estado_civil = "Soltero",
viaje_de_negocios = "Frecuentemente"
)Para esto estimamos un punto de corte:
# Probabilidades predichas del modelo
probabilidades <- predict(modelo_logistico, type = "response")
# Crear objeto ROC
roc_obj <- roc(rotacion_balanceada$rotacion_num, probabilidades)
# Calcular el mejor punto de corte según índice de Youden
corte_optimo <- coords(roc_obj, "best", ret = "threshold", best.method = "youden")
print(paste("El mejor punto de corte es:", round(corte_optimo, 3)))## [1] "El mejor punto de corte es: 0.549"
El modelo encontró que el umbral más adecuado es 0.549, lo cual mejora la capacidad predictiva.
A continuación se realizan las predicciones del modelo:
# Predicciones
prob_estable <- predict(modelo_logistico, newdata = empleado_estable, type = "response")
# Clasificación con corte 0.549
corte <- 0.549
pred_estable <- ifelse(prob_estable >= corte, "Si rota", "No rota")## Empleado Prob_Rotacion Prediccion
## 1 Estable (bajo riesgo) 0.110 No rota
## 2 Inestable (alto riesgo) 0.961 Si rota
Interpretación:
El empleado estable (bajo riesgo), con alto salario, antigüedad en el cargo, alta satisfacción laboral, sin horas extra, casado y con viajes de negocios poco frecuentes, tiene una probabilidad de rotación del 11%, lo que se interpreta como un bajo riesgo de abandonar la organización. El modelo lo clasifica como “No rota”.
El empleado inestable (alto riesgo), con bajo salario, poca antigüedad, baja satisfacción laboral, soltero, que trabaja horas extra y viaja frecuentemente, presenta una probabilidad de rotación del 96%, siendo clasificado como “Sí rota”. Este caso representa un perfil que requiere atención prioritaria en la gestión de talento, ya que su permanencia en la empresa está altamente comprometida.
Conclusiones
Ingreso mensual: los empleados con salarios más bajos tienen una mayor probabilidad de rotar. Esto confirma que los factores económicos son determinantes.
Antigüedad en el cargo: contrario a la hipótesis inicial, los empleados con mayor antigüedad tienden a permanecer más. Esto sugiere que la rotación ocurre más en etapas tempranas del empleo.
Satisfacción laboral: A mayor satisfacción, menor rotación. Esto muestra la importancia del clima y ambiente organizacional.
Horas extra: trabajar horas adicionales aumenta de manera muy significativa la probabilidad de rotación.
Estado civil: los solteros presentan mayor riesgo de rotación frente a los casados.
Viajes de negocios: viajar frecuentemente o no viajar en absoluto se asocia con mayor probabilidad de rotación, frente a quienes viajan rara vez.
Estrategias para disminuir la rotación
*Mejorar los incentivos económicos:Ajustar escalas salariales o implementar bonos de retención, especialmente en los primeros años.Establecer aumentos periódicos y transparentes.
*Plan de carrera y crecimiento interno: Diseñar programas de promoción y desarrollo que motiven a los empleados a permanecer en la organización.
*Ambiente laboral y satisfacción:Implementar encuestas periódicas de satisfacción laboral.
*Gestión de carga laboral: Redistribuir horas extra.contratar más personal o reorganizar turnos.
*Fomentar el equilibrio trabajo-vida personal: Flexibilidad y balance en viajes de negocios. Reducir la frecuencia de viajes o compensarlos con beneficios (días libres, bonos).
*Diseñar programas específicos de retención para empleados solteros (mayor riesgo de rotación).
*Promover actividades sociales y de integración para fortalecer su sentido de pertenencia.