En una organización, se busca comprender y prever los factores que influyen en la rotación de empleados entre distintos cargos. La empresa ha recopilado datos históricos sobre el empleo de sus trabajadores, incluyendo variables como la antigüedad en el cargo actual, el nivel de satisfacción laboral, el salario actual, edad y otros factores relevantes. La gerencia planea desarrollar un modelo de regresión logística que permita estimar la probabilidad de que un empleado cambie de cargo en el próximo período y determinar cuales factores indicen en mayor proporción a estos cambios.

Con esta información, la empresa podrá tomar medidas proactivas para retener a su talento clave, identificar áreas de mejora en la gestión de recursos humanos y fomentar un ambiente laboral más estable y tranquilo. La predicción de la probabilidad de rotación de empleados ayudará a la empresa a tomar decisiones estratégicas informadas y a mantener un equipo de trabajo comprometido y satisfecho en sus roles actuales.

PUNTO 1:

Seleccione 3 variables categóricas (distintas de rotación) y 3 variables cuantitativas, que se consideren estén relacionadas con la rotación. Nota: Debes justificar porque estas variables están relacionadas y que tipo de relación se espera entre ellas (Hipótesis).

glimpse(rotacion)
## 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, …

VARIABLES SELECCIONADAS

categoricas: Horas_Extra, Campo_Educacion, Cargo numericas: Edad, Ingreso_Mensual, Años_Experiencia

Horas_Extra: Entre mas horas extra trabaje una persona, es mas probable su rotacion a otro cargo

Campo_Educacion: hay campos o dicsiplinas con indices de rotacion mas elevados que otras

Cargo: hay cargos mas prioritarios o solicitados que otros y eso aumenta su indice de rotacion

Edad: entre mas joven, mas posible que rote a otras empresas

Ingreso_Mensual: si los ingresos mensuales son bajos, es muy probable que rote el personal hasta que encuentre ingresos que se acomoden a sus necesidades o peticiones

Años_Experiencia: Cuantos mas años de experiencia tenga la persona, es equivalente a mas ingresos y asi mismo a menos posibilidades de cambios laborales

variables_rotacion = rotacion[,c(1,2,7,10,13,15,17,20)]
table(variables_rotacion$Rotación)
## 
##   No   Si 
## 1233  237

PUNTO 2:

Realiza un análisis univariado (caracterización) de la información contenida en la base de datos rotacion.

Variables Numericas

promediosPunto2 <- function(columna){
  # Promedio de ingresos mensuales
  promedio = mean(rotacion[[columna]], na.rm = TRUE)
  rotacion[[columna]][is.na(rotacion[[columna]])] = promedio
  print(paste(" --- Promedio de ", columna ," : ",(promedio)))
  plot_ly(x = ~rotacion[[columna]], type = "histogram") %>%
    layout(xaxis = list(title = columna), yaxis = list(title = "Frecuencia"), 
           title = "Histograma")
}

promediosPunto2("Ingreso_Mensual")
## [1] " --- Promedio de  Ingreso_Mensual  :  6502.93129251701"
promediosPunto2("Edad")
## [1] " --- Promedio de  Edad  :  36.9244897959184"
promediosPunto2("Años_Experiencia")
## [1] " --- Promedio de  Años_Experiencia  :  11.2795918367347"

Variables Categoricas

Para estas se realiza su prueba de chi-cuadrado para validar su relacion

CategoricasPunto2 <- function(columna){
  tabla_contingencia = table(rotacion$Rotación, rotacion[[columna]])
  resultado_chi_cuadrado = chisq.test(tabla_contingencia)
  print(resultado_chi_cuadrado)
  df_tabla_contingencia = as.data.frame.matrix(tabla_contingencia)
  barplot(as.matrix(df_tabla_contingencia), 
          beside = TRUE, 
          legend = rownames(df_tabla_contingencia),
          main = paste("Distribución de", columna, "por Rotación"),
          xlab = "Rotación",
          ylab = "Frecuencia")
}
CategoricasPunto2("Cargo")
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_contingencia
## X-squared = 86.19, df = 8, p-value = 2.752e-15

CategoricasPunto2("Horas_Extra")
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  tabla_contingencia
## X-squared = 87.564, df = 1, p-value < 2.2e-16

De acuerdo con las graficas y los resultados obtenidos, se puede concluir que las variables seleccionadas tienen una relacion estrecha con la variable a predecir (Rotacion). En los siguientes puntos se hayaran las conclusiones y se daran valores de las relaciones existentes.

PUNTO 3:

Realiza un análisis de bivariado en donde la variable respuesta sea rotacion codificada de la siguiente manera (y=1 es si rotación, y=0 es no rotación). Con base en estos resultados identifique cuales son las variables determinantes de la rotación e interpretar el signo del coeficiente estimado. Compare estos resultados con la hipotesis planteada en el punto 2.

rotacion_map = c("Si" = 1, "No" = 0)

rotacion$rotacion_numerica = rotacion_map[as.character(rotacion$Rotación)]
rotacion$Rotación = rotacion_map[as.character(rotacion$Rotación)]
rotacion$Rotación = as.character(rotacion$Rotación)
rotacion$rotacion_numerica = as.numeric(rotacion$rotacion_numerica)

mean_rotacion = mean(rotacion$Ingreso_Mensual[rotacion$rotacion_numerica == 1])
mean_no_rotacion = mean(rotacion$Ingreso_Mensual[rotacion$rotacion_numerica == 0])

Variables Numericas

NumericasPunto3 <- function(columna){
  t_valoresNumericos <- t.test(rotacion$rotacion_numerica, rotacion[[columna]])
  print("Prueba t")
  print(t_valoresNumericos)

  hist(rotacion[[columna]], 
       xlab = columna,
       ylab = "Frecuencia",
       col = "blue",
       main = paste("Rotacion en relacion con ", columna))
  
  abline(v = mean(rotacion[[columna]]), col = "red", lwd = 2)
}
NumericasPunto3("Ingreso_Mensual")
## [1] "Prueba t"
## 
##  Welch Two Sample t-test
## 
## data:  rotacion$rotacion_numerica and rotacion[[columna]]
## t = -52.957, df = 1469, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -6743.638 -6261.902
## sample estimates:
##    mean of x    mean of y 
##    0.1612245 6502.9312925

NumericasPunto3("Edad")
## [1] "Prueba t"
## 
##  Welch Two Sample t-test
## 
## data:  rotacion$rotacion_numerica and rotacion[[columna]]
## t = -154.16, df = 1473.8, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -37.23106 -36.29548
## sample estimates:
##  mean of x  mean of y 
##  0.1612245 36.9244898

NumericasPunto3("Años_Experiencia")
## [1] "Prueba t"
## 
##  Welch Two Sample t-test
## 
## data:  rotacion$rotacion_numerica and rotacion[[columna]]
## t = -54.726, df = 1475.6, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -11.51689 -10.71984
## sample estimates:
##  mean of x  mean of y 
##  0.1612245 11.2795918

De acuerdo con los resultados obtenidos en los analisis se puede concluir lo siguiente:

Son acertadas las Hipotesis planteadas con las variables numericas elegidas en el primer punto del ejercicio

Variables Categoricas

CategoricasPunto3 <- function(columna){
  tabla_contingencia <- table(rotacion[[columna]], rotacion$Rotación)

  chi_square_test_result <- chisq.test(tabla_contingencia)
  
  print(chi_square_test_result)
  
  df <- as.data.frame.matrix(tabla_contingencia)
  df$category <- rownames(df)
  df <- tidyr::gather(df, "Rotación", "Frecuencia", -category)
  ggplot(df, aes(x = category, y = Frecuencia, fill = Rotación)) +
    geom_bar(stat = "identity") +
    labs(title = paste("Tabla de Contingencia para:", columna),
         x = "Categoría",
         y = "Frecuencia",
         fill = "Rotación") +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1))
}
CategoricasPunto3("Cargo")
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_contingencia
## X-squared = 86.19, df = 8, p-value = 2.752e-15

CategoricasPunto3("Horas_Extra")
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  tabla_contingencia
## X-squared = 87.564, df = 1, p-value < 2.2e-16

#CategoricasPunto3("Campo_Educacion")

PUNTO 4:

Realice una partición en los datos de forma aleatoria donde 70% sea un set para entrenar el modelo y 30% para prueba. Estime un modelo logístico con la muestra del 70%. Muestre los resultados.

table(rotacion$Horas_Extra)
## 
##   No   Si 
## 1054  416
HorasExtra_map = c("Si" = 1, "No" = 0)
rotacion$Horas_Extra = HorasExtra_map[as.character(rotacion$Horas_Extra)]

rotacion$Cargo = factor(rotacion$Cargo)

rotacion$Cargo = as.numeric(rotacion$Cargo)

set.seed(300)
entrenamiento = sample(1:nrow(rotacion), 0.7 * nrow(rotacion))
datosTrain = rotacion[entrenamiento, ]
datosTest = rotacion[-entrenamiento, ]

modelo_logistico = glm(rotacion_numerica ~ Horas_Extra + Cargo + Edad
                       + Ingreso_Mensual + Años_Experiencia, data = datosTrain, family = binomial)

summary(modelo_logistico)
## 
## Call:
## glm(formula = rotacion_numerica ~ Horas_Extra + Cargo + Edad + 
##     Ingreso_Mensual + Años_Experiencia, family = binomial, data = datosTrain)
## 
## Coefficients:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.577e+00  4.997e-01  -3.156  0.00160 ** 
## Horas_Extra       1.508e+00  1.812e-01   8.325  < 2e-16 ***
## Cargo             1.310e-01  4.117e-02   3.182  0.00146 ** 
## Edad             -2.453e-02  1.355e-02  -1.811  0.07016 .  
## Ingreso_Mensual  -3.038e-05  3.891e-05  -0.781  0.43490    
## Años_Experiencia -2.648e-02  2.335e-02  -1.134  0.25675    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 932.07  on 1028  degrees of freedom
## Residual deviance: 818.19  on 1023  degrees of freedom
## AIC: 830.19
## 
## Number of Fisher Scoring iterations: 5
exp(modelo_logistico$coefficients)
##      (Intercept)      Horas_Extra            Cargo             Edad 
##        0.2066099        4.5198543        1.1399880        0.9757671 
##  Ingreso_Mensual Años_Experiencia 
##        0.9999696        0.9738676

De los resultados podemos decir lo siguiente:

Horas_Extra: El coeficiente estimado es 1.508, con un valor z de 8.325 y un p-valor muy pequeño. Esto indica que por cada aumento unitario en las horas extras, la log-odds de que la variable de respuesta sea “1” aumenta en 1.508, manteniendo constantes las otras variables. Es altamente significativo y sugiere que las horas extras tienen un impacto significativo en la probabilidad del evento de interés.

Cargo: El coeficiente estimado es 0.131, con un valor z de 3.182 y un p-valor de 0.00146. Esto sugiere que el cargo también tiene un impacto significativo en la probabilidad de que la variable de respuesta sea “1”. Por cada unidad de aumento en el cargo, la log-odds de que la variable de respuesta sea “1” aumenta en 0.131, manteniendo constantes las otras variables.

Edad: El coeficiente estimado es -0.025, con un valor z de -1.811 y un p-valor de 0.07016. Aunque el p-valor no es menor que 0.05, sugiere cierta tendencia a la significancia. Esto indica que la edad podría tener algún impacto en la variable de respuesta, pero se necesita más análisis para confirmarlo.

Ingreso_Mensual: El coeficiente estimado es -0.00003038, con un valor z de -0.781 y un p-valor de 0.4349. El p-valor es mayor que 0.05, lo que sugiere que el ingreso mensual no tiene un impacto significativo en la variable de respuesta.

Años_Experiencia: El coeficiente estimado es -0.0265, con un valor z de -1.134 y un p-valor de 0.25675. Similar a la edad, el p-valor es mayor que 0.05, indicando que los años de experiencia no tienen un impacto significativo en la variable de respuesta.

PUNTO 5:

Evaluar el poder predictivo del modelo con base en la curva ROC y el AUC en el set de datos de prueba.

predicciones = predict(modelo_logistico, newdata = datosTest, type = "response")

boxplot(predicciones)

roc_curve = roc(datosTest$Rotación, predicciones)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc_score <- auc(roc_curve)

plot_ly(x = ~roc_curve$specificities, y = ~roc_curve$sensitivities, 
        type = 'scatter', mode = 'lines', line = list(color = 'blue'), 
        name = 'Curva ROC') %>%
  add_trace(x = c(0, 1), y = c(0, 1), mode = 'lines', line = list(color = 'red', dash = 'dash'), 
            name = 'Línea de referencia') %>%
  layout(title = paste("Curva ROC (AUC =", round(auc_score, 2), ")", sep = ""),
         xaxis = list(title = "1 - Especificidad"),
         yaxis = list(title = "Sensibilidad"))

PUNTO 6:

En las conclusiones adicione una discución sobre cuál sería la estrategia para disminuir la rotación en la empresa (con base en las variables que resultaron significativas en el punto 3).

De acuerdo con los resultados obtenidos para minimizar la rotacion se deberia buscar o contratra personal en lo posible con las siguientes caracteristicas:

De acuerdo con lo mencionado anteriormente y teniendo en cuenta que no se analizaron el resto de variables que tambien pueden influir de gran manera en la rotacion laboral de las personas, es apropiado decir que se deben de analizar a profuncidad todas las variables o factores que puedan influir en la rotacion de las personas, sin embargo, con las variables seleccionadas anteriormente se puede mitigar en gran medida esa rotacion llevando a cabo un plan en el que aminoren todos los factores anteriormente menciandos como salario mensual, cargos, experiencia, horas extra, etc.