HHRR es un dataset simulado que contiene 10 diferentes características de 14999 registros pertenencientes a empleados de distintos sectores. Contiene los siguientes atributos:
Cargamos el dataset
hhrr <- read.csv("HR_comma_sep.csv", header = T)
Cargamos las librerías
library(dplyr) #Data Manipulation
library(caTools) #Split Datasets
library(lattice) #Plots
library(ggplot2) #Plots
library(caret) #Machine Learning
library(rpart) #Decission Tree Algorithm
library(e1071) #Random Forest Algorithm
library(ranger) #Random Forest Algorithm
library(kernlab) #Support Vector Machine
EDA: Análisis exploratorio de los datos
Primero vamos a ver si hay algún registro que no esté completo.
hhrr[!complete.cases(hhrr),]
## [1] satisfaction_level last_evaluation number_project
## [4] average_montly_hours time_spend_company Work_accident
## [7] left promotion_last_5years sales
## [10] salary
## <0 rows> (or 0-length row.names)
Todos los registros están completos. Si hubieran registros incompletos deberíamos de realizar un análisis factual o ‘Median Imputation’.
Seguimos explorando nuestro dataset viendo la estructura del mismo, y los estadísticos pertinentes.
str(hhrr)
## 'data.frame': 14999 obs. of 10 variables:
## $ satisfaction_level : num 0.38 0.8 0.11 0.72 0.37 0.41 0.1 0.92 0.89 0.42 ...
## $ last_evaluation : num 0.53 0.86 0.88 0.87 0.52 0.5 0.77 0.85 1 0.53 ...
## $ number_project : int 2 5 7 5 2 2 6 5 5 2 ...
## $ average_montly_hours : int 157 262 272 223 159 153 247 259 224 142 ...
## $ time_spend_company : int 3 6 4 5 3 3 4 5 5 3 ...
## $ Work_accident : int 0 0 0 0 0 0 0 0 0 0 ...
## $ left : int 1 1 1 1 1 1 1 1 1 1 ...
## $ promotion_last_5years: int 0 0 0 0 0 0 0 0 0 0 ...
## $ sales : Factor w/ 10 levels "accounting","hr",..: 8 8 8 8 8 8 8 8 8 8 ...
## $ salary : Factor w/ 3 levels "high","low","medium": 2 3 3 2 2 2 2 2 2 2 ...
summary(hhrr)
## satisfaction_level last_evaluation number_project average_montly_hours
## Min. :0.0900 Min. :0.3600 Min. :2.000 Min. : 96.0
## 1st Qu.:0.4400 1st Qu.:0.5600 1st Qu.:3.000 1st Qu.:156.0
## Median :0.6400 Median :0.7200 Median :4.000 Median :200.0
## Mean :0.6128 Mean :0.7161 Mean :3.803 Mean :201.1
## 3rd Qu.:0.8200 3rd Qu.:0.8700 3rd Qu.:5.000 3rd Qu.:245.0
## Max. :1.0000 Max. :1.0000 Max. :7.000 Max. :310.0
##
## time_spend_company Work_accident left
## Min. : 2.000 Min. :0.0000 Min. :0.0000
## 1st Qu.: 3.000 1st Qu.:0.0000 1st Qu.:0.0000
## Median : 3.000 Median :0.0000 Median :0.0000
## Mean : 3.498 Mean :0.1446 Mean :0.2381
## 3rd Qu.: 4.000 3rd Qu.:0.0000 3rd Qu.:0.0000
## Max. :10.000 Max. :1.0000 Max. :1.0000
##
## promotion_last_5years sales salary
## Min. :0.00000 sales :4140 high :1237
## 1st Qu.:0.00000 technical :2720 low :7316
## Median :0.00000 support :2229 medium:6446
## Mean :0.02127 IT :1227
## 3rd Qu.:0.00000 product_mng: 902
## Max. :1.00000 marketing : 858
## (Other) :2923
Ahora vamos a realizar algunos gráficos para hacer la información más visual y rápida de leer:
En el siguiente gráfico podemos observar la distribución del nivel de satisfacción en general. Se observa que la mayoría de registros tienen una satisfacción por encima de la media (0.500), pero podemos observar un pico bastante pronunciado en la parte inferior, es decir, una serie de registros que puntua por debajo de 0.25:
ggplot(hhrr, aes(satisfaction_level)) +
geom_histogram(fill = 'aquamarine3', binwidth = 0.01) +
xlab('Nivel de Satisfacción') +
ylab('') +
coord_flip() +
labs(title = 'Gráfico 1: Distribución del nivel de Satisfacción')
Si volvemos a hacer el anterior gráfico diferenciando por tipo de salario, podemos ver que el pico inferior se compone principalmente de empleados con salario medio y bajo:
ggplot(hhrr, aes(satisfaction_level)) +
geom_histogram(aes(fill = salary), binwidth = 0.01) +
xlab('Nivel de Satisfacción') +
ylab('') +
coord_flip() +
scale_fill_manual(name = 'Salario',
values = c('lightpink1', 'lightblue1', 'olivedrab4'),
labels = c('Alto', 'Medio', 'Bajo')) +
labs(title = 'Gráfico 2: Distribución del nivel de Satisfacción')
Ahora vamos a ver si existen diferencias en la distribución de nivel de satisfacción en los diferentes tipos de salarios:
ggplot(hhrr, aes(satisfaction_level, fill = factor(salary))) +
geom_density(alpha = 0.3) +
xlab('Nivel de Satisfacción') +
ylab('') +
scale_fill_manual(name = 'Salario',
values = c('lightpink1', 'lightblue1', 'olivedrab4'),
labels = c('Alto', 'Medio', 'Bajo')) +
labs(title = 'Gráfico 3: Nivel de Satisfacción en los diferentes tipos de salario')
Podemos ver que las distribuciones son muy parecidas entre sí, por tanto, podemos decir que el nivel de satisfacción no está directamente relacionado con el salario. Podriamos comprobarlo, calculando la media de satisfacción por tipo de salario, donde observamos que las tres medias son muy similares:
hhrr %>%
group_by(salary) %>%
summarise(media = mean(satisfaction_level))
## # A tibble: 3 × 2
## salary media
## <fctr> <dbl>
## 1 high 0.6374697
## 2 low 0.6007531
## 3 medium 0.6218166
Visto en un boxplot se vería de la siguiente manera:
#Order levels of Salary factor
hhrr$salary <- factor(hhrr$salary, levels=c("high", "medium", "low"))
ggplot(hhrr, aes(x = salary, y = satisfaction_level)) +
geom_boxplot(aes(fill = salary)) +
xlab('Salario') +
ylab('Nivel de Satisfacción') +
scale_fill_manual(name = 'Salario',
values = c('lightpink1', 'lightblue1', 'olivedrab4'),
labels = c('Alto', 'Medio', 'Bajo')) +
labs(title = 'Gráfico 4: Nivel de Satisfacción en los diferentes tipos de salario')
Como hemos visto que no hay prácticamente diferencias en el nivel de satisfacción en los diferentes tipos de salario, vamos a estudiar si el nivel de satisfacción es diferente para las personas que dejan el empleo o las que se quedan en la empresa.
ggplot(hhrr, aes(satisfaction_level, fill = factor(left))) +
geom_density(alpha = 0.3) +
xlab('Nivel de Satisfacción') +
ylab('') +
scale_fill_manual(name = 'Abandono',
values = c('lightpink1', 'lightblue1'),
labels = c('No', 'Sí')) +
labs(title = 'Gráfico 5: Nivel de Satisfacción por Abandono de la empresa')
Observando el gráfico podemos observar que la mayoría de personas con un nivel de satisfacción por debajo de la media (0.500), son empleados que dejan la empresa, en contraposición de las personas que se encuentran por encima de la media, que son mayoritariamente empleados que se quedan en la empresa. Podríamos observar una estrecha relación entre el nivel de satisfacción y el dejar la empresa o no.
Ahora vamos a observar el nivel de satisfacción por accidente de trabajo y por promoción en los últimos 5 años:
ggplot(hhrr, aes(satisfaction_level, fill = factor(Work_accident))) +
geom_density(alpha = 0.3) +
xlab('Nivel de Satisfacción') +
ylab('') +
scale_fill_manual(name = 'Accidente de Trabajo',
values = c('lightpink1', 'lightblue1'),
labels = c('No', 'Yes')) +
labs(title = 'Gráfico 6: Nivel de Satisfacción por Accidente de Trabajo')
ggplot(hhrr, aes(satisfaction_level, fill = factor(promotion_last_5years))) +
geom_density(alpha = 0.3) +
xlab('Nivel de Satisfacción') +
ylab('') +
scale_fill_manual(name = 'Promoción en los últimos 5 años',
values = c('lightpink1', 'lightblue1'),
labels = c('No', 'Yes')) +
labs(title = 'Gráfico 7: Nivel de Satisfacción por Promoción en los últimos 5 años')
Las distribuciones son muy similares entre sí en los dos gráficos anteriores; no podríamos establecer una relación entre accidente de trabajo y nivel de satisfacción (Gráfico 6), ni entre promoción en los últimso 5 años y nivel de satisfacción (Gráfico 7).
En el siguiente gráfico se observa que el nivel de satisfacción más alto se corresponde a los empleados que llevan a cabo entre 3 y 5 proyectos. Las personas que llevan 2 o 6 o más proyectos, son las mas insatisfechas.
ggplot(hhrr, aes(number_project, satisfaction_level)) +
geom_line(aes(colour = number_project)) +
ylab('Nivel de Satisfacción') +
xlab('Número de proyectos') +
labs(title = 'Gráfico 8: Nivel de Satisfacción por Número de Proyectos') +
theme(legend.position = 'none')
Vamos a computar la correlación de pearson (\(r_(xy)\)) entre las 7 variables cuantitativas del dataset:
## satisfaction_level last_evaluation number_project
## satisfaction_level 1.000 0.105 -0.143
## last_evaluation 0.105 1.000 0.349
## number_project -0.143 0.349 1.000
## average_montly_hours -0.020 0.340 0.417
## time_spend_company -0.101 0.132 0.197
## Work_accident 0.059 -0.007 -0.005
## left -0.388 0.007 0.024
## average_montly_hours time_spend_company Work_accident
## satisfaction_level -0.020 -0.101 0.059
## last_evaluation 0.340 0.132 -0.007
## number_project 0.417 0.197 -0.005
## average_montly_hours 1.000 0.128 -0.010
## time_spend_company 0.128 1.000 0.002
## Work_accident -0.010 0.002 1.000
## left 0.071 0.145 -0.155
## left
## satisfaction_level -0.388
## last_evaluation 0.007
## number_project 0.024
## average_montly_hours 0.071
## time_spend_company 0.145
## Work_accident -0.155
## left 1.000
Es importante destacar que encontramos una correlación relativamente alta entre el nivel de satisfacción y el abandono o no de la empresa (esto corrobora la relación que hemos observado en el gráfico 5).
Podemos ver que la mayor correlación que se obtiene es entre el promedio de horas mensuales y el número de proyectos (0.417).
Realizamos un gráfico para obtener la información visual:
ggplot(hhrr, aes(factor(number_project), average_montly_hours, colour = number_project)) +
geom_boxplot() +
ggtitle('') +
ylab('Promedio de Horas trabajadas al mes') +
xlab('Número de Proyectos') +
theme(legend.position = "none",
legend.direction = "horizontal") +
labs(title = 'Gráfico 9: Número de Proyectos por Promedio de Horas al mes',
color = 'Número de Proyectos',
size = '')
Este gráfico no nos da información de relevancia, dado que es lógico pensar que cuantos más proyectos realice un empleado, más horas trabajará al mes.
Por último, vamos a realizar un gráfico del nivel de satisfacción con los diferentes tipos de sector:
ggplot(hhrr, aes(factor(sales), satisfaction_level)) +
geom_boxplot(aes(colour = factor(sales))) +
ggtitle('') +
ylab('Nivel de Satisfacción') +
xlab('Sector') +
theme(axis.text.x = element_text(angle=-45),
legend.position = 'none') +
labs(title = 'Gráfico 10: Nivel de Satisfacción por sector',
color = 'Número de Proyectos',
size = '')
Se observa que no hay prácticamente diferencias en el nivel de satisfacción en los distintos sectores. Sin embargo, podemos comentar que contabilidad (accounting) y recursos humanos (hr) son los sectores mas insatisfechos, y tecnologías de la información (IT) y management son los sectores más satisfechos.
Machine Learning
Ahora vamos a evaluar el nivel de confianza (Accuracy) para predecir si una persona se quedará o no en la empresa (‘left’), mediante diferentes algoritmos de clasificación. Utilizaremos el K-Nearest Neightbours, Decission Tree, Random Forest, Support Vector Machine y Logistic Regression.
sample.hhrr <- hhrr[sample(1:nrow(hhrr), 4000, replace = FALSE),]
sample <- sample.split(sample.hhrr, SplitRatio = .7)
train <- subset(sample.hhrr, sample == T)
test <- subset(sample.hhrr, sample == F)
set.seed(128)
knn.model <- train(left ~ .,
data = train,
method = 'knn',
preProcess = c('scale'))
Calculamos los valores predichos y la Confussion Matrix:
knn.pred <- predict(knn.model, test[,-7])
knn.cm <- confusionMatrix(knn.pred, test[,7])
set.seed(193)
dt.model <- train(left ~ .,
data = train,
method = 'rpart',
preProcess = c('scale'))
dt.pred <- predict(dt.model, test[,-7])
dt.cm <- confusionMatrix(dt.pred, test[,7])
set.seed(146)
rf.model <- train(left ~ .,
data = train,
method = 'ranger',
preProcess = c('scale'))
rf.pred <- predict(rf.model, test[,-7])
rf.cm <- confusionMatrix(rf.pred, test[,7])
set.seed(100)
svm.model <- train(left ~ .,
data = train,
method = 'svmRadial',
preProcess = c('scale'))
svm.pred <- predict(svm.model, test[,-7])
svm.cm <- confusionMatrix(svm.pred, test[,7])
set.seed(102)
lr.model <- train(left ~ .,
data = train,
method = 'LogitBoost',
preProcess = c('scale'))
lr.pred <- predict(lr.model, test[,-7])
lr.cm <- confusionMatrix(lr.pred, test[,7])
Creo un dataframe con el valor de Accuracy de todos los algoritmos para obtener una comparación más clara:
models <- as.data.frame(list('KNN' = knn.cm$overall[1],
'DT' = dt.cm$overall[1],
'RF' = rf.cm$overall[1],
'SVM' = svm.cm$overall[1],
'LR' = lr.cm$overall[1]))
models
## KNN DT RF SVM LR
## Accuracy 0.9158333 0.905 0.9791667 0.9308333 0.9458333
Podemos observar que el Random Forest es el que trabaja mejor en este caso (0.981), por lo tanto, ahora utilizamos todo el dataset para obtener el modelo correspondiente:
split <- sample.split(hhrr, SplitRatio = .7)
training <- subset(hhrr, split == T)
testing <- subset(hhrr, split == F)
set.seed(1011)
rf <- train(left ~ .,
data = train,
method = 'ranger',
preProcess = c('scale'))
pred <- predict(rf, testing[,-7])
confmat <- confusionMatrix(pred, testing$left)
confmat
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 3411 55
## 1 17 1017
##
## Accuracy : 0.984
## 95% CI : (0.9799, 0.9875)
## No Information Rate : 0.7618
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.9554
## Mcnemar's Test P-Value : 1.298e-05
##
## Sensitivity : 0.9950
## Specificity : 0.9487
## Pos Pred Value : 0.9841
## Neg Pred Value : 0.9836
## Prevalence : 0.7618
## Detection Rate : 0.7580
## Detection Prevalence : 0.7702
## Balanced Accuracy : 0.9719
##
## 'Positive' Class : 0
##
El valor de Accuracy es de 98.67% con un intérvalo de confianza de 98.29% a 98.98%.
La Kappa de Cohen nos informa de el valor de acuerdo absoluto entre las predicciones (‘Prediction’) y el valor real (‘Reference’), siempre teniendo en cuenta del acuerdo por azar. El valor de acuerdo es de 96.28%, valor que resulta ‘Casi Perfecto’ según Landis y Koch (1977), y ‘Excelente’ según Fleiss (1981).
La Sensibilidad nos informa de si el modelo clasifica a las personas que no dejan el empleo como personas que no dejan el empleo. En cambio, la Especificidad nos informa de si el modelo clasifica a las personas que dejan el empleo, como personas que dejan el empleo.
Tanto para Sensibilidad (99.68%) como para Especificidad (95.43%), los índices son altos, pero podríamos decir que el modelo clasifica mejor a las personas que no dejan la empresa, que a las personas que si dejan la empresa.
Gracias a este modelo podemos predecir si un nuevo empleado es susceptible o no de dejar la empresa. Por ello, creamos un nuevo dataset, que será un registro aleatorio de nuestro dataset original (hhrr):
set.seed(1011)
new.data <- hhrr[sample(1:nrow(hhrr), 1, replace = FALSE),]
new.data
## satisfaction_level last_evaluation number_project
## 12099 0.11 0.97 6
## average_montly_hours time_spend_company Work_accident left
## 12099 284 4 0 1
## promotion_last_5years sales salary
## 12099 0 sales low
Por ejemplo, tenemos un empleado con un nivel de satisfacción bajo (0.11), que lleva a cabo 6 proyectos, con una media de horas trabajadas al mes es de 284h, tiene un salario bajo, lleva 4 años en la empresa, y no ha tenido ningún accidente de trabajo.
Vamos a ver si este empleado podría dejar o no la empresa realizando la predicción en nuestro modelo:
new.data.pred <- predict(rf, new.data[,-7])
new.data.pred
## [1] 1
## Levels: 0 1
Según nuestro modelo, dejaría la empresa.
Vamos a cambiar algunos parámetros de este empleado. Dado que hemos visto que dejar o no la empresa, tiene relación con el nivel de satisfacción, vamos a cambiar este parámetro a la media en nivel de satisfacción (0.5):
new.data$satisfaction_level <- 0.50
predict(rf, new.data[,-7])
## [1] 0
## Levels: 0 1
Podemos observar que al tener un nivel de satisfacción igual que a la media, nuestra predicción cambia; este empleado no dejará la empresa.
Con respecto al salario, también realizamos una predicción con los mismos parámetros, pero con un nivel de salario alto:
new.data$salary <- 'high'
predict(rf, new.data[,-7])
## [1] 1
## Levels: 0 1
El nivel de salario no afecta a la decisión de dejar la empresa o no, dado que este empleado, a pesar de tener un salario alto, dejaría igualmente la empresa.
Conclusiones
Según algunos estudios, un nivel de satisfacción alto puede mejorar la productividad (Gibson y Otros, 1993; Killian, 1990; Oliveros, 1994).
Hemos podido observar que la satisfacción en el lugar de trabajo es importante para evitar la fuga de empleados, y por ende, tiene repercusión en la productividad de la empresa. Evaluar estos indicadores en la empresa, nos puede ayudar a mejorar el plan de recursos humanos en la empresa, así como ajustar las politicas de la empresa. La seguridad, la confianza, las comodidades, el reconocimiento, la promoción, las relaciones interpersonales o el respeto, son claves fundamentales para tener un buen nivel de satisfacción por parte de los empleados.
Como recomendación para futuros análisis, sería de interés estudiar la relación entre el nivel de satisfaccion y el estilo de liderazgo, dado que es otro factor importante en cuanto a satisfacción en la empresa (Strauss y Sayles, 1992).
Recursos
Dataset:
https://www.kaggle.com/ludobenistant/hr-analytics
Bibliografía:
Gibson, J. Ivancevich, J. y Donnelly, J. (1993) Organizaciones: Conducta, Estructura,Proceso. México: Eunsa.
Killian, R. (1990). Dirección en la Administración. México: Reverte.
Oliveros, F. (1994). La Participación en los Centros Educativos. Pamplona. España:Eunsa.
Strauss, G. y Sayles, L. (1992). Personal.(Cadena J., traductor). México: PreniceHall. (Trabajo original publicado en inglés en 1980).
Notas
Este proyecto forma parte de un portfolio personal. La base de datos utilizados pertenecen a Kaggle, datos de acceso abierto.
El código R está íntegramente escrito con fines didácticos y divulgativos.
Todos los derechos reservados ©