0.0.1 Primero se realiza una exploración de datos, para verificar el estado del dataset. buscando datos faltantes, verificando composición de datos entre otros.

# VALIDACIÓN DE CALIDAD DE DATOS:

# 1. Estructura básica
cat("   - Observaciones:", nrow(rotacion), "\n")
##    - Observaciones: 1470
cat("   - Variables:", ncol(rotacion), "\n")
##    - Variables: 24
# 2. Análisis de missing values
missing_summary <- miss_var_summary(rotacion)
print(missing_summary)
## # A tibble: 24 × 3
##    variable               n_miss pct_miss
##    <chr>                   <int>    <num>
##  1 Rotación                    0        0
##  2 Edad                        0        0
##  3 Viaje de Negocios           0        0
##  4 Departamento                0        0
##  5 Distancia_Casa              0        0
##  6 Educación                   0        0
##  7 Campo_Educación             0        0
##  8 Satisfacción_Ambiental      0        0
##  9 Genero                      0        0
## 10 Cargo                       0        0
## # ℹ 14 more rows
if(any(missing_summary$n_miss > 0)) {
  cat("   ⚠️  EXISTEN VALORES MISSING\n")
} else {
  cat("   ✅ NO HAY VALORES MISSING\n")
}
##    ✅ NO HAY VALORES MISSING
# 3. Verificar valores únicos de variables clave
cat("Departamento:", unique(rotacion$Departamento), "\n")
## Departamento: Ventas IyD RH
cat("Estado_Civil:", unique(rotacion$Estado_Civil), "\n")
## Estado_Civil: Soltero Casado Divorciado
cat("Horas_Extra:", unique(rotacion$Horas_Extra), "\n")
## Horas_Extra: Si No
cat("Rotación:", unique(rotacion$Rotación), "\n")
## Rotación: Si No
# 4. Preparar datos limpios
rotacion_clean <- rotacion
cat("\n4. DATOS PREPARADOS PARA ANÁLISIS\n")
## 
## 4. DATOS PREPARADOS PARA ANÁLISIS

1 Selección de variables

1.0.0.1 Para el análisis esta actividad, se toma como variables categóricas: horas extras, estado civil del colaborador y el departamento en el cual trabaja. Como hipótesis, tenemos primero, una persona soltera le facilitara el cambiar de trabajo, ya que no tendrá el mismo tipo de compromisos que un colaborador, que este casado o tenga una familia. Además, si esta misma persona, realiza varias horas extras durante la semana o el mes, esto le desmotivara o agotara, impulsando la idea de buscar un empleo donde no deba realizar horas extras muy seguido. Por último, se verifica los departamentos donde hay mayor rotación, con el fin de validar si son departamentos muy exigentes o que agoten al personal.
1.0.0.2 En las variables cuantitativas, seleccionamos el sueldo, años desde el ultimo ascenso y la edad de una persona. Nuevamente, una persona joven que perciba un sueldo que no le garantice un bienestar o calidad de vida adecuado, buscara otras opciones sumado a esto, aquellos que no han sido promocionados en años podría generar frustración y querrán buscar una posición acorde con su experiencia. Finalmente, una persona joven buscara siempre crecimiento profesional y estabilidad; por tal motivo será más factible que alguien joven, busque alternativas y como consecuencia dejar la organización.

2 2. Analisis univariado

2.0.0.1 En el análisis univariado, primero identificamos el porcentaje de personal que cambio de empleo en la organización, como vemos en la Figura 1. 237 que equivale al 16,1% del personal cambio de puesto de trabajo, mientras el 1233 o el 83,9% se mantuvo en la empresa.
# Variable respuesta: Rotación
rotacion_clean <- rotacion_clean %>%
  mutate(Rotacion_bin = ifelse(Rotación == "Si", 1, 0))

tabla_rotacion <- table(rotacion_clean$Rotación)
prop_rotacion <- prop.table(tabla_rotacion) * 100

cat("No rotó:", tabla_rotacion["No"], "(", round(prop_rotacion["No"], 1), "%)\n")
## No rotó: 1233 ( 83.9 %)
cat("Sí rotó:", tabla_rotacion["Si"], "(", round(prop_rotacion["Si"], 1), "%)\n\n")
## Sí rotó: 237 ( 16.1 %)
# Gráfico de rotación
ggplot(rotacion_clean, aes(x = Rotación, fill = Rotación)) +
  geom_bar() +
  geom_text(stat = 'count', aes(label = ..count..), vjust = -0.5) +
  labs(title = "Figura 1.Distribución de Rotación de Empleados",
       x = "", y = "Frecuencia") +
  theme_minimal()

2.1 variables categoricas

2.1.0.1 Al revisar las variables categóricas seleccionadas para el ejercicio, nos muestra que el 28% del equipo de trabajo realiza horas extras. Referente el estado civil, el 45,8% de los colaboradores, se encuentran casados; mientras el 32% y 22,2% se encuentran solteros y divorciados respectivamente, al juntar estos porcentajes el 54,2% equivale al personal sin pareja. Además, el departamento con el mayor porcentaje de empleados es el de I&D con un 65,4%, mientras ventas y recursos humanos cuentan con un 30,3% y un 4,3%.
# Horas Extra
ggplot(rotacion_clean, aes(x = Horas_Extra)) +
  geom_bar(aes(y = after_stat(count/sum(count)*100)), fill = "steelblue") +
  geom_text(aes(label = scales::percent(after_stat(count/sum(count)), accuracy = 0.1),
                y = after_stat(count/sum(count)*100)),
            stat = "count", vjust = -0.5, size = 3) +
  labs(title = "Figura 2. Distribución de Horas Extra", x = "", y = "Porcentaje (%)") +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  theme_minimal()

# Estado Civil  
ggplot(rotacion_clean, aes(x = fct_infreq(Estado_Civil))) +
  geom_bar(aes(y = after_stat(count/sum(count)*100)), fill = "darkred") +
  geom_text(aes(label = scales::percent(after_stat(count/sum(count)), accuracy = 0.1),
                y = after_stat(count/sum(count)*100)),
            stat = "count", vjust = -0.5, size = 3) +
  labs(title = "Figura 3. Distribución por Estado Civil", x = "", y = "Porcentaje (%)") +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  theme_minimal()

# Departamento
ggplot(rotacion_clean, aes(x = fct_infreq(Departamento))) +
  geom_bar(aes(y = after_stat(count/sum(count)*100)), fill = "darkgreen") +
  geom_text(aes(label = scales::percent(after_stat(count/sum(count)), accuracy = 0.1),
                y = after_stat(count/sum(count)*100)),
            stat = "count", vjust = -0.5, size = 3) +
  labs(title = "Figura 4. Distribución por Departamento", x = "", y = "Porcentaje (%)") +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

2.2 variables cuantitativas

2.2.0.1 Al realizar el análisis de las variables cuantitativas, en el ingreso mensual, el sueldo mínimo es de aproximadamente 1000 dólares, el promedio es de aproximadamente 6500-7500 dólares y la mediana es de 5000 dólares. La diferencia entre la media (6500-7500) y la mediana (5000) indica que existe un grupo pequeño que percibe salarios muy elevados, lo que eleva el promedio general por encima del ingreso típico. Además, dado que la mediana es 5000, exactamente el 50% de la población recibe un salario inferior a este valor
2.2.0.2 En asensos o promociones, la mediana indica 1 año, podemos definir que la mitad de los colaboradores han sido promocionados en el ultimo año. No obstante, se evidencia un grupo que no ha sido promovido en mucho tiempo, un máximo de 15 años sin promociones.
2.2.0.3 Las edades del equipo de trabajo, encontramos un promedio de 36 años de estos el 25% tiene menos de 30 años y otro 25% que supera los 43 años.
# Función para análisis
analisis_univariado <- function(variable, nombre, color) {
  cat(paste("\n", strrep("=", 60), "\n"))
  cat(paste("RESUMEN ESTADÍSTICO:", nombre, "\n"))
  cat(paste(strrep("=", 60), "\n"))
  
  # Calcular estadísticas
  estadisticas <- data.frame(
    Estadístico = c("Mínimo", "1er Cuartil", "Mediana", "Media", "3er Cuartil", "Máximo", 
                   "Desviación Estándar", "Varianza", "IQR", "Coef. Variación", "NAs"),
    Valor = c(
      min(variable, na.rm = TRUE),
      quantile(variable, 0.25, na.rm = TRUE),
      median(variable, na.rm = TRUE),
      mean(variable, na.rm = TRUE),
      quantile(variable, 0.75, na.rm = TRUE),
      max(variable, na.rm = TRUE),
      sd(variable, na.rm = TRUE),
      var(variable, na.rm = TRUE),
      IQR(variable, na.rm = TRUE),
      sd(variable, na.rm = TRUE) / mean(variable, na.rm = TRUE),
      sum(is.na(variable))
    )
  )
  
  # Formatear números
  estadisticas$Valor <- round(estadisticas$Valor, 3)
  
  # Mostrar tabla formateada
  print(knitr::kable(estadisticas, align = c('l', 'r'), 
                     caption = paste("Tabla Estadística:", nombre)))
  
  # Crear gráfico
  p <- ggplot(rotacion_clean, aes(x = variable)) +
    geom_histogram(fill = color, alpha = 0.7, bins = 30, color = "white") +
    geom_vline(aes(xintercept = mean(variable, na.rm = TRUE)), 
               color = "red", linetype = "dashed", size = 1) +
    geom_vline(aes(xintercept = median(variable, na.rm = TRUE)), 
               color = "blue", linetype = "dashed", size = 1) +
    labs(title = nombre, 
         subtitle = "Línea roja: Media | Línea azul: Mediana",
         x = nombre, y = "Frecuencia") +
    theme_minimal()
  
  print(p)
  
  return(estadisticas)
}

# Aplicar a variables seleccionadas
resultado1 <- analisis_univariado(rotacion_clean$Ingreso_Mensual, "Figura 5. Ingreso Mensual", "red")
## 
##  ============================================================ 
## RESUMEN ESTADÍSTICO: Figura 5. Ingreso Mensual 
## ============================================================
## 
## 
## Table: Tabla Estadística: Figura 5. Ingreso Mensual
## 
## |Estadístico         |        Valor|
## |:-------------------|------------:|
## |Mínimo              |     1009.000|
## |1er Cuartil         |     2911.000|
## |Mediana             |     4919.000|
## |Media               |     6502.931|
## |3er Cuartil         |     8379.000|
## |Máximo              |    19999.000|
## |Desviación Estándar |     4707.957|
## |Varianza            | 22164857.072|
## |IQR                 |     5468.000|
## |Coef. Variación     |        0.724|
## |NAs                 |        0.000|

resultado2 <- analisis_univariado(rotacion_clean$Años_ultima_promoción, "Figura 6. Años desde Última Promoción", "blue")
## 
##  ============================================================ 
## RESUMEN ESTADÍSTICO: Figura 6. Años desde Última Promoción 
## ============================================================
## 
## 
## Table: Tabla Estadística: Figura 6. Años desde Última Promoción
## 
## |Estadístico         |  Valor|
## |:-------------------|------:|
## |Mínimo              |  0.000|
## |1er Cuartil         |  0.000|
## |Mediana             |  1.000|
## |Media               |  2.188|
## |3er Cuartil         |  3.000|
## |Máximo              | 15.000|
## |Desviación Estándar |  3.222|
## |Varianza            | 10.384|
## |IQR                 |  3.000|
## |Coef. Variación     |  1.473|
## |NAs                 |  0.000|

resultado3 <- analisis_univariado(rotacion_clean$Edad, "Figura 7. Edad", "green")
## 
##  ============================================================ 
## RESUMEN ESTADÍSTICO: Figura 7. Edad 
## ============================================================
## 
## 
## Table: Tabla Estadística: Figura 7. Edad
## 
## |Estadístico         |  Valor|
## |:-------------------|------:|
## |Mínimo              | 18.000|
## |1er Cuartil         | 30.000|
## |Mediana             | 36.000|
## |Media               | 36.924|
## |3er Cuartil         | 43.000|
## |Máximo              | 60.000|
## |Desviación Estándar |  9.136|
## |Varianza            | 83.465|
## |IQR                 | 13.000|
## |Coef. Variación     |  0.247|
## |NAs                 |  0.000|

3 Analisis bivariado

3.0.0.1 Al realizar el análisis bivariado, entre las horas extras y el personal que continuo o abandonó la empresa; se obtiene un p<0,05 lo cual nos indica una relación significativa entre ambas variables (horas extras y rotación). Al revisar la Figura 8, se observa que el 89,6% del personal que no realizó horas extras continúo vinculado a la organización. Caso opuesto, de aquellos que realizaron horas extras el 30,5% decidió cambiar de trabajo.
3.0.0.2 El análisis entre estado civil y rotación del personal, nos indica un P = 0, el cual nos indica una asociación significativa, así mismo, al revisar la Figura 9, tanto casados como divorciados presentaron un 12% y un 10% de rotación. Sin embargo, los solteros presentaron un 25% de abandono de la compañía.
3.0.0.3 Para el análisis entre área o departamento y la rotación, nuevamente se obtuvo un P< 0,005 por lo cual también existe una relación entre la rotación y departamentos. En la Figura 10, aunque el departamento de I&D cuenta con la mayor cantidad de personal en este estudio, tiene la tasa de rotación mas baja (14%), mientras el área de ventas tiene la tasa de rotación más alta con un 20,6% y muy de cerca recursos humanos con un 19%.
# Función para análisis bivariado categórico 
analisis_bivariado_cat <- function(var_cat, nombre_var, numero_figura) {
  # Crear tablas
  tabla <- table(rotacion_clean[[var_cat]], rotacion_clean$Rotacion_bin)
  prop_tabla <- prop.table(tabla, margin = 1) * 100
  
  # Encabezado organizado
  cat("\n", rep("=", 60), "\n", sep = "")
  cat("ANÁLISIS:", nombre_var, "vs ROTACIÓN\n")
  cat(rep("=", 60), "\n\n", sep = "")
  
  # Tabla de frecuencias absolutas 
  cat("FRECUENCIAS ABSOLUTAS:\n")
  cat(rep("-", 40), "\n", sep = "")
  tabla_con_margenes <- addmargins(tabla)
  # Asignar nombres descriptivos a las columnas
  colnames(tabla_con_margenes) <- c("No Rotó", "Sí Rotó", "Total")
  rownames(tabla_con_margenes) <- c(rownames(tabla), "Total")
  print(tabla_con_margenes)
  
  # Tabla de porcentajes 
  cat("\nPORCENTAJES POR FILA (%):\n")
  cat(rep("-", 40), "\n", sep = "")
  prop_df <- as.data.frame.matrix(prop_tabla)
  colnames(prop_df) <- c("No Rotó (%)", "Sí Rotó (%)")
  # Agregar totales
  prop_df$Total <- rowSums(prop_df)
  print(round(prop_df, 1))
  
  # Test chi-cuadrado con interpretación
  test_chi <- chisq.test(tabla)
  cat("\nPRUEBA ESTADÍSTICA:\n")
  cat(rep("-", 40), "\n", sep = "")
  cat("Chi-cuadrado =", round(test_chi$statistic, 3), "\n")
  cat("p-value =", round(test_chi$p.value, 4), "\n")
  
  # Interpretación del resultado
  if (test_chi$p.value < 0.05) {
    cat("Resultado: RELACIÓN SIGNIFICATIVA (p < 0.05)\n")
    cat("→ Existe asociación entre", nombre_var, "y la rotación\n")
  } else {
    cat("Resultado: NO HAY RELACIÓN SIGNIFICATIVA (p ≥ 0.05)\n")
    cat("→ No hay evidencia de asociación entre", nombre_var, "y la rotación\n")
  }
  
  # Preparar datos para el gráfico 
  datos_grafico <- rotacion_clean %>%
    group_by(!!sym(var_cat), Rotacion_bin) %>%
    summarise(n = n(), .groups = 'drop') %>%
    group_by(!!sym(var_cat)) %>%
    mutate(
      porcentaje = n / sum(n) * 100,
      etiqueta = paste0(round(porcentaje, 1), "%")
    )
  
  # Gráfico 
  grafico <- ggplot(datos_grafico, aes(x = !!sym(var_cat), y = n, fill = factor(Rotacion_bin))) +
    geom_bar(stat = "identity", position = "fill") +
    geom_text(aes(label = etiqueta), 
              position = position_fill(vjust = 0.5),
              size = 3, color = "white", fontface = "bold") +
    labs(title = paste("Figura", numero_figura, ". Rotación por", nombre_var),
         subtitle = paste("Chi-cuadrado p-value =", round(test_chi$p.value, 4)),
         x = nombre_var, y = "Proporción") +
    scale_fill_manual(values = c("0" = "steelblue", "1" = "tomato"),
                      labels = c("No Rotó", "Sí Rotó"), 
                      name = "Rotación") +
    scale_y_continuous(labels = scales::percent) +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1),
          plot.title = element_text(face = "bold", size = 14))
  
  return(grafico)
}

# Aplicar a variables categóricas c
cat("ANÁLISIS BIVARIADO DE ROTACIÓN LABORAL\n")
## ANÁLISIS BIVARIADO DE ROTACIÓN LABORAL
cat(rep("=", 50), "\n") 
## = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
resultado1 <- analisis_bivariado_cat("Horas_Extra", "Horas Extra", 8)
## 
## ============================================================
## ANÁLISIS: Horas Extra vs ROTACIÓN
## ============================================================
## 
## FRECUENCIAS ABSOLUTAS:
## ----------------------------------------
##        
##         No Rotó Sí Rotó Total
##   No        944     110  1054
##   Si        289     127   416
##   Total    1233     237  1470
## 
## PORCENTAJES POR FILA (%):
## ----------------------------------------
##    No Rotó (%) Sí Rotó (%) Total
## No        89.6        10.4   100
## Si        69.5        30.5   100
## 
## PRUEBA ESTADÍSTICA:
## ----------------------------------------
## Chi-cuadrado = 87.564 
## p-value = 0 
## Resultado: RELACIÓN SIGNIFICATIVA (p < 0.05)
## → Existe asociación entre Horas Extra y la rotación
resultado2 <- analisis_bivariado_cat("Estado_Civil", "Estado Civil", 9) 
## 
## ============================================================
## ANÁLISIS: Estado Civil vs ROTACIÓN
## ============================================================
## 
## FRECUENCIAS ABSOLUTAS:
## ----------------------------------------
##             
##              No Rotó Sí Rotó Total
##   Casado         589      84   673
##   Divorciado     294      33   327
##   Soltero        350     120   470
##   Total         1233     237  1470
## 
## PORCENTAJES POR FILA (%):
## ----------------------------------------
##            No Rotó (%) Sí Rotó (%) Total
## Casado            87.5        12.5   100
## Divorciado        89.9        10.1   100
## Soltero           74.5        25.5   100
## 
## PRUEBA ESTADÍSTICA:
## ----------------------------------------
## Chi-cuadrado = 46.164 
## p-value = 0 
## Resultado: RELACIÓN SIGNIFICATIVA (p < 0.05)
## → Existe asociación entre Estado Civil y la rotación
resultado3 <- analisis_bivariado_cat("Departamento", "Departamento", 10)
## 
## ============================================================
## ANÁLISIS: Departamento vs ROTACIÓN
## ============================================================
## 
## FRECUENCIAS ABSOLUTAS:
## ----------------------------------------
##         
##          No Rotó Sí Rotó Total
##   IyD        828     133   961
##   RH          51      12    63
##   Ventas     354      92   446
##   Total     1233     237  1470
## 
## PORCENTAJES POR FILA (%):
## ----------------------------------------
##        No Rotó (%) Sí Rotó (%) Total
## IyD           86.2        13.8   100
## RH            81.0        19.0   100
## Ventas        79.4        20.6   100
## 
## PRUEBA ESTADÍSTICA:
## ----------------------------------------
## Chi-cuadrado = 10.796 
## p-value = 0.0045 
## Resultado: RELACIÓN SIGNIFICATIVA (p < 0.05)
## → Existe asociación entre Departamento y la rotación
# Mostrar gráficos
print(resultado1)

print(resultado2)

print(resultado3)

3.0.0.4 En el análisis de las variables cuantitativas para el salario vs la rotación, aquellos empleados que continuaron en sus puestos perciben un promedio de 6832 dólares, mientras, los que decidieron dejar su puesto percibieron en promedio 4787 dólares; la diferencia entre ambos es de 2045 dólares. Además, aquellos que cambiaron de trabajo, la mitad percibían un salario superior a 3200 dólares, pero algunos, perciben un salario superior a 5000 dólares, como se observa en la Figura 11.
3.0.0.5 Sin embargo, al revisar los años de promoción contra la rotación, hay una pequeña diferencia entre quienes cambiaron de puesto de trabajo y aquellos que permanecieron (3 meses y medio), además en ambos grupos las promociones se han dado recientemente. Por otro lado, tenemos un P>0, por ende esta apreciación no es estadísticamente significativa.
3.0.0.6 Referente la edad vs la rotación, se observa una diferencia de promedios de 4 años, en el grupo que continúo ejerciendo sus funciones, encontramos un promedio de 37,7 años, caso contrario, aquellos que decidieron no continuar presentan un promedio de edad de 33 años. Además, la mitad del personal que roto, tiene una edad inferior a los 32 años; en ambos grupos también vemos personas con edades entre 58 – 60 años. Por ultimo el P<0 por lo cual, la edad y la rotación tiene un relación significativa.
# Análisis bivariado para variables numéricas con mejor presentación
analisis_bivariado_num <- function(var_num, nombre_var, numero_figura) {
  # Realizar test t
  test_t <- t.test(rotacion_clean[[var_num]] ~ rotacion_clean$Rotacion_bin)
  
  # Calcular estadísticas descriptivas
  stats_no_roto <- rotacion_clean[[var_num]][rotacion_clean$Rotacion_bin == 0]
  stats_roto <- rotacion_clean[[var_num]][rotacion_clean$Rotacion_bin == 1]
  
  # Encabezado organizado
  cat("\n", rep("=", 60), "\n", sep = "")
  cat("ANÁLISIS:", nombre_var, "vs ROTACIÓN\n")
  cat(rep("=", 60), "\n\n", sep = "")
  
  # Tabla de estadísticas descriptivas
  cat("ESTADÍSTICAS DESCRIPTIVAS:\n")
  cat(rep("-", 50), "\n", sep = "")
  
  tabla_stats <- data.frame(
    Estadístico = c("n", "Media", "Desviación Estándar", "Mínimo", "Mediana", "Máximo"),
    No_Rotó = c(
      length(stats_no_roto),
      round(mean(stats_no_roto), 2),
      round(sd(stats_no_roto), 2),
      round(min(stats_no_roto), 2),
      round(median(stats_no_roto), 2),
      round(max(stats_no_roto), 2)
    ),
    Rotó = c(
      length(stats_roto),
      round(mean(stats_roto), 2),
      round(sd(stats_roto), 2),
      round(min(stats_roto), 2),
      round(median(stats_roto), 2),
      round(max(stats_roto), 2)
    )
  )
  
  colnames(tabla_stats) <- c("Estadístico", "No Rotó", "Sí Rotó")
  print(tabla_stats, row.names = FALSE)
  
  # Test t-student
  cat("\nPRUEBA T-STUDENT (Comparación de Medias):\n")
  cat(rep("-", 50), "\n", sep = "")
  cat("Diferencia de medias:", round(test_t$estimate[1] - test_t$estimate[2], 2), "\n")
  cat("t-value:", round(test_t$statistic, 3), "\n")
  cat("p-value:", round(test_t$p.value, 4), "\n")
  cat("Intervalo de confianza (95%): [", 
      round(test_t$conf.int[1], 2), ", ", 
      round(test_t$conf.int[2], 2), "]\n", sep = "")
  
  # Interpretación del resultado
  if (test_t$p.value < 0.05) {
    cat("Resultado: DIFERENCIA SIGNIFICATIVA (p < 0.05)\n")
    cat("→ Existe diferencia significativa en", nombre_var, "entre grupos\n")
  } else {
    cat("Resultado: NO HAY DIFERENCIA SIGNIFICATIVA (p ≥ 0.05)\n")
    cat("→ No hay evidencia de diferencia en", nombre_var, "entre grupos\n")
  }
  
  # Gráfico con numeración de figura
  grafico <- ggplot(rotacion_clean, aes(x = factor(Rotacion_bin), y = .data[[var_num]], 
                             fill = factor(Rotacion_bin))) +
    geom_boxplot(alpha = 0.8) +
    stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white") +
    labs(title = paste("Figura", numero_figura, ".", nombre_var, "vs Rotación"),
         subtitle = paste("Test t: p =", round(test_t$p.value, 4)),
         x = "Rotación", 
         y = nombre_var,
         caption = paste("Puntos blancos = Media | n(total) =", nrow(rotacion_clean))) +
    scale_fill_manual(values = c("0" = "steelblue", "1" = "tomato"),
                      labels = c("No Rotó", "Sí Rotó")) +
    scale_x_discrete(labels = c("No Rotó", "Sí Rotó")) +
    theme_minimal() +
    theme(legend.position = "none",
          plot.title = element_text(face = "bold", size = 14),
          axis.text = element_text(size = 10))
  
  return(grafico)
}

# Aplicar a variables numéricas con numeración
cat("ANÁLISIS BIVARIADO - VARIABLES NUMÉRICAS\n")
## ANÁLISIS BIVARIADO - VARIABLES NUMÉRICAS
cat(rep("=", 50), "\n") 
## = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Especificar el número de figura para cada análisis (comenzando desde 11)
resultado_num1 <- analisis_bivariado_num("Ingreso_Mensual", "Ingreso Mensual", 11)
## 
## ============================================================
## ANÁLISIS: Ingreso Mensual vs ROTACIÓN
## ============================================================
## 
## ESTADÍSTICAS DESCRIPTIVAS:
## --------------------------------------------------
##          Estadístico  No Rotó  Sí Rotó
##                    n  1233.00   237.00
##                Media  6832.74  4787.09
##  Desviación Estándar  4818.21  3640.21
##               Mínimo  1051.00  1009.00
##              Mediana  5204.00  3202.00
##               Máximo 19999.00 19859.00
## 
## PRUEBA T-STUDENT (Comparación de Medias):
## --------------------------------------------------
## Diferencia de medias: 2045.65 
## t-value: 7.483 
## p-value: 0 
## Intervalo de confianza (95%): [1508.24, 2583.05]
## Resultado: DIFERENCIA SIGNIFICATIVA (p < 0.05)
## → Existe diferencia significativa en Ingreso Mensual entre grupos
resultado_num2 <- analisis_bivariado_num("Años_ultima_promoción", "Años desde Última Promoción", 12) 
## 
## ============================================================
## ANÁLISIS: Años desde Última Promoción vs ROTACIÓN
## ============================================================
## 
## ESTADÍSTICAS DESCRIPTIVAS:
## --------------------------------------------------
##          Estadístico No Rotó Sí Rotó
##                    n 1233.00  237.00
##                Media    2.23    1.95
##  Desviación Estándar    3.23    3.15
##               Mínimo    0.00    0.00
##              Mediana    1.00    1.00
##               Máximo   15.00   15.00
## 
## PRUEBA T-STUDENT (Comparación de Medias):
## --------------------------------------------------
## Diferencia de medias: 0.29 
## t-value: 1.288 
## p-value: 0.1987 
## Intervalo de confianza (95%): [-0.15, 0.73]
## Resultado: NO HAY DIFERENCIA SIGNIFICATIVA (p ≥ 0.05)
## → No hay evidencia de diferencia en Años desde Última Promoción entre grupos
resultado_num3 <- analisis_bivariado_num("Edad", "Edad", 13)
## 
## ============================================================
## ANÁLISIS: Edad vs ROTACIÓN
## ============================================================
## 
## ESTADÍSTICAS DESCRIPTIVAS:
## --------------------------------------------------
##          Estadístico No Rotó Sí Rotó
##                    n 1233.00  237.00
##                Media   37.56   33.61
##  Desviación Estándar    8.89    9.69
##               Mínimo   18.00   18.00
##              Mediana   36.00   32.00
##               Máximo   60.00   58.00
## 
## PRUEBA T-STUDENT (Comparación de Medias):
## --------------------------------------------------
## Diferencia de medias: 3.95 
## t-value: 5.829 
## p-value: 0 
## Intervalo de confianza (95%): [2.62, 5.29]
## Resultado: DIFERENCIA SIGNIFICATIVA (p < 0.05)
## → Existe diferencia significativa en Edad entre grupos
# Mostrar gráficos
print(resultado_num1)

print(resultado_num2)

print(resultado_num3)

4 Modelo de regresión logistica

cat("=== 4. MODELO DE REGRESIÓN LOGÍSTICA ===\n\n")
## === 4. MODELO DE REGRESIÓN LOGÍSTICA ===
# Preparar datos para el modelo
rotacion_modelo <- rotacion_clean %>%
  mutate(
    Rotacion_bin = as.factor(Rotacion_bin),
    Horas_Extra = as.factor(Horas_Extra),
    Estado_Civil = as.factor(Estado_Civil),
    Departamento = as.factor(Departamento)
  )

# Ajustar modelo
modelo <- glm(Rotacion_bin ~ Ingreso_Mensual + Años_ultima_promoción + Edad +
                Horas_Extra + Estado_Civil + Departamento,
              data = rotacion_modelo, family = "binomial")

cat("RESUMEN DEL MODELO:\n")
## RESUMEN DEL MODELO:
print(summary(modelo))
## 
## Call:
## glm(formula = Rotacion_bin ~ Ingreso_Mensual + Años_ultima_promoción + 
##     Edad + Horas_Extra + Estado_Civil + Departamento, family = "binomial", 
##     data = rotacion_modelo)
## 
## Coefficients:
##                          Estimate Std. Error z value Pr(>|z|)    
## (Intercept)            -1.104e+00  3.521e-01  -3.134 0.001725 ** 
## Ingreso_Mensual        -1.277e-04  2.754e-05  -4.636 3.55e-06 ***
## Años_ultima_promoción   5.140e-02  2.796e-02   1.838 0.066040 .  
## Edad                   -2.859e-02  1.014e-02  -2.818 0.004826 ** 
## Horas_ExtraSi           1.495e+00  1.572e-01   9.512  < 2e-16 ***
## Estado_CivilDivorciado -2.945e-01  2.294e-01  -1.284 0.199222    
## Estado_CivilSoltero     8.493e-01  1.698e-01   5.001 5.72e-07 ***
## DepartamentoRH          7.061e-01  3.567e-01   1.980 0.047744 *  
## DepartamentoVentas      6.166e-01  1.664e-01   3.705 0.000211 ***
## ---
## 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: 1098.6  on 1461  degrees of freedom
## AIC: 1116.6
## 
## Number of Fisher Scoring iterations: 5
# Tabla de resultados formateada
resultados_tidy <- tidy(modelo, conf.int = TRUE, exponentiate = TRUE)

# Crear nombres legibles para las variables
resultados_tidy$Variable <- resultados_tidy$term
resultados_tidy$Variable <- gsub("Horas_Extra", "Horas Extra: ", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("Estado_Civil", "Estado Civil: ", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("Departamento", "Departamento: ", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("Ingreso_Mensual", "Ingreso Mensual", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("Años_ultima_promoción", "Años última promoción", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("Edad", "Edad", resultados_tidy$Variable)
resultados_tidy$Variable <- gsub("^\\(Intercept\\)", "Intercepto", resultados_tidy$Variable)

# Crear tabla formateada
tabla_final <- resultados_tidy %>%
  mutate(
    across(c(estimate, std.error, statistic, p.value, conf.low, conf.high), 
           ~round(., 3)),
    Significancia = case_when(
      p.value < 0.001 ~ "***",
      p.value < 0.01 ~ "**", 
      p.value < 0.05 ~ "*",
      p.value < 0.1 ~ ".",
      TRUE ~ ""
    )
  ) %>%
  select(Variable, `Odds Ratio` = estimate, `Error Estándar` = std.error,
         `Valor z` = statistic, `Valor p` = p.value, Significancia,
         `IC 95% Bajo` = conf.low, `IC 95% Alto` = conf.high)

kbl(tabla_final, caption = "Resultados del Modelo de Regresión Logística") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Resultados del Modelo de Regresión Logística
Variable Odds Ratio Error Estándar Valor z Valor p Significancia IC 95% Bajo IC 95% Alto
Intercepto 0.332 0.352 -3.134 0.002 ** 0.166 0.662
Ingreso Mensual 1.000 0.000 -4.636 0.000 *** 1.000 1.000
Años última promoción 1.053 0.028 1.838 0.066 . 0.995 1.111
Edad 0.972 0.010 -2.818 0.005 ** 0.952 0.991
Horas Extra: Si 4.458 0.157 9.512 0.000 *** 3.282 6.080
Estado Civil: Divorciado 0.745 0.229 -1.284 0.199 0.470 1.158
Estado Civil: Soltero 2.338 0.170 5.001 0.000 *** 1.679 3.269
Departamento: RH 2.026 0.357 1.980 0.048
0.970 3.967
Departamento: Ventas 1.853 0.166 3.705 0.000 *** 1.336 2.567
4.0.0.1 Al realizar el modelo, en la tabla observamos que las horas extras tiene el valor de OR más alto, como consecuencia el hacer horas extras, representa el mayor riesgo para que un colaborador decida dejar su puesto de trabajo. Además de esto, aquellos que se encuentran solteros, en el departamento de ventas o recursos humanos, tendrán una mayor posibilidad de dejar su puesto de trabajo. Caso contrario, entre mayor sea la persona tendrá menos posibilidades de dejar su cargo y también, si percibe un buen sueldo es probable que continue en su puesto.
# Interpretación de resultados
cat("INTERPRETACIÓN DE RESULTADOS:\n\n")
## INTERPRETACIÓN DE RESULTADOS:
vars_significativas <- resultados_tidy %>%
  filter(p.value < 0.05, !grepl("Intercepto", term))

if(nrow(vars_significativas) > 0) {
  cat("VARIABLES SIGNIFICATIVAS (p < 0.05):\n")
  for(i in 1:nrow(vars_significativas)) {
    or <- vars_significativas$estimate[i]
    var <- vars_significativas$Variable[i]
    
    if(or > 1) {
      cat("•", var, ": AUMENTA probabilidad de rotación (OR =", round(or, 2), ")\n")
    } else {
      cat("•", var, ": DISMINUYE probabilidad de rotación (OR =", round(or, 2), ")\n")
    }
  }
} else {
  cat("No hay variables significativas al nivel 0.05\n")
}
## VARIABLES SIGNIFICATIVAS (p < 0.05):
## • Intercepto : DISMINUYE probabilidad de rotación (OR = 0.33 )
## • Ingreso Mensual : DISMINUYE probabilidad de rotación (OR = 1 )
## • Edad : DISMINUYE probabilidad de rotación (OR = 0.97 )
## • Horas Extra: Si : AUMENTA probabilidad de rotación (OR = 4.46 )
## • Estado Civil: Soltero : AUMENTA probabilidad de rotación (OR = 2.34 )
## • Departamento: RH : AUMENTA probabilidad de rotación (OR = 2.03 )
## • Departamento: Ventas : AUMENTA probabilidad de rotación (OR = 1.85 )

5 Evaluación del modelo

cat("=== 5. EVALUACIÓN DEL MODELO ===\n\n")
## === 5. EVALUACIÓN DEL MODELO ===
# Predicciones y curva ROC
predicciones <- predict(modelo, type = "response")
roc_curve <- roc(rotacion_modelo$Rotacion_bin, predicciones)
auc_valor <- auc(roc_curve)

# Encabezado organizado
cat(rep("=", 60), "\n", sep = "")
## ============================================================
cat("EVALUACIÓN DEL MODELO DE PREDICCIÓN\n")
## EVALUACIÓN DEL MODELO DE PREDICCIÓN
cat(rep("=", 60), "\n\n", sep = "")
## ============================================================
cat("MÉTRICAS DE EVALUACIÓN:\n")
## MÉTRICAS DE EVALUACIÓN:
cat(rep("-", 40), "\n", sep = "")
## ----------------------------------------
# Crear tabla de métricas ROC
metricas_roc <- data.frame(
  Métrica = c("AUC (Área bajo curva ROC)", "Interpretación"),
  Valor = c(
    round(auc_valor, 3),
    if(auc_valor >= 0.9) "Excelente poder predictivo" 
    else if(auc_valor >= 0.8) "Buen poder predictivo"
    else if(auc_valor >= 0.7) "Poder predictivo aceptable"
    else "Poder predictivo limitado"
  )
)

print(metricas_roc, row.names = FALSE)
##                    Métrica                      Valor
##  AUC (Área bajo curva ROC)                      0.763
##             Interpretación Poder predictivo aceptable
# Gráfico ROC con numeración
cat("\n\nFigura 14. Curva ROC del Modelo Predictivo\n")
## 
## 
## Figura 14. Curva ROC del Modelo Predictivo
par(mar = c(5, 4, 4, 2) + 0.1)
plot(roc_curve, 
     main = "Figura 14. Curva ROC del Modelo Predictivo",
     col = "blue", lwd = 2.5,
     xlab = "1 - Especificidad (Tasa de Falsos Positivos)",
     ylab = "Sensibilidad (Tasa de Verdaderos Positivos)")
abline(a = 0, b = 1, lty = 2, col = "red", lwd = 1.5)
legend("bottomright", 
       legend = c(paste("AUC =", round(auc_valor, 3)), "Línea de referencia (AUC = 0.5)"),
       col = c("blue", "red"), 
       lwd = c(2.5, 1.5),
       lty = c(1, 2),
       cex = 0.8)
grid()

# Matriz de confusión
punto_corte <- 0.5
predicciones_class <- ifelse(predicciones > punto_corte, 1, 0)
conf_matrix <- confusionMatrix(as.factor(predicciones_class), rotacion_modelo$Rotacion_bin)

cat("\n", rep("=", 60), "\n", sep = "")
## 
## ============================================================
cat("MATRIZ DE CONFUSIÓN Y MÉTRICAS\n")
## MATRIZ DE CONFUSIÓN Y MÉTRICAS
cat(rep("=", 60), "\n\n", sep = "")
## ============================================================
# Matriz de confusión formateada
cat("MATRIZ DE CONFUSIÓN (Punto de corte = 0.5):\n")
## MATRIZ DE CONFUSIÓN (Punto de corte = 0.5):
cat(rep("-", 50), "\n", sep = "")
## --------------------------------------------------
matriz_bonita <- as.matrix(conf_matrix$table)
colnames(matriz_bonita) <- c("Real: No Rotó", "Real: Sí Rotó")
rownames(matriz_bonita) <- c("Pred: No Rotó", "Pred: Sí Rotó")

# Imprimir matriz con formato
matriz_impresa <- as.data.frame(matriz_bonita)
matriz_impresa$Total <- rowSums(matriz_bonita)

print(matriz_impresa)
##      Prediction     Reference Freq Total
## 1 Pred: No Rotó Real: No Rotó 1217  1413
## 2 Pred: Sí Rotó Real: No Rotó   16    57
## 3 Pred: No Rotó Real: Sí Rotó  196  1413
## 4 Pred: Sí Rotó Real: Sí Rotó   41    57
# Totales por columna
totales_col <- c("Total", colSums(matriz_bonita))
cat("\n")
print(totales_col, row.names = FALSE)
##               Real: No Rotó Real: Sí Rotó 
##       "Total"        "1233"         "237"
# Métricas de clasificación en tabla
cat("\nMÉTRICAS DE CLASIFICACIÓN:\n")
## 
## MÉTRICAS DE CLASIFICACIÓN:
cat(rep("-", 40), "\n", sep = "")
## ----------------------------------------
metricas_clasificacion <- data.frame(
  Métrica = c("Exactitud (Accuracy)", 
              "Sensibilidad (Recall)", 
              "Especificidad",
              "Precisión",
              "F1-Score"),
  Valor = c(
    round(conf_matrix$overall["Accuracy"], 3),
    round(conf_matrix$byClass["Sensitivity"], 3),
    round(conf_matrix$byClass["Specificity"], 3),
    round(conf_matrix$byClass["Precision"], 3),
    round(conf_matrix$byClass["F1"], 3)
  ),
  Descripción = c(
    "Porcentaje total de aciertos",
    "Capacidad de detectar NO rotación",
    "Capacidad de detectar SI rotación", 
    "Aciertos al predecir rotación",
    "Balance entre Precisión y Sensibilidad"
  )
)

print(metricas_clasificacion, row.names = FALSE)
##                Métrica Valor                            Descripción
##   Exactitud (Accuracy) 0.856           Porcentaje total de aciertos
##  Sensibilidad (Recall) 0.987      Capacidad de detectar NO rotación
##          Especificidad 0.173      Capacidad de detectar SI rotación
##              Precisión 0.861          Aciertos al predecir rotación
##               F1-Score 0.920 Balance entre Precisión y Sensibilidad
# Interpretación de métricas clave
cat("\nINTERPRETACIÓN DE RESULTADOS:\n")
## 
## INTERPRETACIÓN DE RESULTADOS:
cat(rep("-", 40), "\n", sep = "")
## ----------------------------------------
cat("• EXACTITUD:", round(conf_matrix$overall["Accuracy"] * 100, 1), "% -",
    if(conf_matrix$overall["Accuracy"] > 0.8) "MUY BUENA" 
    else if(conf_matrix$overall["Accuracy"] > 0.7) "ACEPTABLE" 
    else "BAJA", "\n")
## • EXACTITUD: 85.6 % - MUY BUENA
cat("• SENSIBILIDAD:", round(conf_matrix$byClass["Sensitivity"] * 100, 1), "% -",
    "Excelente para detectar NO rotación\n")
## • SENSIBILIDAD: 98.7 % - Excelente para detectar NO rotación
cat("• ESPECIFICIDAD:", round(conf_matrix$byClass["Specificity"] * 100, 1), "% -",
    "BAJA para detectar SI rotación\n")
## • ESPECIFICIDAD: 17.3 % - BAJA para detectar SI rotación
cat("\nRECOMENDACIÓN: El modelo es conservador - predice bien la NO rotación")
## 
## RECOMENDACIÓN: El modelo es conservador - predice bien la NO rotación
cat("\npero necesita mejorar la detección de empleados que SÍ rotarán.\n")
## 
## pero necesita mejorar la detección de empleados que SÍ rotarán.

6 Predicciones

6.0.0.1 En la parte de predicciones, le presentamos 3 casos al modelo con el objetivo de que determine el riesgo que el empleado renuncie. De este modo, podemos hacernos una idea de cuales empleados tienen más posibilidades de rotar según las condiciones en las que se encuentre.
cat("=== 6. PREDICCIONES Y ESTRATEGIAS ===\n\n")
## === 6. PREDICCIONES Y ESTRATEGIAS ===
# Encabezado organizado
cat(rep("=", 60), "\n", sep = "")
## ============================================================
cat("PREDICCIONES PARA PERFILES DE EMPLEADOS\n")
## PREDICCIONES PARA PERFILES DE EMPLEADOS
cat(rep("=", 60), "\n\n", sep = "")
## ============================================================
# Obtener valores válidos del dataset
deptos_validos <- unique(rotacion$Departamento)
estados_validos <- unique(rotacion$Estado_Civil)
horas_validas <- unique(rotacion$Horas_Extra)

cat("VALORES VÁLIDOS IDENTIFICADOS:\n")
## VALORES VÁLIDOS IDENTIFICADOS:
cat(rep("-", 35), "\n", sep = "")
## -----------------------------------
cat("• Departamentos:", paste(deptos_validos, collapse = ", "), "\n")
## • Departamentos: Ventas, IyD, RH
cat("• Estados civiles:", paste(estados_validos, collapse = ", "), "\n")
## • Estados civiles: Soltero, Casado, Divorciado
cat("• Horas extra:", paste(horas_validas, collapse = ", "), "\n\n")
## • Horas extra: Si, No
# Crear empleados hipotéticos con valores VÁLIDOS
empleados_hipoteticos <- data.frame(
  Perfil = c("Alto Riesgo", "Riesgo Moderado", "Bajo Riesgo"),
  Ingreso_Mensual = c(2500, 4500, 6500),
  Años_ultima_promoción = c(5, 2, 1),
  Edad = c(28, 35, 42),
  Horas_Extra = factor(c("Si", "Si", "No"), levels = horas_validas),
  Estado_Civil = factor(c("Soltero", "Casado", "Casado"), levels = estados_validos),
  Departamento = factor(c(deptos_validos[1], deptos_validos[2], deptos_validos[1]), 
                       levels = deptos_validos)
)

# Realizar predicciones
predicciones_hipo <- predict(modelo, newdata = empleados_hipoteticos, type = "response")
empleados_hipoteticos$Probabilidad_Rotacion <- round(predicciones_hipo, 3)
empleados_hipoteticos$Porcentaje_Rotacion <- round(predicciones_hipo * 100, 1)

# Tabla de predicciones formateada
cat("TABLA DE PREDICCIONES:\n")
## TABLA DE PREDICCIONES:
cat(rep("-", 80), "\n", sep = "")
## --------------------------------------------------------------------------------
tabla_predicciones <- empleados_hipoteticos %>%
  select(Perfil, Ingreso_Mensual, Edad, Horas_Extra, Estado_Civil, 
         Departamento, Años_ultima_promoción, Porcentaje_Rotacion)

print(tabla_predicciones, row.names = FALSE)
##           Perfil Ingreso_Mensual Edad Horas_Extra Estado_Civil Departamento
##      Alto Riesgo            2500   28          Si      Soltero       Ventas
##  Riesgo Moderado            4500   35          Si       Casado          IyD
##      Bajo Riesgo            6500   42          No       Casado       Ventas
##  Años_ultima_promoción Porcentaje_Rotacion
##                      5                73.0
##                      2                25.3
##                      1                 7.8
# Gráfico de probabilidades
cat("\n\nFigura 15. Probabilidades de Rotación por Perfil\n")
## 
## 
## Figura 15. Probabilidades de Rotación por Perfil
grafico_predicciones <- ggplot(empleados_hipoteticos, 
                               aes(x = reorder(Perfil, -Probabilidad_Rotacion), 
                                   y = Probabilidad_Rotacion, 
                                   fill = Perfil)) +
  geom_col(alpha = 0.8) +
  geom_text(aes(label = paste0(Porcentaje_Rotacion, "%")), 
            vjust = -0.5, size = 5, fontface = "bold") +
  labs(title = "Figura 15. Probabilidades de Rotación por Perfil",
       x = "Perfil de Empleado",
       y = "Probabilidad de Rotación") +
  scale_y_continuous(labels = scales::percent, limits = c(0, 0.8)) +
  scale_fill_manual(values = c("Alto Riesgo" = "tomato", 
                              "Riesgo Moderado" = "gold", 
                              "Bajo Riesgo" = "steelblue")) +
  theme_minimal() +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 0, hjust = 0.5),
        plot.title = element_text(face = "bold", size = 14))

print(grafico_predicciones)

# Estrategia de intervención mejorada
cat("\n", rep("=", 60), "\n", sep = "")
## 
## ============================================================
cat("PLAN DE ACCIÓN Y ESTRATEGIAS\n")
## PLAN DE ACCIÓN Y ESTRATEGIAS
cat(rep("=", 60), "\n\n", sep = "")
## ============================================================
punto_corte_intervencion <- 0.6

cat("RECOMENDACIONES POR PERFIL:\n")
## RECOMENDACIONES POR PERFIL:
cat(rep("-", 50), "\n", sep = "")
## --------------------------------------------------
for(i in 1:nrow(empleados_hipoteticos)) {
  prob <- empleados_hipoteticos$Probabilidad_Rotacion[i]
  perfil <- empleados_hipoteticos$Perfil[i]
  
  if(prob > punto_corte_intervencion) {
    decision <- "🔴 INTERVENCIÓN INMEDIATA"
    color <- "\\033[31m"  # Rojo
    acciones <- c(
      "• Revisión salarial urgente (+15-20%)",
      "• Reducción inmediata de horas extra", 
      "• Plan de desarrollo personalizado",
      "• Mentoría ejecutiva",
      "• Revisión cada 2 semanas"
    )
  } else if(prob > 0.3) {
    decision <- "🟡 MONITOREAR ACTIVAMENTE"
    color <- "\\033[33m"  # Amarillo
    acciones <- c(
      "• Seguimiento trimestral",
      "• Programa de mentoría",
      "• Oportunidades de desarrollo",
      "• Revisión salarial en 6 meses"
    )
  } else {
    decision <- "🟢 ESTABLE - MANTENER"
    color <- "\\033[32m"  # Verde
    acciones <- c(
      "• Revisión anual normal",
      "• Mantener condiciones actuales",
      "• Incluir en programas de retención básicos"
    )
  }
  
  cat("\n", perfil, " - ", decision, "\n", sep = "")
  cat("Probabilidad de rotación: ", prob*100, "%\n", sep = "")
  cat("Acciones recomendadas:\n")
  for(accion in acciones) {
    cat("  ", accion, "\n")
  }
  cat("\n")
}
## 
## Alto Riesgo - 🔴 INTERVENCIÓN INMEDIATA
## Probabilidad de rotación: 73%
## Acciones recomendadas:
##    • Revisión salarial urgente (+15-20%) 
##    • Reducción inmediata de horas extra 
##    • Plan de desarrollo personalizado 
##    • Mentoría ejecutiva 
##    • Revisión cada 2 semanas 
## 
## 
## Riesgo Moderado - 🟢 ESTABLE - MANTENER
## Probabilidad de rotación: 25.3%
## Acciones recomendadas:
##    • Revisión anual normal 
##    • Mantener condiciones actuales 
##    • Incluir en programas de retención básicos 
## 
## 
## Bajo Riesgo - 🟢 ESTABLE - MANTENER
## Probabilidad de rotación: 7.8%
## Acciones recomendadas:
##    • Revisión anual normal 
##    • Mantener condiciones actuales 
##    • Incluir en programas de retención básicos
cat("• El modelo identifica correctamente patrones de riesgo conocidos\n")
## • El modelo identifica correctamente patrones de riesgo conocidos
cat("• Las horas extra son el factor de riesgo MÁS importante\n")
## • Las horas extra son el factor de riesgo MÁS importante
cat("• La combinación de múltiples factores aumenta el riesgo exponencialmente\n")
## • La combinación de múltiples factores aumenta el riesgo exponencialmente
cat("• Las predicciones permiten acciones PROACTIVAS de retención\n")
## • Las predicciones permiten acciones PROACTIVAS de retención
cat("• Se recomienda aplicar este análisis a empleados reales\n")
## • Se recomienda aplicar este análisis a empleados reales

7 Conclusiones

7.0.0.1 Durante todo este ejercicio, se observa que las causas que más afectan la rotación de personal son las horas extras principalmente, la edad, estado civil y sueldo; a esto se le suma el trabajar en las áreas de recursos humanos y ventas, a pesar de tener el menor personal (de los datos estudiados), son los departamentos que más rotación presentaron.
7.0.0.2 Seguramente estas variables tienen mayor impacto ya que un colaborador soltero y joven, tendrá menos responsabilidades si lo comparamos con un empleado casado y con una edad mayor (38 años en adelante). Por tal motivo, le será más fácil conseguir un trabajo que se adapte a sus necesidades, otro factor importante es el tiempo extra en su puesto de trabajo, si es constante los empleados lo tomaran como negativa en especial si buscan formalizar una familia o emprender algún proyecto. Por ultimo el salario influye de tal manera los empleados jóvenes obtén por buscar mejores oportunidades.

7.0.1 Como medidas, se recomienda:

7.0.1.1 • Validar los procesos o los puestos que requieren horas extras, si se pueden disminuir o buscar la manera de bajar esta carga.
7.0.1.2 • Inspeccionar el departamento de ventas, ya que presento la mayor rotación, puede estar causando algún estrés o tener altas exigencias que fomenta la renuncia de los colaboradores.
7.0.1.3 • Brindar a los jóvenes o nuevos talentos ayudas que les permita verse dentro de la compañía, como subsidios de estudio, vivienda o auxilios extralegales.
7.0.1.4 • Motivar el personal mediante bonificaciones o vacaciones si cumple con ciertas metas, en especial en el área de ventas donde mayor rotación se evidencia.
7.0.1.5 • Se recomienda ajustar el modelo, ya que presenta falencias para detectar aquellos empleados que de verdad quieren dejar la organización.