Creación de Clústeres
A continuación se hacen diferentes visualizaciones de gráficos de
Clúster para poder detectar el número óptimo de Clústeres.
fviz_nbclust(datos_escalados, kmeans, method = "wss")

fviz_nbclust(datos_escalados, kmeans, method = "silhouette")

fviz_nbclust(datos_escalados, kmeans, method = "gap_stat")

Como podemos ver el número óptimo de Clústeres podrías
estar entre 2-5
Según estos datos el número de clústeres ideal para
poder trabajar la información es 2
Se crea k2 para poder visualizar en datos como se ven los clústeres
dentro del data frame.
k2 <- kmeans(datos_escalados, centers = 4)
k2
## K-means clustering with 4 clusters of sizes 45, 27, 9, 25
##
## Cluster means:
## Antiguedad Salario Prestaciones Jornada_Laboral Herramientas Temperatura
## 1 0.1744489 0.4547268 0.8114496 0.4553069 0.6485722 0.30299671
## 2 -0.5145195 0.1276206 -0.7249346 -0.2157419 0.2923616 -0.07121457
## 3 -0.2509097 -1.4247477 -1.0350742 -0.3040377 -1.7024180 0.70301567
## 4 0.3320005 -0.4434292 -0.3050532 -0.4770977 -0.8703100 -0.72156798
## Estrés Transporte Instalaciones Rotación Edad Dependientes
## 1 0.30900582 0.3030690 0.5273121 0.4916137 0.2338760 0.2265705
## 2 0.04400083 0.1410431 0.2302236 -0.4348050 -0.8461325 -0.5503336
## 3 -0.88351663 -0.5954382 -1.2552190 -2.1139388 -0.6542528 -0.1787708
## 4 -0.28566538 -0.4834931 -0.7459244 0.3457027 0.7283773 0.2508909
##
## Clustering vector:
## [1] 1 4 3 2 2 1 4 1 4 1 1 1 1 2 1 2 2 1 3 3 2 2 2 2 1 4 1 2 4 1 1 4 2 2 1 4 3
## [38] 3 4 1 1 4 4 4 1 2 3 4 3 1 2 2 1 2 2 4 1 1 4 1 1 2 4 1 4 2 4 1 2 4 1 1 1 4
## [75] 3 1 4 4 3 1 1 1 1 4 1 2 2 1 1 2 1 1 1 1 4 2 4 2 1 1 2 1 4 2 1 1
##
## Within cluster sum of squares by cluster:
## [1] 285.39104 207.64482 84.84052 296.87159
## (between_SS / total_SS = 30.6 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
str(k2)
## List of 9
## $ cluster : int [1:106] 1 4 3 2 2 1 4 1 4 1 ...
## $ centers : num [1:4, 1:12] 0.174 -0.515 -0.251 0.332 0.455 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:4] "1" "2" "3" "4"
## .. ..$ : chr [1:12] "Antiguedad" "Salario" "Prestaciones" "Jornada_Laboral" ...
## $ totss : num 1260
## $ withinss : num [1:4] 285.4 207.6 84.8 296.9
## $ tot.withinss: num 875
## $ betweenss : num 385
## $ size : int [1:4] 45 27 9 25
## $ iter : int 4
## $ ifault : int 0
## - attr(*, "class")= chr "kmeans"
#Se quita la columana de edad ya que afecta a los datos que queremos analizar
DS2<-subset(datos_escalados,select=-Edad)
k22<-kmeans(DS2,centers=4)
k22
## K-means clustering with 4 clusters of sizes 29, 42, 13, 22
##
## Cluster means:
## Antiguedad Salario Prestaciones Jornada_Laboral Herramientas Temperatura
## 1 -0.43412159 0.1811505 0.2235827 0.4754019 0.1670737 -1.0723744
## 2 0.32383994 0.3335470 0.4832468 0.4780116 0.5213541 0.8136200
## 3 -0.17531142 -1.0537147 -1.1176558 -0.3108297 -1.7462593 0.2861225
## 4 0.05760441 -0.2529113 -0.5568519 -1.3555616 -0.1836654 -0.3087625
## Estrés Transporte Instalaciones Rotación Dependientes
## 1 0.05679417 0.2908790 0.1403235 0.2400431 0.111257860
## 2 0.14432414 0.3725087 0.3882955 0.3985582 -0.034006053
## 3 -0.87128563 -0.3631633 -1.2622148 -1.6529564 -0.007280258
## 4 0.16445764 -0.8799879 -0.1804090 -0.1005573 -0.077435470
##
## Clustering vector:
## [1] 1 2 3 2 4 2 4 2 2 1 4 2 1 1 1 2 1 2 3 3 1 4 4 4 2 4 1 4 1 2 2 1 3 1 2 4 3
## [38] 3 3 2 2 1 4 1 2 1 3 1 3 2 4 2 2 2 2 3 2 1 2 2 1 4 1 1 4 1 4 2 4 1 2 2 1 4
## [75] 3 2 3 4 3 2 2 2 1 4 2 1 2 2 1 2 2 2 2 2 4 4 1 4 2 1 2 2 4 1 1 2
##
## Within cluster sum of squares by cluster:
## [1] 199.2447 238.6959 144.4055 220.3491
## (between_SS / total_SS = 30.5 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Esta información nos dice que el clúster 1 está compuesto por
personas que contestaron datos medianamente positivos en la encuesta, es
decir que, por ejemplo, en la parte de la encuesta en donde eran
oraciones y la gente respondía si estaba o no de acuerdo, las personas
en el clúster 1 tendieron a contestar en esas oraciones en que estaban
tan de acuerdo con la oración establecida. Y viceversa las personas en
el clúster 2 tendieron a no estar de acuerdo con las oraciones de la
encuesta.
Ahora se usarán los siguientes códigos para visualizar la
distribución de las categorías/columnas Salario, Prestaciones y
Temperatura dentro de cada clúster definido por la Columna Clúster en
términos de porcentajes, esto nos ayudará a entender cómo se relacionan
las variables en el conjunto de datos. Estas variables fueron elegidas
por el Modelo de Regresión, ya que, al realizarlo, estas resultaron ser
las variables más relevantes para hacer predicciones sobre el valor de
la respuesta de Rotación.
set.seed(200)
kmeans_result <- kmeans(DS2, centers = 4)
kmeans_result$centers
## Antiguedad Salario Prestaciones Jornada_Laboral Herramientas Temperatura
## 1 -0.41214676 -1.5910729 -1.0350742 -1.2752926 -1.77366014 0.1868622
## 2 0.48326149 -0.3608401 -0.3983419 -0.4836742 -0.45199584 -0.7119568
## 3 -0.55802788 0.0192572 -0.7618043 0.1254014 0.04949067 0.2191218
## 4 0.04285545 0.5295731 0.8179843 0.4944643 0.60830491 0.3074850
## Estrés Transporte Instalaciones Rotación Dependientes
## 1 -0.6450121 -1.4055677 -1.8008918 -1.5928283 -0.07743547
## 2 -0.1899346 -0.2348163 -0.2830433 0.4017670 0.17415564
## 3 -0.4860091 0.2347771 0.1544357 -0.9177533 -0.49198900
## 4 0.4783786 0.3107541 0.4569282 0.4972779 0.14065573
datos1 <- ELF
datos1$Cluster <- kmeans_result$cluster
contingency <- table(datos1$Cluster, datos1$Salario)
contingency <- prop.table(contingency, margin = 1) * 100
contingency2 <- table(datos1$Cluster, datos1$Prestaciones)
contingency2 <- prop.table(contingency2, margin = 1) * 100
contingency3 <- table(datos1$Cluster, datos1$Temperatura)
contingency3 <- prop.table(contingency3, margin = 1) * 100
print(contingency)
##
## 1 2 3 4 5
## 1 66.666667 11.111111 11.111111 11.111111 0.000000
## 2 10.344828 24.137931 6.896552 41.379310 17.241379
## 3 4.545455 9.090909 9.090909 54.545455 22.727273
## 4 2.173913 2.173913 6.521739 21.739130 67.391304
print(contingency3)
##
## 1 2 3 4 5
## 1 22.222222 0.000000 22.222222 22.222222 33.333333
## 2 62.068966 6.896552 17.241379 6.896552 6.896552
## 3 22.727273 4.545455 13.636364 18.181818 40.909091
## 4 21.739130 8.695652 4.347826 13.043478 52.173913
print(contingency2)
##
## 1 2 3 4 5
## 1 66.666667 22.222222 0.000000 0.000000 11.111111
## 2 27.586207 24.137931 20.689655 10.344828 17.241379
## 3 31.818182 45.454545 9.090909 9.090909 4.545455
## 4 0.000000 0.000000 4.347826 36.956522 58.695652
En esta parte lo que se hace es añadir una nueva columna a mi data
frame original llamada Clúster y se le asigna el clúster correspondiente
a cada variable gracias a cálculos previamente realizados.
DFEF <- ELF
DFEF$cluster<-as.factor(k22$cluster)
# DFEF
Por último, se hacen estos códigos para poder exportar este data
frame con la columna de clúster a un Excel y así se pueda usar en POWER
BI.
getwd()
## [1] "C:/Users/IanAb/Documents/7to Semestre/Actividades"
library(openxlsx)
write.xlsx(DFEF, "ClustersFORM.xlsx")
Árbol de Decisiones Encuesta FORM
Carga de Paquete y Librería a usar, junto con creación del
árbol de decisiones.
library(rpart)
library(rpart.plot)
df_arbol<-ELF
df_arbol$Rotación <- as.factor(df_arbol$Rotación)
df_arbol$Salario <- as.factor(df_arbol$Salario)
df_arbol$Prestaciones <- as.factor(df_arbol$Prestaciones)
df_arbol$Temperatura <- as.factor(df_arbol$Temperatura)
arbol <- rpart(formula= Rotación ~ Salario + Prestaciones + Temperatura,data=df_arbol)
arbol
## n= 106
##
## node), split, n, loss, yval, (yprob)
## * denotes terminal node
##
## 1) root 106 50 5 (0.085 0.047 0.14 0.2 0.53)
## 2) Prestaciones=1,2 40 29 5 (0.17 0.12 0.22 0.2 0.27)
## 4) Salario=1,2 13 8 1 (0.38 0.15 0.077 0.38 0) *
## 5) Salario=3,4,5 27 16 5 (0.074 0.11 0.3 0.11 0.41)
## 10) Salario=3,4 20 12 3 (0.05 0.1 0.4 0.15 0.3) *
## 11) Salario=5 7 2 5 (0.14 0.14 0 0 0.71) *
## 3) Prestaciones=3,4,5 66 21 5 (0.03 0 0.091 0.2 0.68) *
rpart.plot(arbol,box.palette = list("orange","#AD7B39", "#FFC981","gray", "yellow", "#FFEECB"))

# Gráfico de preuba para corroborar otra información adicional
# prp(arbol,extra=7)
Esta Herramienta del Árbol de Decisiones sirve para poder ver como
se distribuye el comportamiento de ciertas respuestas según la acción
tomada en otras preguntas. En este caso el Árbol de decisiones
selecciona las dos variables va Influyentes para la variable de
Rotación.
Se dice que son las más influyentes ya que en el modelo de Regresión
que se mostrará a continuación, al realizar los códigos
correspondientes, se revela que las dos variables más influyentes para
la rotación son las Prestaciones y Salario.
Antes de explicar el Árbol es necesario entender que significan los
números y categorías. En la encuesta realizada al Personal de FORM se le
dieron ciertas afirmaciones/oraciones, y se les pidió que eligieran el
valor de la escala con el cual se identificaban.
Dicha escala era de 5 valores, los cuales se muestra a
continuación:
- Totalmente de acuerdo (5)
- Medianamente de Acuerdo (4)
- Ni de Acuerdo ni en Desacuerdo (3)
- Medianamente en Desacuerdo (2)
- Totalmente en Desacuerdo (1)
Ahora bien las categorías Salario y Prestaciones hacen alusión al
área a que se refería la pregunta realizada. Para poder ver las
preguntas/afirmaciones/oraciones que se hicieron pueden ver el dashboard
compartido en la Evidencia “Dashboard para FORM (Avance)”
Por ende el cuadro que se encuentra en la parte superior del árbol
hace referencia a la pregunta de Prestaciones e indica que si las
personas contestaron a esa pregunta con 1 o 2 estás personas se
clasificaran del lado izquierdo; en caso de que las personas hayan
contestado a la pregunta de Prestaciones con un valor de 3,4 o 5 se les
clasificará/agrupará del lado derecho.
Ahora bien, este Árbol se interpreta/lee de la siguiente manera
del 100% (106 personas) que contestaron la pregunta de
“Prestaciones”, el 62% contesto que esta de
cierta manera de acuerdo en que las prestaciones son algo que hace que
se queden en la empresa.
Por ende 38% de las personas contestaron en que no están tan de
acuerdo en que las prestaciones son algo que los hace quedarse en la
empresa. Ahora bien, ese 38% se distribuye de la siguiente manera, 12.5%
contesto en que no están tan de acuerdo en que el salario que reciben es
bueno para el trabajo que realizan (ya que seleccionaron como respuesta
el valor 1,2) y 25.5% están medianamente de acuerdo en que reciben un
buen salario (ya que seleccionaron como respuesta el valor 3,4,5).
La información relevante que podemos obtener aquí es que se podría
decir que el 38% de las personas que contestaron la
encuesta consideran que las prestaciones que ofrecen FORM no son
suficientes para retenerlos a largo/mediano plazo. Y que
también de ese 38%, 12% igual considera que no reciben un salario digno
de su trabajo.
Si bien son porcentajes que representan una minoría en la empresa,
es de vital importancia atender esta situación ya que si se quiere tener
una tasa de rotación de personal baja, se debe analizar las áreas de
mejora que la empresa pueda tener en este aspecto; y según este
árbol de decisiones las áreas de prestaciones y salarios pueden ser una
de las áreas a mejorar para poder potencializar la retención
del talento humano.
Análisis de Regresión Lineal
Análisis exploratorio de Variables Independientes y
Dependientes
Se usa la misma base de datos “EFL”.
dataRg<-ELF
dataRg$Edad <- as.integer(sub(" años", "", dataRg$Edad))
summary(dataRg)
## Puesto Antiguedad Motivación Salario
## Length:106 Min. : 1.00 Length:106 Min. :1.000
## Class :character 1st Qu.: 1.00 Class :character 1st Qu.:3.000
## Mode :character Median : 9.00 Mode :character Median :4.000
## Mean :14.08 Mean :3.792
## 3rd Qu.:34.50 3rd Qu.:5.000
## Max. :36.00 Max. :5.000
## Prestaciones Jornada_Laboral Herramientas Temperatura
## Min. :1.000 Min. :1.00 Min. :1.000 Min. :1.000
## 1st Qu.:2.000 1st Qu.:4.00 1st Qu.:3.000 1st Qu.:1.000
## Median :4.000 Median :5.00 Median :5.000 Median :3.000
## Mean :3.274 Mean :4.16 Mean :3.877 Mean :3.123
## 3rd Qu.:5.000 3rd Qu.:5.00 3rd Qu.:5.000 3rd Qu.:5.000
## Max. :5.000 Max. :5.00 Max. :5.000 Max. :5.000
## Estrés Transporte Instalaciones Rotación
## Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
## 1st Qu.:3.000 1st Qu.:4.000 1st Qu.:4.000 1st Qu.:3.000
## Median :4.000 Median :5.000 Median :5.000 Median :5.000
## Mean :3.679 Mean :4.009 Mean :4.311 Mean :4.038
## 3rd Qu.:5.000 3rd Qu.:5.000 3rd Qu.:5.000 3rd Qu.:5.000
## Max. :5.000 Max. :5.000 Max. :5.000 Max. :5.000
## Conflicto.Acoso Satisfacción.en.el.trabajo Emoción
## Length:106 Length:106 Length:106
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
## Edad Genero Estado.Civil Municipio
## Min. :18.00 Length:106 Length:106 Length:106
## 1st Qu.:25.25 Class :character Class :character Class :character
## Median :33.50 Mode :character Mode :character Mode :character
## Mean :35.62
## 3rd Qu.:45.00
## Max. :68.00
## Escolaridad Dependientes
## Length:106 Min. :0.000
## Class :character 1st Qu.:0.000
## Mode :character Median :1.000
## Mean :1.085
## 3rd Qu.:2.000
## Max. :3.000
str(dataRg)
## 'data.frame': 106 obs. of 21 variables:
## $ Puesto : chr "Administrativo" "Costurera" "Ayudante general" "Ayudante general" ...
## $ Antiguedad : int 9 36 4 2 1 36 36 36 36 1 ...
## $ Motivación : chr "Por el salario" "Otro" "Ubicación de la empresa" "Ubicación de la empresa" ...
## $ Salario : int 5 4 2 5 3 4 2 5 4 5 ...
## $ Prestaciones : int 4 4 1 4 1 5 3 4 1 4 ...
## $ Jornada_Laboral : int 5 5 1 5 5 5 4 5 4 5 ...
## $ Herramientas : int 5 4 1 5 5 5 4 5 1 5 ...
## $ Temperatura : int 2 3 3 4 4 2 2 4 5 1 ...
## $ Estrés : int 5 2 1 5 3 4 5 4 4 5 ...
## $ Transporte : int 4 2 4 5 1 5 1 5 5 2 ...
## $ Instalaciones : int 5 4 4 5 5 4 4 5 5 5 ...
## $ Rotación : int 4 5 1 4 3 5 3 5 5 5 ...
## $ Conflicto.Acoso : chr "No" "No" "Si" "No" ...
## $ Satisfacción.en.el.trabajo: chr "cotización ante imss, fecha de pago, comer a las 3pm" "Ninguno" "mucho trabajo, estrés" "Todo bien " ...
## $ Emoción : chr "agusto, feliz" "Bien" "cómoda, no satisfecha" "Tranquila y contenta " ...
## $ Edad : int 30 54 21 20 43 61 55 29 56 36 ...
## $ Genero : chr "Femenino" "Femenino" "Femenino" "Femenino" ...
## $ Estado.Civil : chr "Unión libre" "Casado" "Soltero" "Casado" ...
## $ Municipio : chr "Apodaca" "Apodaca" "Apodaca" "Apodaca" ...
## $ Escolaridad : chr "Licenciatura" "Primaria" "Preparatoria" "Preparatoria" ...
## $ Dependientes : int 0 0 0 0 0 2 1 0 0 2 ...
Análisis Exploratorio de datos Demográficos
datademo <- select(dataRg, "Edad", "Genero", "Estado.Civil", "Municipio", "Escolaridad", "Dependientes")
summary(datademo)
## Edad Genero Estado.Civil Municipio
## Min. :18.00 Length:106 Length:106 Length:106
## 1st Qu.:25.25 Class :character Class :character Class :character
## Median :33.50 Mode :character Mode :character Mode :character
## Mean :35.62
## 3rd Qu.:45.00
## Max. :68.00
## Escolaridad Dependientes
## Length:106 Min. :0.000
## Class :character 1st Qu.:0.000
## Mode :character Median :1.000
## Mean :1.085
## 3rd Qu.:2.000
## Max. :3.000
Modelo de Regresión Lineal
regresionF <- lm( Rotación ~ Salario + Prestaciones + Jornada_Laboral + Herramientas + Temperatura + Estrés + Transporte + Instalaciones + Conflicto.Acoso, data=dataRg)
summary (regresionF)
##
## Call:
## lm(formula = Rotación ~ Salario + Prestaciones + Jornada_Laboral +
## Herramientas + Temperatura + Estrés + Transporte + Instalaciones +
## Conflicto.Acoso, data = dataRg)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.0624 -0.6444 0.1742 0.7601 2.0695
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.155175 0.604075 3.568 0.000566 ***
## Salario 0.183708 0.094051 1.953 0.053729 .
## Prestaciones 0.299393 0.081487 3.674 0.000395 ***
## Jornada_Laboral -0.040359 0.099399 -0.406 0.685630
## Herramientas 0.137645 0.090219 1.526 0.130412
## Temperatura -0.162673 0.063386 -2.566 0.011839 *
## Estrés 0.001298 0.082590 0.016 0.987494
## Transporte 0.094415 0.077552 1.217 0.226454
## Instalaciones -0.014934 0.112110 -0.133 0.894310
## Conflicto.AcosoPrefiero no decirlo 0.264413 1.134678 0.233 0.816240
## Conflicto.AcosoSi 0.175659 0.321619 0.546 0.586230
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.089 on 95 degrees of freedom
## Multiple R-squared: 0.3447, Adjusted R-squared: 0.2758
## F-statistic: 4.998 on 10 and 95 DF, p-value: 8.232e-06
Se seleccionan solo las variables de Salario, Prestaciones y
Temperatura, ya que son las que indica el modelo que tienen más
relevancia (Esto se puede ver con los *).
regresionF <- lm( Rotación ~ Salario + Prestaciones + Temperatura , data=dataRg)
summary (regresionF)
##
## Call:
## lm(formula = Rotación ~ Salario + Prestaciones + Temperatura,
## data = dataRg)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.3567 -0.6312 0.2871 0.7267 1.9292
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.55741 0.38178 6.699 1.17e-09 ***
## Salario 0.23803 0.08448 2.817 0.00581 **
## Prestaciones 0.32148 0.07301 4.403 2.64e-05 ***
## Temperatura -0.15205 0.06147 -2.474 0.01503 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.08 on 102 degrees of freedom
## Multiple R-squared: 0.3079, Adjusted R-squared: 0.2876
## F-statistic: 15.13 on 3 and 102 DF, p-value: 3.241e-08
Ya que nuestro modelo de regresión obtiene un valor p value menor a
0.05 se puede decir que sí es válido. Otra información que obtenemos de
este código es el valor de nuestra “Adjusted R-squared” lo cual
significa que el 28.76% de la variabilidad de nuestra Rotación es
predicha con el modelo teniendo en cuenta 3 variables predictoras
(Salario, Prestaciones, Temperatura).
Ya que el P Value de los coeficientes de nuestras 3 variables es
menor a 0.05, indica que si tienen cierto impacto y ayudan a predecir el
aspecto de la rotación.
A continuación se hace una predicción ejemplo:
datosFinF <- data.frame(Salario= 5, Prestaciones= 4, Temperatura= 2)
predict(regresionF, datosFinF)
## 1
## 4.72939
Esto nos indica que una persona que haya estado Completamente de
Acuerdo con la oración de Salario, Medianamente de Acuerdo con la
oración de Prestaciones y haya estado Medianamente en Desacuerdo con la
oración de Temperatura; probablemente haya estado casi Totalmente de
Acuerdo en que es probable en que esté en FORM en un Futuro.