Projekt HR
Wstęp
Poniższy projekt przedstawia analizę danych opartą na danych zawierających informacje dotyczące pracowników pewnej firmy. Główną zmienną, której dotyczy analiza to attrition, czyli rezygnowanie z pracy. Analiza opiera się na zbadaniu motywacji, przyczyn, zależności pomiędzy odchodzeniem z pracy a innymi zmiennymi.
Powstawić można hipotezę badawczą - co wpływa na odchodzenie z pracy przez pracowników?
Projekt zawiera się w trzech głównych etapach: 1. Data cleansing, Wrangling, 2. Wizualizacja danych, 3. Analiza opisowa i wnioskowanie statystyczne.
Celem projektu jest wykonanie analizy skupiając się na zmiennej ‘attrition’, opartej na przygotowanym zbiorze danych.
Wczytanie bibliotek
Etap 1. Data cleansing
Wstęp
W procesie analizy danych kluczowym etapem jest ich oczyszczenie, aby zapewnić poprawność i spójność zbioru. W pierwszej kolejności sprawdzono kompletność danych, identyfikując brakujące wartości oraz analizując ich rozkład za pomocą wykresów i podsumowań statystycznych. Następnie zweryfikowano zgodność zmiennych z określonymi regułami, skorygowano błędy oraz uzupełniono braki imputacją, co umożliwiło dalszą rzetelną analizę danych.
W celu wykonania projektu wczytano zestaw danych.
dane <- read.csv(file = "HR.csv")
Kolejne wczytanie danych z nagłówkami i specyficznymi separatorami.
tabela <- read.csv("HR.csv", header= TRUE, sep=",", dec=",")
Następnie wyświetlono dane z tabeli, aby wstępnie zweryfikować ich poprawność, ilość oraz aby zyskać ogólny pogląd na badane wartości.
View(tabela)
Ważnym krokiem analizy jest sprawdzenie liczby brakujących wartości w całym zbiorze danych. Uzyskana wartość to łączna liczba brakujących obserwacji wśród wszystkich zmiennych.
sum(is.na(tabela))
## [1] 400
Aby dowiedzieć się szczegółów dotyczących braków zmiennych wykonano wykres brakujących wartości. Przedstawia on wszystkie zmienne występujące w zbiorze danych oraz wskazuje te, które zawierają puste wartości. Jak można odczytać z poniższego wykresu, w zbiorze występują trzy zmienne, które mają braki. Są to kolejno: Age (100), MonthlyIncome (150) oraz Attrition(150).
plot_missing(tabela)
Kolejną metodą sprawdzającą braki danych jest shadowmapa. Pokazuje ona, w których kolumnach znajdują się brakujące dane oraz zwraca ich liczbę.
gg_miss_var(tabela) + labs( title = "Shadowmapa brakujących danych", x =
"Kolumny", y = "Liczba brakujących wartości" )
Poniżej zastosowano bardziej szczegółowy wykres, który pokazuje nie tylko w których zmiennych są braki, ale także wskazuje wiersz, w którym one występują.
vis_miss(tabela)
Podsumowanie braków danych w formie tabeli.
wybrane_kolumny <- dplyr::select(tabela, Attrition, MonthlyIncome, Age)
miss_var_summary(wybrane_kolumny)
## # A tibble: 3 × 3
## variable n_miss pct_miss
## <chr> <int> <num>
## 1 Attrition 150 10.2
## 2 MonthlyIncome 150 10.2
## 3 Age 100 6.80
Wizualizacja braków danych w formie wykresu słupkowego. Poniżej wyświetlane są zależności pomiędzy brakami danych. Z wykresu wynika, że nie ma wzorca braku danych, są one niezależne. Jest niewiele przypadków (łącznie 34), gdzie brakuje więcej niż jednej zmiennej w wierszu, ale nie można tego uznać za regułę.
gg_miss_upset(tabela)
Kolejnym krokiem w przygotowaniu danych do ich póżniejszej analizy jest sprawdzenie ich spójności. Dane powinny spełniać określone przez analityka reguły, aby nie fałszowały późniejszych obliczeń. W tym projekcie określono pięć reguł, które musiały zostać spełnione przez odpowiednie zmienne. Są to kolejno: wiek pracownika większy lub równy od 18 i mniejszy od 100, odejście pracownika z firmy ma mieć wartość prawda lub fałsz, miesięczny dochód większy od zera oraz lata pracy z firmie większe lub równe zero.
RULE <- editset(c(
"Age >= 18",
"Age <100",
"Attrition %in% c('Yes','No')",
"MonthlyIncome > 0",
"YearsAtCompany >= 0"
))
RULE
##
## Data model:
## dat1 : Attrition %in% c('No', 'Yes')
##
## Edit set:
## num1 : 18 <= Age
## num2 : Age < 100
## num3 : 0 < MonthlyIncome
## num4 : 0 <= YearsAtCompany
Wynik analizy przedstawia liczbę naruszeń określonych reguł w zbiorze danych, wskazując, które zmienne nie spełniają założeń dotyczących poprawnych wartości. Wykres dodatkowo wizualizuje skalę tych naruszeń, co pozwala na szybkie zidentyfikowanie obszarów wymagających korekty.
violations <- violatedEdits(RULE, tabela)
summary(violations)
## Edit violations, 1470 observations, 0 completely missing (0%):
##
## editname freq rel
## dat1 150 10.2%
##
## Edit violations per record:
##
## errors freq rel
## 0 1105 75.2%
## 1 253 17.2%
## 2 90 6.1%
## 3 21 1.4%
## 4 1 0.1%
summary(violatedEdits(RULE, tabela))
## Edit violations, 1470 observations, 0 completely missing (0%):
##
## editname freq rel
## dat1 150 10.2%
##
## Edit violations per record:
##
## errors freq rel
## 0 1105 75.2%
## 1 253 17.2%
## 2 90 6.1%
## 3 21 1.4%
## 4 1 0.1%
plot(violations)
Zidentyfikowane w poprzednim kroku naruszenia reguł zamieniono na NA - puste wartości. W kolejnych krokach dane te zostaną wypełnione wybraną metodą.
for (i in 1:nrow(violations)) {
for (j in 1:ncol(violations)) {
if (!is.na(violations[i, j]) && violations[i, j]) {
dane[i, colnames(violations)[j]] <- NA
}
}
}
Funkcja kNN() z pakietu VIM uzupełnia brakujące wartości w zbiorze danych za pomocą metody k najbliższych sąsiadów (k-Nearest Neighbors, k-NN). Wybiera k = 5 najbardziej podobnych obserwacji i na ich podstawie imputuje brakujące wartości. Dzięki temu powstaje nowy zbiór danych (tabela_knn), w którym luki w danych zostały zastąpione przewidywanymi wartościami.
tabela_knn <- kNN(tabela, k = 5)
sum(is.na(tabela_knn))
## [1] 0
Poniższy wykres przedstawia wartości odstające w badanej populacji.
boxplot(tabela$Age)
boxplot(tabela$MonthlyIncome)
Podsumowanie
Proces oczyszczania danych pozwolił na identyfikację brakujących wartości oraz niezgodności w zbiorze, co umożliwiło ich skuteczną korektę. Zastosowane metody wizualizacji i analizy wykazały, że trzy zmienne zawierały braki, które następnie uzupełniono metodą imputacji. Dodatkowo zweryfikowano zgodność danych z określonymi regułami i skorygowano błędne wartości, aby zapewnić ich spójność. Finalnie, oczyszczony zbiór danych jest gotowy do dalszej analizy, eliminując ryzyko błędnych wniosków wynikających z braków i niespójności.
Etap 2. Data wrangling
Wstęp
W celu lepszego zrozumienia struktury zatrudnienia i wynagrodzeń w firmie dokonano filtrowania oraz analizy wybranych zmiennych. Szczególną uwagę poświęcono młodym pracownikom o niskich dochodach i krótkim stażu, a także ogólnej strukturze zatrudnienia w różnych działach i stanowiskach.
Poniżej zastosowano filtrowanie wybranych zmiennych. Wynik zawiera pracowników młodych, o niskich dochodach i krótkim stażu u obecnego menedżera, co może wskazywać na grupę o wyższym ryzyku rotacji lub dopiero rozpoczynającą karierę.
tabela_knn %>%
filter(Age < 22, MonthlyIncome < 1500, YearsWithCurrManager < 5) %>%
dplyr::select(Age, BusinessTravel, Department, Education, Gender, MonthlyIncome, YearsWithCurrManager)
## Age BusinessTravel Department Education Gender MonthlyIncome
## 1 21 Travel_Rarely Research & Development 2 Male 1232
## 2 19 Travel_Rarely Research & Development 3 Male 1102
## 3 18 Travel_Rarely Research & Development 3 Male 1420
## 4 18 Non-Travel Research & Development 2 Male 1051
## 5 21 Travel_Rarely Research & Development 3 Female 1416
## YearsWithCurrManager
## 1 0
## 2 0
## 3 0
## 4 0
## 5 0
Poniżej dokonano sortowania danych za pomocą jednej lub więcej zmiennych. Dodatkowo użyto funkcji ‘count’, aby zliczyć posortowane obserwacje.
tabela_knn %>%
count(Department)
## Department n
## 1 Human Resources 63
## 2 Research & Development 961
## 3 Sales 446
tabela_knn %>%
count(Gender)
## Gender n
## 1 Female 588
## 2 Male 882
tabela_knn %>%
count(JobRole)
## JobRole n
## 1 Healthcare Representative 131
## 2 Human Resources 52
## 3 Laboratory Technician 259
## 4 Manager 102
## 5 Manufacturing Director 145
## 6 Research Director 80
## 7 Research Scientist 292
## 8 Sales Executive 326
## 9 Sales Representative 83
Zagłębiając się w funkcję sortowania, wykonano podsumowanie libczy osób na danych stanowiskach wraz z podaniem średniego zarobku na tym stanowisku. Uzyskane informacje posortowano malejąco. Z poniższej analizy wynika, że najwięcej osób pracowało na stanowisku dyrektora ds. sprzedaży, natomiast najmniej w dziale zasobów ludzkich. Średnio najlepiej wynagradzanym stanowiskiem był przedstawiciel handlowy, natomiast najlepiej wynagradzanym był manager.
tabela_knn %>%
group_by(JobRole) %>%
summarise(
Liczba_osób = n(),
Średni_zarobek = mean(MonthlyIncome)
) %>%
arrange(desc(Liczba_osób))
## # A tibble: 9 × 3
## JobRole Liczba_osób Średni_zarobek
## <chr> <int> <dbl>
## 1 Sales Executive 326 6902.
## 2 Research Scientist 292 3204.
## 3 Laboratory Technician 259 3218.
## 4 Manufacturing Director 145 7265.
## 5 Healthcare Representative 131 7427.
## 6 Manager 102 17119.
## 7 Sales Representative 83 2705.
## 8 Research Director 80 15818.
## 9 Human Resources 52 4241.
Podsumowanie
Analiza wykazała, że wśród młodych pracowników o niskich dochodach mogą znajdować się osoby o wyższym ryzyku rotacji. Dodatkowo, struktura zatrudnienia wskazuje na dominację mężczyzn w firmie oraz największą liczbę pracowników w dziale badań i rozwoju. Pod względem wynagrodzenia najlepiej opłacanym stanowiskiem był manager, co sugeruje istotne różnice w wynagrodzeniach zależnie od roli w organizacji.
Etap 3. Data visualization
Wstęp
Analiza danych wizualizacyjnych pozwala na lepsze zrozumienie czynników wpływających na satysfakcję i rotację pracowników. W niniejszym etapie przedstawiono różne aspekty związane z zatrudnieniem, takie jak wynagrodzenie, staż pracy, wykształcenie, wiek oraz satysfakcja zawodowa, które mogą wpływać na decyzje o pozostaniu lub odejściu z firmy. Pozwolą one na lepsze zrozumienie co motywuje pracowników do opuszczania firmy.
Wykres 1 - Satysfakcja z pracy
Poniższy wykres przedstawia jak pracownicy z podziałem na płeć oceniali swoją staysfkację z pracy w czteropunktowej skali. Zdecydowanie więcej mężczyzn wskazało dwa najwyższe poziomy zadowolenia w porównaniu do kobiet.
ggplot(tabela_knn, aes(x=JobSatisfaction)) +
geom_histogram(bins=10) +
labs(title="Satysfakcja z pracy", x="Ocena od 1 do 4", y="Liczba osób") +
theme_bw() +
facet_grid(~Gender)
Wykres 2 - Zależność wieku względem zarobków
Ten punktowy wykres przedstawia zależność wieku pracownika względem jego zarobków. W tym przypadku logiczne założenie, że wraz z wiekiem zarobki powinny rosnąć jak najbardziej się sprawdza. Jak widać linia trendu jest rosnącą funckją liniową, wskazującą na średni wzrost zarobków względem wieku. Naturalnie występują wartości skrajnie odstające, gdzie 60 - latek zarabia mniej niż 20 - latek czy 30 - latek. Dodatkowo wykres podzielono względem płci. Linie trendu praktycznie się na siebie nakładają, co wskazuje na to, że płeć nie ma zbytniego wpływu na zarobki względem wieku - liczy się doświadczenie.
ggplot(tabela_knn, aes(x=Age, y=MonthlyIncome, color=Gender)) +
geom_point() +
geom_smooth(method="lm") +
theme_light() +
theme(legend.position = c(0.1, 0.85)) +
labs(
title = "Zależność wieku względem zarobków",
x = "Wiek",
y = "Miesięczne zarobki")
## Warning: A numeric `legend.position` argument in `theme()` was deprecated in ggplot2
## 3.5.0.
## ℹ Please use the `legend.position.inside` argument of `theme()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using formula = 'y ~ x'
Wykres 3 - Zależność satysfakcji z pracy względem odejść praconików
Na poniższym wykresie przedstawiono jak satysfakcja z pracy wpływa na decyzję pracownika o odejściu. Zdecydowanie widać, iż więcej jest pracowników, którzy zostają w firmie niż tych, którzy z niej odchodzą. Badana populacja wykazuje się bardzo wysoką satysfakcją z pracy - tych, którzy zostali i ocenili swoje zadowolonie najwyższym punktem jest niemalże dwuktornie więcej niż tych najmniej zadowolonych. Natomiast odejście z pracy nie do końca podyktowane jest małą satysfakcją z pracy. Najwięcej pracowników, którzy odeszli z firmy ocenili swoje zadolowanie na 3 w czterostopniowej skali. Zatem wysoka satysfakcja nie gwarantuje zatrzymania pracownika.
ggplot(data = tabela_knn, aes(x = JobSatisfaction, fill = Attrition)) +
geom_histogram(binwidth = 1, position = "dodge", color = "black") +
facet_grid(. ~ Attrition) +
scale_fill_manual(values = c("skyblue", "orange")) +
labs(
title = "Rozkład satysfakcji pracy do odejść pracowników",
x = "Satysfakcja z pracy",
y = "Liczba osób",
fill = "Odejście pracownika"
) +
theme_minimal()
Wykres 4 - Zależność liczby lat pracy w firmie względem odejść
Wykres ten pokazuje, jak liczba lat pracy rozkłada się w grupie pracowników, którzy odeszli, w porównaniu do tych, którzy pozostali w firmie. Widać bardzo wyraźnie, iż najwięcej ludzi odchodzi z pracy do 10 lat stażu. Później odsetek ten znacznie spada, a czasem nawet nie występuje - staje się wyjątkiem. Mimo to należy zauważyć, że znaczna większość pracowników nie decyduje się w ogóle rezygnować z pracy w przeciągu tych 10 pierwszych lat.
ggplot(data = tabela_knn, aes(x = YearsAtCompany, fill = Attrition)) +
geom_histogram(binwidth = 1, position = "dodge", color = "black") +
facet_grid(. ~ Attrition) +
scale_fill_manual(values = c("darkgreen", "orange")) +
labs(
title = "Zależność liczby lat pracy w firmie względem odejść",
x = "liczby lat pracy w firmie",
y = "Liczba osób",
fill = "Odejście pracownika"
) +
theme_minimal()
Wykres 5 - Zależność liczby stawki godzinowej względem odejść
Rozkłady dla obu grup są bardzo podobne – zakres wartości, mediana oraz rozstęp międzykwartylowy są niemal identyczne, co sugeruje, że wysokość stawki godzinowej nie miała istotnego wpływu na decyzję o odejściu. Brak wyraźnych różnic między grupami oznacza, że inne czynniki, a nie wysokość wynagrodzenia godzinowego, mogły bardziej wpływać na rotację pracowników.
ggplot(tabela_knn, aes(x = Attrition, y = HourlyRate )) +
geom_boxplot() +
coord_flip()
labs(
title = "Wykres pudełkowy dla zmiennej Attrition",
x = "Attrition (Yes/No)",
y = "HourlyRate"
) +
theme_minimal()
## NULL
Wykres 6 - Zależność liczby lat od ostatniego awansu względem odejść
Wykres ten ma rozkład bardzo podobny do czwartego - większość pracowników odchodzi kiedy od ostatniego awansu nie minęło więcej niż 3 lata. Może to wskazywać na potrzebę nagradzania pracowników promocją w pierwszych latach ich stażu pracy.
ggplot(data = tabela_knn, aes(x = YearsSinceLastPromotion, fill = Attrition)) +
geom_histogram(binwidth = 1, position = "dodge", color = "white") +
facet_grid(. ~ Attrition) +
scale_fill_manual(values = c("skyblue", "violet")) +
labs(
title = "Zależność liczby lat od ostatniego awansu względem odejść",
x = "lata od ostatniego awansu",
y = "Liczba osób",
fill = "Odejście pracownika"
) +
theme_minimal()
Wykres 7 - Korelacja rotacji pomiędzy działami względem odejść
Wykres ten przedstawia zestawienie działów i odejść pracowników. Można zauważyć, że są one na podobnym poziomie - największa różnica to 6 punktów procentowych. Wskazuje to na niewielki wpływ tej zmiennej na badanie motywacji pracowników do zmieniania miejsca pracy.
data_percent <- tabela_knn %>%
group_by(Department, Attrition) %>%
summarise(count = n()) %>%
group_by(Department) %>%
mutate(percent = count / sum(count) * 100)
## `summarise()` has grouped output by 'Department'. You can override using the
## `.groups` argument.
ggplot(data_percent, aes(x=Department, y=count, fill=Attrition)) +
geom_bar(stat="identity", position="dodge") +
geom_text(aes(label=sprintf("%.1f%%", percent)), position=position_dodge(width=0.9), vjust=-0.25) +
theme_light() +
labs(
title = "Zależność rotacji pracownikow pomiedzy dzialami a odejscia z pracy",
x = "Dział",
y = "Liczba osób",
fill = "Odejście pracownika"
) +
theme(legend.position = c(0.85, 0.85))
Wykres 8 - Korelacja wybranych zmiennych (wiek, dochód, staż pracy, satysfakcja z pracy) względem odejść pracowników
Analizując korelacje zmiennej odejścia pracowników z innymi zmiennymi, można zauważyć następujące zależności:
Korelacja z wiekiem (-16,5%) – starsi pracownicy rzadziej odchodzą z firmy, co może wynikać z większej stabilności zawodowej lub większych korzyści związanych z długoterminowym zatrudnieniem.
Korelacja z miesięcznym dochodem (-15,5%) – osoby zarabiające więcej są mniej skłonne do odejścia, co może wskazywać na wpływ wynagrodzenia jako czynnika motywującego do pozostania w firmie.
Korelacja ze stażem pracy w firmie (-13,6%) – dłuższy staż pracy wiąże się z mniejszym prawdopodobieństwem rezygnacji, co może oznaczać, że pracownicy przywiązują się do organizacji wraz z upływem czasu.
Korelacja z satysfakcją z pracy (-10,6%) – choć relacja jest stosunkowo słaba, można zauważyć, że osoby mniej zadowolone z pracy częściej odchodzą, co potwierdza intuicyjny związek między satysfakcją a lojalnością wobec firmy.
# Tworzenie zmiennej binarnej dla Attrition
tabela_knn$Attrition_bin <- ifelse(tabela_knn$Attrition == "Yes", 1, 0)
# Wybrane zmienne do analizy
selected_vars <- tabela_knn[, c("Age", "MonthlyIncome", "JobSatisfaction", "YearsAtCompany", "Attrition_bin")]
# Obliczenie macierzy korelacji
cor_matrix <- cor(selected_vars, use = "complete.obs")
# Zamiana macierzy korelacji na procenty
cor_matrix_percent <- cor_matrix * 100
# Przekształcenie macierzy do formatu długiego
melted_cor_matrix <- melt(cor_matrix_percent)
# Tworzenie heatmapy z wartościami procentowymi
ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "darkblue", high = "darkred", mid = "white", midpoint = 0, limit = c(-100, 100), space = "Lab", name="Korelacja (%)") +
geom_text(aes(label = sprintf("%.1f%%", value)), color = "black", size = 4) + # Dodanie etykiet procentowych
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
coord_fixed()
Wykres 9 - Korelacja wybranych zmiennych (płeć, wiek, stan cywilny) względem odejść pracowników
- Proporcje odejść wśród mężczyzn i kobiet są bardzo zbliżone. Płeć nie wydaje się zatem istotnym czynnikiem wpływającym na odejścia.
- Osoby stanu wolnego mają wyraźnie wyższą skłonność do odejścia w porównaniu do osób zamężnych żonatych oraz rozwiedzionych.
- Osoby, które odchodzą, częściej otrzymują niższe wynagrodzenie. Widać największą różnicę w przedziale do około 5000 jednostek – tu występuje najwięcej odejść.
- Nadgodziny zwiększają odejścia. Jeśli pracownicy pracują ponad normę, mogą być bardziej skłonni do rezygnacji.
# Tworzenie zmiennej binarnej dla Attrition (1 = Yes, 0 = No)
tabela_knn$Attrition_bin <- ifelse(tabela_knn$Attrition == "Yes", 1, 0)
# 1. Rozkład odejść w zależności od płci (Gender)
ggplot(tabela_knn, aes(x = Gender, fill = Attrition)) +
geom_bar(position = "fill") +
labs(title = "Rozkład odejść w zależności od płci", y = "Proporcja", x = "Płeć") +
scale_fill_manual(values = c("No" = "lightblue", "Yes" = "darkred"), name = "Attrition") +
theme_minimal()
# 2. Rozkład odejść w zależności od stanu cywilnego (MaritalStatus)
ggplot(tabela_knn, aes(x = MaritalStatus, fill = Attrition)) +
geom_bar(position = "fill") +
labs(title = "Rozkład odejść w zależności od stanu cywilnego", y = "Proporcja", x = "Stan cywilny") +
scale_fill_manual(values = c("No" = "lightblue", "Yes" = "darkred"), name = "Attrition") +
theme_minimal()
# 3. Wpływ wynagrodzenia (MonthlyIncome) na odejścia
ggplot(tabela_knn, aes(x = MonthlyIncome, fill = Attrition)) +
geom_density(alpha = 0.5) +
labs(title = "Wpływ wynagrodzenia na odejścia", x = "Miesięczne wynagrodzenie", y = "Gęstość") +
scale_fill_manual(values = c("No" = "lightblue", "Yes" = "darkred"), name = "Attrition") +
theme_minimal()
# 4. Odejścia w zależności od liczby godzin pracy (OverTime)
ggplot(tabela_knn, aes(x = OverTime, fill = Attrition)) +
geom_bar(position = "fill") +
labs(title = "Odejścia a nadgodziny", y = "Proporcja", x = "Nadgodziny") +
scale_fill_manual(values = c("No" = "lightblue", "Yes" = "darkred"), name = "Attrition") +
theme_minimal()
Podsumowanie
Przedstawione wizualizacje dostarczają cennych informacji na temat czynników determinujących satysfakcję i rotację pracowników. Widać wyraźne zależności między stażem pracy, wynagrodzeniem oraz awansami a decyzją o odejściu, natomiast płeć nie wydaje się istotnym czynnikiem wpływającym na rotację. Najbardziej narażeni na odejście są pracownicy we wczesnym etapie kariery, zwłaszcza jeśli ich wynagrodzenie nie rośnie lub nie otrzymują awansu. Wyniki te mogą być pomocne w opracowaniu skutecznych strategii zarządzania zasobami ludzkimi, które pozwolą na zwiększenie rotacji pracowników i poprawę ich satysfakcji zawodowej.
Etap 3. Analiza opisowa i wnioskowanie statystyczne
Wstęp
Analiza statystyczna pozwala zrozumieć, jakie czynniki mogą wpływać na decyzję pracowników o odejściu z firmy. Wykorzystane metody, takie jak testy t-Studenta, ANOVA, analiza korelacji czy regresja liniowa, pomagają w identyfikacji zależności między zmiennymi. Szczególną uwagę poświęcono zróżnicowaniu dochodów, wpływowi wieku na decyzje o pozostaniu w firmie oraz nierównościom w rozkładzie wieku.
Podstawowe statystyki wieku w zależności od odejścia
Tabela pokazuje średni dochód, medianę oraz odchylenie standardowe wynagrodzenia dla dwóch grup pracowników - tych którzy odeszli z firmy i tych którzy w niej zostali. Pracownicy, którzy nie odeszli, mają wyższy średni dochód niż ci, którzy odeszli. To sugeruje, że osoby z niższym wynagrodzeniem częściej odchodzą. Mediana również pokazuje znaczącą różnicę: 5189.5 (pozostali) vs. 3017.5 (odeszli). Oznacza to, że większość osób odchodzących zarabiała znacznie mniej niż większość tych, którzy zostali. W obu grupach odchylenie standardowe jest wysokie, co oznacza duże zróżnicowanie wynagrodzeń. Jednak pracownicy, którzy pozostali, mają większe zróżnicowanie płac (4775 vs. 3662), co sugeruje, że w tej grupie mogą być zarówno osoby z wysokimi, jak i niskimi zarobkami.
income_summary <- tabela_knn %>% group_by(Attrition) %>%
summarise(Średni_dochód = round(mean(MonthlyIncome, na.rm = TRUE), 0),
Mediana_dochodu = median(MonthlyIncome, na.rm = TRUE),
Odchylenie_standardowe = round(sd(MonthlyIncome, na.rm = TRUE), 0))
print(income_summary)
## # A tibble: 2 × 4
## Attrition Średni_dochód Mediana_dochodu Odchylenie_standardowe
## <chr> <dbl> <dbl> <dbl>
## 1 No 6767 5190. 4775
## 2 Yes 4725 3018. 3662
Miary pozycyjne
Wyniki przedstawiają kwartyle oraz rozstęp międzykwartylowy (IQR) dla wieku. Wynika z tego, że:
25% obserwacji ma wartość wieku mniejszą lub równą 30
Połowa wartości wieku jest mniejsza lub równa 35
75% obserwacji ma wartość wieku mniejszą lub równą 43
(30 - 43) rozstęp 13-stu lat, w którym znajduje się środkowe 50% danych
quantile(tabela_knn$Age, probs = c(0.25, 0.5, 0.75))
## 25% 50% 75%
## 30 35 43
IQR(tabela_knn$Age)
## [1] 13
Miary zróżnicowania
Policzono trzy miary zróżnicowania, kolejno: rozstęp, wariancję i odchylenie standardowe. Wyniki są następujące:
Najmłodsza osoba w zbiorze danych ma 18 lat, a najstarsza 60 lat (zakres wieku to 42 lata)
wysoka wartość wariancji sugeruje, że wartości są rozproszone i zróżnicowanie
przeciętnie, wartości wieku różnią się od średniej o prawie 9 lat
dane są stosunkowo wysoko zróżnicowane względem ich średniej wartości
range(tabela_knn$Age)
## [1] 18 60
var(tabela_knn$Age)
## [1] 80.4288
sd(tabela_knn$Age)
## [1] 8.96821
cv_age <- sd(tabela_knn$Age) / mean(tabela_knn$Age) * 100
cv_age
## [1] 24.3153
Analiza rozkładu danych
Poniżej, obliczono wartość skośności oraz kurtozy, aby określić rozkład danych. Skośność wieku wynosi 0,46 - dodatnia wartość wskazuje na skośność prawostronną oraz więcej młodszych pracowników. Kurtoza wieku wynosi 2,67, co oznacza, że rozkład wieku jest lekko spłaszczony, w porównaniu do normalnego.
skewness(tabela_knn$Age)
## [1] 0.460907
kurtosis(tabela_knn$Age)
## [1] 2.67162
Reguła empiryczna
W celu policzenia reguł empirycznych wybrano trzy wartości: 68%, 95% i 99,7% obserwacji. Oznacza to, że:
68% pracowników mieści się w przedziale 27-46 lat
95% mieści się w przedziale 19-55 lat
99,7% mieści się w przedziale 10-64 lat
mean_age <- mean(tabela_knn$Age)
sd_age <- sd(tabela_knn$Age)
c(mean_age - sd_age, mean_age + sd_age)
## [1] 27.9148 45.8512
c(mean_age - 2*sd_age, mean_age + 2*sd_age)
## [1] 18.9466 54.8194
c(mean_age - 3*sd_age, mean_age + 3*sd_age)
## [1] 9.97837 63.78762
Testy normalności
Test Shapiro-Wilka służy do sprawdzenia normalności rozkładu danej zmiennej. Hipoteza zerowa mówi, że dane pochodzą z rozkładu normalnego, względem alternatywy, że tak nie jest. Z racji, że wartość p-value jest niższa niż 0.01 odrzucamy hipotezę zerową na rzecz alternatywy. Oznacza to, że rozkład wieku nie jest normalny w obydwu badanych przypadkach zmiennych.
shapiro.test(tabela_knn$Age)
##
## Shapiro-Wilk normality test
##
## data: tabela_knn$Age
## W = 0.9749, p-value = 0.00000000000000241
shapiro.test(tabela_knn$TotalWorkingYears)
##
## Shapiro-Wilk normality test
##
## data: tabela_knn$TotalWorkingYears
## W = 0.9074, p-value <0.0000000000000002
Test t-Studenta
Zastosowano test t-Studenta, aby porównać średni wiek pracowników, którzy zostali w firmie z tymi, którzy odeszli. Wyniki są następujące:
P-value jest ekstremalnie niskie (p < 0.05), więc istnieje istotna statystycznie różnica między średnimi wieku pracowników, którzy zostali, a tych, którzy odeszli.
Średnia wieku pracowników, którzy pozostali w firmie, wynosi 37.50 lat, podczas gdy średnia wieku osób, które odeszły, to 33.33 lat.
Przedział ufności (2.83 – 5.51) nie obejmuje zera, co dodatkowo potwierdza, że różnica między grupami jest statystycznie istotna.
t.test(Age ~ Attrition, data = tabela_knn)
##
## Welch Two Sample t-test
##
## data: Age by Attrition
## t = 6.125, df = 286.9, p-value = 0.00000000298
## alternative hypothesis: true difference in means between group No and group Yes is not equal to 0
## 95 percent confidence interval:
## 2.83089 5.51175
## sample estimates:
## mean in group No mean in group Yes
## 37.5016 33.3303
ANOVA
Analiza wariancji została zastosowana do sprawdzenia, czy istnieją istotne różnice w liczbie lat pracy między pracownikami różnych działów. Wnioski są następujące:
P-value = 0.83, co oznacza, że nie ma istotnych statystycznie różnic w liczbie lat pracy
Niska wartość F (0.18) sugeruje, że różnice między średnimi dla działów są bardzo małe w porównaniu do zmienności wewnątrz grup. Przynależność do działu nie wpływa istotnie na liczbę lat pracy – staż pracowników jest podobny niezależnie od działu.
anova_model <- aov(TotalWorkingYears ~ Department, data = tabela_knn)
summary(anova_model)
## Df Sum Sq Mean Sq F value Pr(>F)
## Department 2 22 11.1 0.18 0.83
## Residuals 1467 88912 60.6
Test chi-kwadrat
Test Chi-kwadrat został użyty do zbadania, czy istnieje zależność między odejściem pracownika z firmy a poziomem wykształcenia. Wnioski są następujące:
p-value = 0.314, co oznacza, że poziom wykształcenia nie ma istotnego wpływu na decyzję o odejściu z firmy.
staystyka jest niska, co oznacza, że różnice między rzeczywistymi a oczekiwanymi wartościami są niewielkie.
Wniosek: Wykształcenie nie wpływa istotnie na rotację pracowników.
chisq.test(table(tabela_knn$Attrition, tabela_knn$Education))
##
## Pearson's Chi-squared test
##
## data: table(tabela_knn$Attrition, tabela_knn$Education)
## X-squared = 4.751, df = 4, p-value = 0.314
Test chi-kwadrat 2
Test Chi-kwadrat został użyty do zbadania, czy istnieje zależność między odejściem pracownika z firmy a stanowiskiem. Wnioski są następujące:
p-value < 0.05 co oznacza, że stanowisko ma bardzo duże znaczenie w kontekście odejść z pracy
staystyka jest wysoka, co oznacza, że różnice między rzeczywistymi a oczekiwanymi wartościami są duże.
Wniosek: Odejścia są silnie zależne od stanowiska. Niektóre stanowiska mogą mieć znacznie większą rotację niż inne.
chisq.test(table(tabela_knn$Attrition, tabela_knn$JobRole))
##
## Pearson's Chi-squared test
##
## data: table(tabela_knn$Attrition, tabela_knn$JobRole)
## X-squared = 84.93, df = 8, p-value = 0.00000000000000495
Test korelacji Pearsona
Zbadano korelację pomiędzy wiekiem a całkowitą liczbą lat pracy. Wysoka wartość statystyki wskazuje na silną zależność między zmiennymi. Bardzo niska wartość p-value oznacza, że możemy odrzucić hipotezę zerową stanowiącą o braku korelacji pomiędzy wiekiem a całkowitą liczbą lat pracy. Całkiem wysoka wartość współczynnika oznacza, że im wyższy wiek, tym większa liczba lat przepracowanych.
cor.test(tabela_knn$Age, tabela_knn$TotalWorkingYears)
##
## Pearson's product-moment correlation
##
## data: tabela_knn$Age and tabela_knn$TotalWorkingYears
## t = 35.55, df = 1468, p-value <0.0000000000000002
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.651657 0.706679
## sample estimates:
## cor
## 0.680125
Regresja liniowa
Poniżej sformułowano regresję liniową, w której odejscia z pracy są wyjaśniane przez wiek oraz dochód, odległość od domu, satysfakcję z pracy, staż pracy, nadgodziny, lata od ostatniego awansu. Z regresji tej wynika, że:
każdy dodatkowy rok życia zmniejsza prawdopodobienstwo odejścia z pracy o 0.00465
z każdym wzrostem miesięcznego wynagrodzenia o 1 zmniejsza się prawdopodobienstwo odejścia z pracy o 0.00000736
zwiększenie dystansu od domu o 1 jednostkę zwiększa prawdopodobienstwo odejścia z pracy o 0.00382
każdy dodatkowy rok pracy w firmie zmniejsza prawdopodobienstwo odejścia z pracy o 0.00669
kiedy pracownik ma nadgodziny to zwiększa się prawdopodobienstwo odejścia z pracy o 0.18509, niż gdyby ich nie miał
Wszystkie zmienne są istotne statystycznie na poziomie przynajmniej 1%. Model wyjaśniany jest w 11,3%.
tabela_knn_num <- tabela_knn
tabela_knn_num$Attrition <- as.numeric(as.factor(tabela_knn_num$Attrition)) - 1
tabela_knn_num$OverTime <- as.numeric(as.factor(tabela_knn_num$OverTime)) - 1
reg_model <- lm(Attrition ~ Age+MonthlyIncome+DistanceFromHome+JobSatisfaction+YearsAtCompany+OverTime+YearsSinceLastPromotion, data = tabela_knn_num)
summary(reg_model)
##
## Call:
## lm(formula = Attrition ~ Age + MonthlyIncome + DistanceFromHome +
## JobSatisfaction + YearsAtCompany + OverTime + YearsSinceLastPromotion,
## data = tabela_knn_num)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.4527 -0.1855 -0.1038 -0.0059 1.2483
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.39496243 0.04471464 8.83 < 0.0000000000000002
## Age -0.00483343 0.00112527 -4.30 0.0000186
## MonthlyIncome -0.00000500 0.00000238 -2.10 0.03602
## DistanceFromHome 0.00382779 0.00107834 3.55 0.00040
## JobSatisfaction -0.03568205 0.00792597 -4.50 0.0000073
## YearsAtCompany -0.00669901 0.00198798 -3.37 0.00077
## OverTime 0.18509245 0.01941256 9.53 < 0.0000000000000002
## YearsSinceLastPromotion 0.00944278 0.00345419 2.73 0.00634
##
## (Intercept) ***
## Age ***
## MonthlyIncome *
## DistanceFromHome ***
## JobSatisfaction ***
## YearsAtCompany ***
## OverTime ***
## YearsSinceLastPromotion **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.335 on 1462 degrees of freedom
## Multiple R-squared: 0.117, Adjusted R-squared: 0.113
## F-statistic: 27.7 on 7 and 1462 DF, p-value: <0.0000000000000002
Współczynnik Giniego
Współczynnik Giniego mierzy nierówność rozkładu danej zmiennej – w tym przypadku wieku. Wiek w tej populacji jest stosunkowo równomiernie rozłożony, z niewielkimi różnicami między wartościami.
gini_coefficient <- Gini(tabela_knn$Age)
gini_coefficient
## [1] 0.136945
Krzywa Lorenza
Krzywa Lorenza przedstawia nierówność rozkładu danej zmiennej – w tym przypadku wieku. Czarna linia diagonalna – reprezentuje idealną równość (każdy ma taki sam wiek). Niebieska krzywa – pokazuje rzeczywisty rozkład wieku. Im bardziej oddala się od linii równości, tym większa nierówność. Krzywa Lorenza znajduje się blisko linii równości, co oznacza, że wiek jest stosunkowo równomiernie rozłożony.
plot(Lc(tabela_knn$Age), col = "blue", lwd = 2, main = "Krzywa Lorenza dla wieku")
Różnice wieku między osobami, które odeszły i zostały
Pracownicy, którzy pozostali w firmie mają średni wiek 37,5 roku, podczas gdy Ci, którzy odeszli, średnio 33,33 roku. Test t (Welcha) wykazał istotną statystycznie różnicę (t = 6.13, p < 0.001), co wskazuje, że młodsi pracownicy częściej odchodzą z pracy. Rozkłady danych pokazują większą gęstość młodszych osób w grupie „Yes” oraz starszych w grupie „No”.
ggstatsplot::ggbetweenstats(data = tabela_knn, x = Attrition, y = Age,
title = "Porównanie wieku między osobami, które odeszły i zostały", xlab
= "Attrition (Czy pracownik odszedł?)", ylab = "Wiek", messages = FALSE)
Porównanie miesięcznych dochodów między osobami, które odeszły i zostały
Pracownicy, którzy pozostali w firmie, mają średni miesięczny dochód μ = 6766.73, natomiast ci, którzy odeszli, μ = 4725.49. Test t (Welcha) wskazuje istotną różnicę (t = 7.23, p < 0.001), co sugeruje, że osoby o niższych dochodach częściej odchodzą. Rozkłady pokazują większą gęstość wyższych dochodów w grupie „No” oraz niższych w grupie „Yes”.
ggstatsplot::ggbetweenstats(data = tabela_knn, x = Attrition, y =
MonthlyIncome, title = "Porównanie miesięcznych dochodów między osobami,
które odeszły i zostały", xlab = "Attrition (Czy pracownik odszedł?)",
ylab = "Miesięczny dochód", messages = FALSE )
Podsumowanie
Przeprowadzone analizy wskazują, że osoby o niższych dochodach oraz młodsi pracownicy częściej decydują się na odejście. Dodatkowo, zmienne takie jak odległość od miejsca pracy czy konieczność pracy w nadgodzinach również wpływają na rotację pracowników. Wyniki te mogą być cenną wskazówką dla pracodawców w kontekście strategii rotacji i polityki wynagrodzeń.
Projekt koncentrował się na analizie odejść pracowników (Attrition) w kontekście kluczowych zmiennych, takich jak wiek i miesięczne dochody. Wykazano, że młodsi pracownicy oraz osoby o niższych zarobkach częściej opuszczają firmę, co potwierdziły istotne statystycznie testy t (Welcha). Rozkłady danych pokazały różnice w strukturze grup „zostałych” i „odeszłych”, podkreślając istotne wzorce w zatrzymywaniu pracowników. Średni wiek osób, które pozostały, wynosił 37,5 roku, podczas gdy tych, którzy odeszli, 33,33 roku, a średnie miesięczne dochody w tych grupach wynosiły odpowiednio 6766,73 i 4725,49. Analiza dostarczyła cennych informacji dla działu HR, wskazując na konieczność zwiększenia wsparcia dla młodszych pracowników i tych z niższymi dochodami. Wyniki te mogą pomóc w opracowaniu strategii rotacji, minimalizując przyszłe odejścia z pracy.