HR Analytics Tutorial

von Tobias Senger


1 Vorhersage der Mitarbeiterleistung

1.1 Einführung

In diesem Kapitel wird die Leistung / Performanz mittels einer multiplen linearen Regression vorhergesagt. Ziel ist es, das beste Modell zu identifizieren und die Wichtigkeit der Prädiktoren zu analysieren.

1.2 Pakete installieren und laden

packages <- c("ggplot2", "tidyverse","rio", "sjPlot", "performance", "here",
              "psych", "buildmer", "ggResidpanel", "sandwich", "lmtest", "papaja")

lapply(packages, function(package){
  if (!require(package, character.only = TRUE)) {
    install.packages(package, dependencies = TRUE)
  }
  library(package, character.only = TRUE)
})

1.2 Arbeitsverzeichnis festlegen

here::here()

1.3 Datenimport

data <- rio::import(file = "data.csv")
str(data)
## 'data.frame':    1470 obs. of  5 variables:
##  $ DistanceFromHome : int  1 8 2 3 2 2 3 24 23 27 ...
##  $ JobInvolvement   : int  3 2 2 3 3 3 4 3 2 3 ...
##  $ JobSatisfaction  : int  4 2 3 3 2 4 1 3 3 3 ...
##  $ WorkLifeBalance  : int  1 3 3 3 3 2 2 3 3 2 ...
##  $ PerformanceRating: int  3 4 3 4 4 4 4 4 4 3 ...

1.4 Deskriptive Analysen

summary(data)
##  DistanceFromHome JobInvolvement JobSatisfaction WorkLifeBalance
##  Min.   : 1.000   Min.   :1.00   Min.   :1.000   Min.   :1.000  
##  1st Qu.: 2.000   1st Qu.:2.00   1st Qu.:2.000   1st Qu.:2.000  
##  Median : 7.000   Median :3.00   Median :3.000   Median :3.000  
##  Mean   : 9.193   Mean   :2.73   Mean   :2.729   Mean   :2.761  
##  3rd Qu.:14.000   3rd Qu.:3.00   3rd Qu.:4.000   3rd Qu.:3.000  
##  Max.   :29.000   Max.   :4.00   Max.   :4.000   Max.   :4.000  
##  PerformanceRating
##  Min.   :1.000    
##  1st Qu.:3.000    
##  Median :4.000    
##  Mean   :3.251    
##  3rd Qu.:4.000    
##  Max.   :4.000

Alle Variablen – außer DistanceFromHome – wurden auf einer 4-stufigen Likert-Skala erhoben und zeigen überdurchschnittliche Ausprägungen. DistanceFromHome weist darauf hin, dass Mitarbeiter im Durchschnitt 9 Kilometer und maximal 29 Kilometer von ihrem Arbeitsplatz entfernt wohnen. Es gibt keine fehlenden Werte in den Daten.

psych::pairs.panels(data,
                    method = "pearson",             
                    hist.col = "grey", 
                    density = TRUE,  
                    ellipses = FALSE,
                    lm = TRUE, 
                    stars = TRUE,
                    bg = "grey", 
                    col = "grey")

Die Streudiagramme zeigen, dass die Performanz am stärksten mit der Mitarbeiterzufriedenheit korreliert. Die Korrelation zwischen Performanz und Job Involvement sowie zwischen Performanz und DistanceFromHome ist schwach. Es besteht keine Korrelation zwischen Performanz und Work-Life-Balance. Zudem wurde keine Multikollinearität festgestellt, da die Prädiktoren nicht miteinander korrelieren.

1.5 Multiple lineare Regression

Variablenauswahl mit dem Paket “buildmer”

Das buildmer-Paket unterstützt die automatische Vorselektion von Variablen in komplexen Regressionsmodellen. Es filtert die wichtigsten Prädiktoren heraus, um das optimale Modell zu bestimmen, das sowohl einfach als auch aussagekräftig ist. In diesem Fall werden Likelihood-Ratio-Tests in einer schrittweisen Rückwärtsselektion verwendet.

Hinweis: In der Modellformel werden auch Interaktionen berücksichtigt.

formula <- PerformanceRating ~ JobSatisfaction * JobInvolvement * 
                              WorkLifeBalance * DistanceFromHome

max_model <- buildmer::buildmer(formula = formula, 
  buildmerControl = buildmerControl(dep = "PerformanceRating", 
                                    direction = c("order", "backward"),
                                    quiet = TRUE, crit = "LRT"), data = data)

formula2 <- formula(max_model)
print(formula2)
## PerformanceRating ~ 1 + JobSatisfaction + JobInvolvement + DistanceFromHome

Die Rückwärtsselektion schlägt vor, die Variable Work-Life-Balance aus dem Modell zu entfernen. Es wurden keine Interaktionen identifiziert.

Modell mit allen Prädiktoren

Zunächst wird eine lineare Regression mit allen Prädiktoren berechnet. Alle Variablen werden z-standardisiert, um die Bedeutung der Prädiktoren zu prüfen.

set.seed(42)
modell1 <- lm(formula = PerformanceRating ~., 
              data = as.data.frame(scale(data)))

sjPlot::tab_model(modell1, title = "Linear model 1",
                  pred.labels = c("Intercept", "Distance From Home", 
                  "Job Involvement", "Job Satisfaction", "Work-Live Balance"),
  digits.re = 2, show.se = TRUE, show.stat = TRUE, 
  string.ci = "95% CI", string.est = "β", string.stat = "t",
  string.se = "SE", col.order = c("est", "se", "ci", "stat", "p"))
Linear model 1
  Performance Rating
Predictors β SE 95% CI t p
Intercept -0.00 0.03 -0.05 – 0.05 -0.00 1.000
Distance From Home -0.07 0.03 -0.12 – -0.02 -2.81 0.005
Job Involvement 0.11 0.03 0.06 – 0.16 4.52 <0.001
Job Satisfaction 0.20 0.03 0.16 – 0.25 8.09 <0.001
Work-Live Balance 0.05 0.03 -0.00 – 0.10 1.84 0.066
Observations 1470
R2 / R2 adjusted 0.061 / 0.058

Die Variablen Job Involvement und Job Satisfaction sind hochsignifikant. Der Prädiktor DistanceFromHome ist zwar signifikant, das Konfidenzintervall reicht jedoch fast bis zur Null. Die Work-Life-Balance ist nur marginal signifikant.

Modell ohne WorkLifeBalance
set.seed(42)
modell2 <- lm(formula = PerformanceRating ~.-WorkLifeBalance, 
              data = as.data.frame(scale(data)))

sjPlot::tab_model(modell2, title = "Linear model 2",
                  pred.labels = c("Intercept", "Distance From Home", 
                                  "Job Involvement", "Job Satisfaction"),
                  digits.re = 2, show.se = TRUE, show.stat = TRUE, 
                  string.ci = "95% CI", string.est = "β", string.stat = "t",
                  string.se = "SE", col.order = c("est", "se", "ci", "stat", "p"))
Linear model 2
  Performance Rating
Predictors β SE 95% CI t p
Intercept -0.00 0.03 -0.05 – 0.05 -0.00 1.000
Distance From Home -0.07 0.03 -0.12 – -0.02 -2.85 0.004
Job Involvement 0.11 0.03 0.06 – 0.16 4.49 <0.001
Job Satisfaction 0.20 0.03 0.15 – 0.25 8.04 <0.001
Observations 1470
R2 / R2 adjusted 0.059 / 0.057

Nach dem Entfernen der Work-Life-Balance aus dem Modell verbessert sich der p-Wert des Prädiktors DistanceFromHome leicht.

Likelihood Ratio Test

Mit einem Likelihood-Ratio-Test werden die beiden Modelle verglichen, um das bessere auszuwählen.

anova(modell1, modell2)
## Analysis of Variance Table
## 
## Model 1: PerformanceRating ~ DistanceFromHome + JobInvolvement + JobSatisfaction + 
##     WorkLifeBalance
## Model 2: PerformanceRating ~ (DistanceFromHome + JobInvolvement + JobSatisfaction + 
##     WorkLifeBalance) - WorkLifeBalance
##   Res.Df    RSS Df Sum of Sq      F  Pr(>F)  
## 1   1465 1379.6                              
## 2   1466 1382.8 -1   -3.1803 3.3772 0.06631 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Der Test zeigt nur eine marginale Signifikanz. Somit ist Modell 2 Modell 1 nicht eindeutig überlegen.

1.6 Modelldiagnostik

ggResidpanel::resid_panel(model = modell1, theme = "gray", smoother = TRUE)

Das Modell ist insgesamt zufriedenstellend, jedoch gibt es zwei Punkte zu beachten. Der Residuen-Plot zeigt zwar ein erwartbares gestaffeltes Muster aufgrund der 4-stufigen Likert-Skala, es gibt jedoch Anzeichen für Heteroskedastizität (ungleiche Varianzen). Im Q-Q-Plot und Histogramm zeigt sich zudem eine leichte Schiefe, was darauf hinweist, dass die Residuen nicht vollständig normalverteilt sind.

performance::check_distribution(modell1)
## # Distribution of Model Family
## 
## Predicted Distribution of Residuals
## 
##  Distribution Probability
##        normal         69%
##       tweedie          9%
##          beta          6%
## 
## Predicted Distribution of Response
## 
##   Distribution Probability
##         normal         47%
##           beta          9%
##  beta-binomial          9%

Ein Vergleich mit verschiedenen Verteilungen legt jedoch nahe, dass die vorhergesagten Verteilungen der Residuen und der Kriteriumsvariablen am wahrscheinlichsten normalverteilt sind.

1.7 Robuste Standardfehler und Konfidenzintervalle

Durch die Berechnung robuster Standardfehler und Konfidenzintervalle wird die lineare Regression robuster gegenüber Annahmeverletzungen wie Heteroskedastizität und Nicht-Normalverteilung der Residuen, was zu verlässlicheren Ergebnissen führt.

robust_se <- sandwich::vcovHC(modell1, type = "HC3")
confint_robust <- lmtest::coefci(modell1, vcov = robust_se)
print(confint_robust)
##                         2.5 %      97.5 %
## (Intercept)      -0.049740513  0.04974051
## DistanceFromHome -0.121505829 -0.02063850
## JobInvolvement    0.061628223  0.16724449
## JobSatisfaction   0.153812402  0.25581699
## WorkLifeBalance  -0.003849719  0.09696841

Das robuste Konfidenzintervall für Work-Life-Balance schließt die Null mit ein, was für Modell 2 ohne Work-Life-Balance als finales Modell spricht.

1.7 Kennwerte

Mit der Berechnung der Kennwerte “Nützlichkeit”, “Redundanz” und “Supression” kann die Wichtigkeit der einzelnen Prädiktoren detailliert analysiert werden.

Nützlichkeit

Die Nützlichkeit betrachtet den Varianzanteil, der ausschließlich auf einen bestimmten Prädiktor zurückzuführen ist. Prädiktoren mit geringer Nützlichkeit können ausgeschlossen werden.

nuetzlichkeit <- rep(NA, times=3)
names(nuetzlichkeit) <- c("DistanceFromHome", "JobInvolvement", "JobSatisfaction")

nuetzlichkeit["DistanceFromHome"] <- summary(modell2)$r.squared - summary(lm(data = data, 
                                        formula = PerformanceRating ~.-DistanceFromHome))$r.squared

nuetzlichkeit["JobInvolvement"] <- summary(modell2)$r.squared - summary(lm(data = data, 
                                          formula = PerformanceRating ~.-JobInvolvement))$r.squared

nuetzlichkeit["JobSatisfaction"] <- summary(modell2)$r.squared - summary(lm(data = data, 
                                        formula = PerformanceRating ~. -JobSatisfaction))$r.squared


enframe(nuetzlichkeit, name = "Predictor", value = "Value") %>% arrange(desc(Value))
## # A tibble: 3 × 2
##   Predictor          Value
##   <chr>              <dbl>
## 1 JobSatisfaction  0.0397 
## 2 JobInvolvement   0.0109 
## 3 DistanceFromHome 0.00288

Die Berechnungen zeigen, dass die Mitarbeiterzufriedenheit den höchsten Nützlichkeitswert aufweist, während DistanceFromHome nur eine geringe Nützlichkeit zeigt.

Redundanz

Ein Prädiktor ist redundant, wenn andere Prädiktoren einen wesentlichen Teil seiner Varianz erklären. Das Hinzufügen eines redundanten Prädiktors würde die Zusammenhänge anderer Prädiktoren auf das Kriterium (Arbeitsleistung) verringern. Redundante Prädiktoren sollten ausgeschlossen werden.

# Kriteriumskorrelationen bestimmen
correlations <- cor(data[,c(1:3, 5)])
print(correlations)
##                   DistanceFromHome JobInvolvement JobSatisfaction
## DistanceFromHome       1.000000000     0.00878328    -0.003668839
## JobInvolvement         0.008783280     1.00000000    -0.021475910
## JobSatisfaction       -0.003668839    -0.02147591     1.000000000
## PerformanceRating     -0.072054902     0.10873299     0.201711838
##                   PerformanceRating
## DistanceFromHome         -0.0720549
## JobInvolvement            0.1087330
## JobSatisfaction           0.2017118
## PerformanceRating         1.0000000
criterion_correlations <- correlations[4,1:3]
print(criterion_correlations)
## DistanceFromHome   JobInvolvement  JobSatisfaction 
##       -0.0720549        0.1087330        0.2017118
# Beta-Gewichte extrahieren
beta_weights <- modell2$coefficients[2:4]

# beta mal r berechnen
beta_times_r <- criterion_correlations * beta_weights

# beta_times_r vergleichen mit r²
ist_redundant <- abs(beta_times_r) < criterion_correlations^2
print(ist_redundant)
## DistanceFromHome   JobInvolvement  JobSatisfaction 
##            FALSE            FALSE            FALSE
# Stärke der Redundanz
redundanz <- criterion_correlations^2 - nuetzlichkeit
enframe(redundanz, name = "Predictor", value = "Value") %>% arrange(desc(Value))
## # A tibble: 3 × 2
##   Predictor           Value
##   <chr>               <dbl>
## 1 DistanceFromHome 0.00231 
## 2 JobSatisfaction  0.000940
## 3 JobInvolvement   0.000902

Keiner der Prädiktoren ist redundant. Allerdings erklären die Variablen Mitarbeiterzufriedenheit und Job Involvement einen Teil der Varianz von DistanceFromHome, wodurch sie wichtiger sind.

Supression

Eine Suppressor-Variable erhöht das R² des Modells, indem sie Varianzen in anderen Prädiktoren unterdrückt. Dies verstärkt den positiven Zusammenhang eines anderen Prädiktors mit dem Kriterium. Suppressor-Variablen sollten im Modell bleiben.

# r² mit Nuetzlichkeit vergleichen
suppression <- criterion_correlations^2 < nuetzlichkeit
print(suppression)
## DistanceFromHome   JobInvolvement  JobSatisfaction 
##            FALSE            FALSE            FALSE

Es zeigen sich bei den Prädiktoren keine Supressionseffekte.

4.8 Visualisierung (Wichtigkeit der Variablen)

coefficients_df <- broom::tidy(modell2)

coefficients_df %>%
  dplyr::filter(term != "(Intercept)") %>%
  ggplot2::ggplot(aes(x = reorder(term, estimate), y = estimate)) +
  geom_col() +
  labs(title = "Wichtigkeit der Variablen basierend auf Regressionskoeffizienten",
       x = "Variablen",
       y = "Koeffizienten") +
  papaja::theme_apa()

Die Regressionskoeffizienten zeigen, dass die Mitarbeiterzufriedenheit den größten Einfluss auf die Arbeitsleistung hat. Ebenfalls wichtig ist das Job Involvement, während die Länge des Arbeitswegs einen schwächeren, negativen Einfluss auf die Performanz hat.