# Cargar librerías necesarias
library(readxl)
library(ggplot2)
library(dplyr)
# Definir la ruta correcta
file_path <- "Datos_Rotación.xlsx"
# Cargar los datos
datos <- read_excel(file_path)
# Renombrar columnas: convertir a minúsculas, eliminar tildes y reemplazar espacios por "_"
colnames(datos) <- tolower(gsub(" ", "_", colnames(datos)))
# ------------------------
# GRÁFICOS DE VARIABLES CUALITATIVAS Y CUANTITATIVAS
# ------------------------
cualitativas <- c("viaje_de_negocios", "genero", "estado_civil", "horas_extra")
cuantitativas <- c("ingreso_mensual", "años_experiencia", "capacitaciones")
# Gráficos de variables cualitativas
for (var in cualitativas) {
p1 <- ggplot(datos, aes(x = .data[[var]], fill = as.factor(rotación))) +
geom_bar(position = "dodge") +
labs(title = paste("Distribución de", var, "según Rotación"), x = var, y = "Frecuencia", fill = "Rotación") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p1)
}# Gráficos de variables cuantitativas
for (var in cuantitativas) {
p2 <- ggplot(datos, aes(x = as.factor(rotación), y = .data[[var]], fill = as.factor(rotación))) +
geom_boxplot() +
labs(title = paste("Boxplot de", var, "según Rotación"), x = "Rotación", y = var, fill = "Rotación") +
theme_minimal()
print(p2)
}# ⚙️ CONFIGURACIÓN INICIAL A PRUEBA DE ERRORES
knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE, results = "asis")
suppressMessages({
library(readxl)
library(dplyr)
library(tidyr)
library(gt)
library(kableExtra)
library(htmltools) # Para forzar la impresión correcta
})
# Definir la ruta correcta
file_path <- "Datos_Rotación.xlsx"
# Cargar los datos
datos <- read_excel(file_path)
datos <- read_excel(file_path) %>%
mutate(across(where(is.character), ~ iconv(.x, to = "ASCII//TRANSLIT")))
colnames(datos) <- tolower(gsub(" ", "_", iconv(colnames(datos), to = "ASCII//TRANSLIT")))
if (!"rotacion" %in% colnames(datos)) {
stop("❌ ERROR: La columna 'rotacion' no existe en los datos.")
}
# ================================
# 📊 CUANTITATIVAS VS ROTACIÓN
# ================================
cuantitativas <- c("ingreso_mensual", "anos_experiencia", "capacitaciones")
tablas_cuantitativas <- list()
for (var in cuantitativas) {
if (!var %in% colnames(datos)) next
tabla_cuant <- datos %>%
group_by(rotacion) %>%
summarise(
Promedio = round(mean(.data[[var]], na.rm = TRUE), 2),
Desviacion = round(sd(.data[[var]], na.rm = TRUE), 2),
.groups = "drop"
)
promedio_no <- tabla_cuant$Promedio[tabla_cuant$rotacion == "No"]
promedio_si <- tabla_cuant$Promedio[tabla_cuant$rotacion == "Si"]
variacion <- ifelse(!is.na(promedio_no) & !is.na(promedio_si) & promedio_si != 0,
round(100 * (promedio_no - promedio_si) / promedio_si, 2), NA)
tabla_cuant <- bind_rows(
tabla_cuant,
tibble(rotacion = "Variacion", Promedio = variacion, Desviacion = NA_real_)
)
# Guardar la tabla en la lista
tablas_cuantitativas[[var]] <- gt(tabla_cuant) %>%
tab_header(title = paste("Comparación de", var, "según Rotación")) %>%
fmt_number(columns = 2:3, decimals = 2) %>%
cols_label(
rotacion = "Rotación",
Promedio = "Promedio",
Desviacion = "Desviación Estándar"
) %>%
tab_options(table.border.top.color = "black",
table.border.bottom.color = "black")
}
# ================================
# 📊 CUALITATIVAS VS ROTACIÓN
# ================================
cualitativas <- c("viaje_de_negocios", "genero", "estado_civil", "horas_extra")
tablas_cualitativas <- list()
for (var in cualitativas) {
if (!var %in% colnames(datos)) next
tabla_cual <- datos %>%
group_by(.data[[var]], rotacion) %>%
summarise(Frecuencia = n(), .groups = "drop") %>%
pivot_wider(names_from = rotacion, values_from = Frecuencia, values_fill = list(Frecuencia = 0)) %>%
mutate(Total = rowSums(across(where(is.numeric)), na.rm = TRUE)) %>%
mutate(across(-1, ~ round(.x / Total * 100, 2))) %>%
rename(Categoria = 1)
# Guardar la tabla en la lista
tablas_cualitativas[[var]] <- gt(tabla_cual) %>%
tab_header(title = paste("Distribución de", var, "según Rotación (%)")) %>%
fmt_number(columns = 2:4, decimals = 2) %>%
cols_label(
Categoria = "Categoría",
No = "No (%)",
Si = "Sí (%)",
Total = "Total (%)"
) %>%
tab_options(table.border.top.color = "black",
table.border.bottom.color = "black")
}
# 📌 FORZAR LA IMPRESIÓN CORRECTA
tagList(tablas_cuantitativas, tablas_cualitativas)| Comparación de ingreso_mensual según Rotación | ||
| Rotación | Promedio | Desviación Estándar |
|---|---|---|
| No | 6,832.74 | 4,818.21 |
| Si | 4,787.09 | 3,640.21 |
| Variacion | 42.73 | NA |
| Comparación de anos_experiencia según Rotación | ||
| Rotación | Promedio | Desviación Estándar |
|---|---|---|
| No | 11.86 | 7.76 |
| Si | 8.24 | 7.17 |
| Variacion | 43.93 | NA |
| Comparación de capacitaciones según Rotación | ||
| Rotación | Promedio | Desviación Estándar |
|---|---|---|
| No | 2.83 | 1.29 |
| Si | 2.62 | 1.25 |
| Variacion | 8.02 | NA |
| Distribución de viaje_de_negocios según Rotación (%) | |||
| Categoría | No (%) | Sí (%) | Total (%) |
|---|---|---|---|
| Frecuentemente | 75.09 | 24.91 | 100.00 |
| No_Viaja | 92.00 | 8.00 | 100.00 |
| Raramente | 85.04 | 14.96 | 100.00 |
| Distribución de genero según Rotación (%) | |||
| Categoría | No (%) | Sí (%) | Total (%) |
|---|---|---|---|
| F | 85.20 | 14.80 | 100.00 |
| M | 82.99 | 17.01 | 100.00 |
| Distribución de estado_civil según Rotación (%) | |||
| Categoría | No (%) | Sí (%) | Total (%) |
|---|---|---|---|
| Casado | 87.52 | 12.48 | 100.00 |
| Divorciado | 89.91 | 10.09 | 100.00 |
| Soltero | 74.47 | 25.53 | 100.00 |
| Distribución de horas_extra según Rotación (%) | |||
| Categoría | No (%) | Sí (%) | Total (%) |
|---|---|---|---|
| No | 89.56 | 10.44 | 100.00 |
| Si | 69.47 | 30.53 | 100.00 |
Estrategia para Disminuir la Rotación 1. Incentivos económicos y salario competitivo + Los empleados con menores ingresos tienen mayor tendencia a la rotación.
La rotación es más alta en empleados con muchas horas extra.
Se sugiere redistribuir la carga laboral, contratar más personal para disminuir la necesidad de horas extra y promover un equilibrio entre la vida laboral y personal.
Los empleados con menos años de experiencia son más propensos a la rotación.
Se recomienda implementar programas de mentoría, oportunidades de crecimiento interno y capacitaciones enfocadas en desarrollo de carrera.
La rotación es mayor en empleados solteros, lo que sugiere que pueden estar buscando más flexibilidad o mejores oportunidades.
Se pueden implementar políticas de home office, horarios flexibles y beneficios como días libres adicionales.
Prompt para IA Generativa
# Cargar librerías necesarias
library(ggplot2)
library(dplyr)
library(readxl)
library(flextable)
# Definir la ruta correcta
file_path <- "Datos_Rotación.xlsx"
# Cargar los datos
datos <- read_excel(file_path)
# 🔹 Asegurar que los nombres de las columnas sean consistentes
colnames(datos) <- gsub(" ", "_", colnames(datos)) # Reemplaza espacios por guion bajo
# 🔹 Convertir variables categóricas en factores
datos$Rotación <- as.factor(datos$Rotación)
datos$Horas_Extra <- as.factor(datos$Horas_Extra)
datos$Estado_Civil <- as.factor(datos$Estado_Civil)
datos$Viaje_de_Negocios <- as.factor(datos$Viaje_de_Negocios) # ✅ Se incluye
# 🔹 Entrenar modelo de regresión logística
modelo_rotacion <- glm(Rotación ~ Estado_Civil + Horas_Extra + Ingreso_Mensual + Años_Experiencia + Viaje_de_Negocios,
data = datos, family = binomial)
# 🔹 Crear los 3 escenarios con nivel Bajo, Medio y Alto de riesgo
escenarios <- data.frame(
Estado_Civil = factor(c("Soltero", "Casado", "Divorciado"), levels = levels(datos$Estado_Civil)),
Horas_Extra = factor(c("No", "Si", "Si"), levels = levels(datos$Horas_Extra)),
Viaje_de_Negocios = factor(c("No_Viaja", "Raramente", "Frecuentemente"), levels = levels(datos$Viaje_de_Negocios)),
Ingreso_Mensual = c(5000, 2500, 500), # 🔥 Se baja aún más en el último
Años_Experiencia = c(15, 5, 1) # 🔥 Menos experiencia en el último caso
)
# 🔹 Predecir la probabilidad de rotación
escenarios$Probabilidad_Rotación <- predict(modelo_rotacion, newdata = escenarios, type = "response")
# 🔹 Clasificar el nivel de riesgo
escenarios$Riesgo <- case_when(
escenarios$Probabilidad_Rotación < 0.2 ~ "Bajo",
escenarios$Probabilidad_Rotación >= 0.2 & escenarios$Probabilidad_Rotación < 0.5 ~ "Medio",
escenarios$Probabilidad_Rotación >= 0.5 ~ "Alto" # 🚨 Se busca que el último sea "Alto"
)
# 🔹 Definir colores según el nivel de riesgo
colores_riesgo <- c("Bajo" = "lightgreen", "Medio" = "yellow", "Alto" = "red")
# 🔹 Crear la tabla con `flextable`
tabla_flex <- flextable(escenarios) %>%
set_caption("📊 Escenarios de Predicción de Rotación") %>%
colformat_num(j = "Probabilidad_Rotación", digits = 2) %>%
color(j = "Riesgo", color = "black", part = "body") %>%
bg(j = "Riesgo", bg = colores_riesgo[escenarios$Riesgo]) %>%
set_table_properties(width = 1, layout = "autofit")
# 🔹 Mostrar la tabla
tabla_flex Estado_Civil | Horas_Extra | Viaje_de_Negocios | Ingreso_Mensual | Años_Experiencia | Probabilidad_Rotación | Riesgo |
|---|---|---|---|---|---|---|
Soltero | No | No_Viaja | 5,000 | 15 | 0.06843696 | Bajo |
Casado | Si | Raramente | 2,500 | 5 | 0.33949226 | Medio |
Divorciado | Si | Frecuentemente | 500 | 1 | 0.50408553 | Alto |
Utilidad del Modelo Predictivo en la Gestión de Personal Este modelo permite predecir el riesgo de rotación y tomar medidas para retener talento.
Identificación temprana: Detecta empleados con alta probabilidad de renunciar, permitiendo intervenir a tiempo.
Estrategias personalizadas: Según el nivel de riesgo, la empresa puede ofrecer incentivos, mejorar condiciones laborales o implementar planes de crecimiento.
Decisiones basadas en datos: Permite identificar patrones y ajustar políticas para mejorar la retención.
Conclusión: Es una herramienta clave para gestionar el talento, mejorar la satisfacción laboral y reducir costos.