Sebagai seseorang bekerja dibidang HR, Anda tidak hanya harus bertanggung jawab atas rekutmen karyawan, tetapi ketika merkeka memustuskan untuk Resign. Masalahnya, tidak seperti rekrutmen karyawan yang bisa disiapkan dari jauh-jauh hari, karyawan yang resign tidak pernah membuat anda kaget. hal tersebut selalu datang tanpa warning meskipun karyawan yang bersangkutan memiliki waktu minimal dua minggu hingga ia akhirnya benar-benar Resign.
Untuk itu anda perlu mempersiapkan diri dari sekarang agar tidak binggung ketika ada seorang karyawan yang mengajukan Resign. jadi pada kesempatan ini kali ini, saya akan melakukan analysis untuk memprediksi karyawan yang akan memutuskan Resign.
Sumber Data
Sumber data yang digunakan dalam laporan ini adalah data pegawai terminasi di perusahaan KIFEST. Dapat diakses melalui : http://bit.ly/KIFEST_HR.
Pengambilan sumber data dari google spreedsheet
Pada data tersebut, memiliki 654 baris dan 21 variabel
glimpse(kifest_df)
Rows: 654
Columns: 21
$ id <dbl> 10001537, 10001541, 10001807, 10001812, 10001272, 10001316, 10001190, 10001297, 10001273, 10001275, 10001~
$ gender <chr> "Male", "Female", "Male", "Male", "Male", "Male", "Male", "Female", "Male", "Male", "Male", "Male", "Male~
$ employee_type <chr> "Contract", "Contract", "Contract", "Contract", "Contract", "Contract", "Contract", "Contract", "Contract~
$ level_of_position <chr> "PELAKSANA", "PELAKSANA", "PELAKSANA", "PELAKSANA", "PELAKSANA", "PELAKSANA", "PELAKSANA", "PELAKSANA", "~
$ band <chr> "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5", "BOD-5~
$ org_unit <chr> "UNIT PLANT SEMARANG", "UNIT PLANT SEMARANG", "UNIT PENGADAAN", "UNIT PLANT JAKARTA", "UNIT PLANT JAKARTA~
$ org_division <chr> "SBU MANUFAKTUR", "SBU MANUFAKTUR", "DIVISI SUPPLY CHAIN", "SBU MANUFAKTUR", "SBU MANUFAKTUR", "SBU MANUF~
$ funct_bus <chr> "MANUFACTURE", "MANUFACTURE", "SUPPORT", "MANUFACTURE", "MANUFACTURE", "MANUFACTURE", "MANUFACTURE", "MAN~
$ position <chr> "PELAKSANA PRODUKSI KOSMETIK", "PELAKSANA PRODUKSI KOSMETIK", "ADMINISTRASI PEMBELIAN BAHAN KEMASAN", "PE~
$ location <chr> "Plant Semarang", "Plant Semarang", "Kantor Pusat", "Plant Jakarta", "Plant Jakarta", "Plant Jakarta", "P~
$ age <dbl> 26, 21, 21, 21, 27, 40, 23, 27, 20, 21, 23, 20, 21, 22, 22, 29, 24, 55, 21, 21, 23, 24, 20, 22, 26, 23, 4~
$ long_work <dbl> 2, 2, 1, 1, 2, 4, 3, 4, 2, 2, 2, 2, 2, 2, 3, 5, 2, 27, 3, 1, 2, 0, 1, 3, 3, 3, 2, 3, 36, 2, 3, 3, 3, 3, 3~
$ education_type <chr> "SMA", "SMA", "SMA", "SMA", "SMP", "SMP", "SMP", "S1", "SMA", "SMA", "SMA", "SMP", "SMA", "SMP", "SMA", "~
$ entitas <chr> "PT KIMIA FARMA Tbk", "PT KIMIA FARMA Tbk", "PT KIMIA FARMA Tbk", "PT KIMIA FARMA Tbk", "PT KIMIA FARMA T~
$ salary <dbl> 2125000, 2125000, 3457000, 3649000, 3457000, 3607000, 3613000, 4730000, 4289000, 4289000, 4177000, 345700~
$ attrition <chr> "TERMINATION", "TERMINATION", "TERMINATION", "TERMINATION", "TERMINATION", "TERMINATION", "TERMINATION", ~
$ resign_type <chr> "Contract_Ends", "Contract_Ends", "Contract_Ends", "Contract_Ends", "Contract_Ends", "Contract_Ends", "Co~
$ marital_status <chr> "Single", "Single", "Single", "Single", "Single", "Single", "Single", "Single", "Single", "Single", "Sing~
$ dependent <dbl> 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 2, 2, 2, ~
$ grade <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
$ termination_date <chr> "1/2/2018", "1/2/2018", "1/2/2018", "1/2/2018", "1/3/2018", "1/3/2018", "1/3/2018", "1/3/2018", "1/3/2018~
Dan ringkasan masing-masing variabel sebagai berikut :
summary(kifest_df)
id gender employee_type level_of_position band org_unit
Min. :10000012 Length:654 Length:654 Length:654 Length:654 Length:654
1st Qu.:10000931 Class :character Class :character Class :character Class :character Class :character
Median :10001723 Mode :character Mode :character Mode :character Mode :character Mode :character
Mean :10093226
3rd Qu.:10001996
Max. :30000063
org_division funct_bus position location age long_work education_type
Length:654 Length:654 Length:654 Length:654 Min. :20.00 Min. : 0.00 Length:654
Class :character Class :character Class :character Class :character 1st Qu.:23.00 1st Qu.: 2.00 Class :character
Mode :character Mode :character Mode :character Mode :character Median :26.00 Median : 2.00 Mode :character
Mean :34.95 Mean :11.47
3rd Qu.:55.00 3rd Qu.:27.00
Max. :62.00 Max. :40.00
entitas salary attrition resign_type marital_status dependent grade
Length:654 Min. : 2125000 Length:654 Length:654 Length:654 Min. :0.0000 Min. : 0.000
Class :character 1st Qu.: 3803000 Class :character Class :character Class :character 1st Qu.:0.0000 1st Qu.: 0.000
Mode :character Median : 4383000 Mode :character Mode :character Mode :character Median :0.0000 Median : 0.000
Mean : 5557305 Mean :0.6269 Mean : 2.096
3rd Qu.: 5632000 3rd Qu.:1.0000 3rd Qu.: 4.000
Max. :50000000 Max. :4.0000 Max. :16.000
termination_date
Length:654
Class :character
Mode :character
Analysis Univariat adalah suatu teknik analysis data terhadap satu variabel secara mandiri, tiap variabel dianalysis tanpa dikaitkan dengan variabel lainya.
Pada kasus ini saya menggunakan Analysis Univariat menggunakan visualisaisiggplot2 dengan menjabarkan 4 varaibel ke dalam diagram batang
Berdasarkan diagaram tersebut, bahwa :
Jenis Teriminasi Terdapat 6 jenis teriminasi, urutan terbanyak Contrac_End, Normal_End, Resign, Died, Fraud dan terkahir Demotion
Tanggungan Keluarga Pegawai yang tidak mempunyai tanggunan keluarga paling banyak teriminasi yaitu 0 maskudnya tidak memiliki tanggunan, disusul tanggungan 1,2,3,dan 4.
Jenis Kelamin Pegawai laki-laki lebih banyak teriminasi di badingkan karyawan perempuan.
Level Jabatan Pegawai dengan level jabatan pelaksana paling banyak teriminasi di badingkan dengan level jabatan yang lain.
Analysis Bivariat adalah dilakukan mengatahui ada tidaknya hubungan kedua variabel
Analysis Bivariat menggunakan ggplot dengan membandingkan varaibel target resign_type dengan variabel salary ke dalam bentuk boxplot
Dari boxplot diatas, dapat disimpulkan bahwa pegawai teriminasi dengan alasan habis kontrak contrac_end paling banyak, dengan rentang gajih antata 3k-40K, disusl dengan Normal_Retirement, Resign, Died, dan Demotion.
Dari analysis ini univariat dan bivariat diatas, saya keructkan target teriminasi menjadi 2 kategori yaitu :
Resign berisi variabel Resign
Termination berisi variabel contrac_end, Normal_Retirement, Resign, Died, dan Demotion. Pengerecutan ini dilakukan karena variabel Resign adalah jenis teriminasi yang diusulkan pegawai atau atas permintaan pegawai senderi.
Analysis bivariat dengan 2 variabel target sebagai berikut :
Analysis Multivariat adalah membandingkan dua variabel atau melihat pengaruh varibel lainya
Analysis multivariat saya membandingkan variabel target dengan 4 variabel lain (Gaji “salary”, Umur “age”, Lama Kerja “long_work” dan Jumlah tanggungan dependen.
Berdasarkan data diatas, hubungan antara lama kerja dan umur sangar berkaitan erat, disusul hubungan antara umur dan lama kerja di bandung dengan jumlah tanggungan keluarga, dengan detail hubungan variabel tersebut sebagai berikut:
cor(kifest_df[,c("salary", "age", "long_work",
"dependent")])
salary age long_work dependent
salary 1.0000000 0.4078812 0.2017021 0.2450270
age 0.4078812 1.0000000 0.9196373 0.6540971
long_work 0.2017021 0.9196373 1.0000000 0.5874774
dependent 0.2450270 0.6540971 0.5874774 1.0000000
Detect Missing Value on Data
Dari data tersebut, beberapa data dengan jenis variabel “chr” harus di ubah menjadi jenis variabel “factor” dengan cara sebagai berikut:
kifest_df$resign_type = as.factor(kifest_df$resign_type)
kifest_df$gender = as.factor(kifest_df$gender)
kifest_df$marital_status = as.factor(kifest_df$marital_status)
kifest_df$employee_type = as.factor(kifest_df$employee_type)
kifest_df$level_of_position = as.factor(kifest_df$level_of_position)
kifest_df$attrition = as.factor(kifest_df$attrition)
Get Outliers Values
out_salary <- boxplot.stats(kifest_df$salary)$out
Berdasarkan dari boxplot diatas, terdapat pencilan data gaji pegawai di angka 50K, yang akan kami hilangkan agar hasil prediksi lebih baik (tidak terlalu bias), dengan cara sebagai berikut:
Get Outliers Index
out_idx <- which(kifest_df$salary%in% c(out_salary))
Data with out outliers
Setelah dihilangkan pencilan data, diperoleh data seperti boxplot diatas, dari 654 data observasi menjadi 594 data observasi.
*Sebelum dihilangkan pencilan data**
dim (kifest_df)
[1] 654 21
Setelah dihilang menggunakan pencilan data
dim (kifest_df_clean)
[1] 594 21
Melihat apakah data berisi nilai NA
sum(is.na(TrainingSet))
[1] 0
Ternyata datanya tidak ada nilai NA
Model_2 <- train(attrition ~ age+salary+marital_status+long_work+gender+employee_type+level_of_position,
data = TrainingSet,
method = "svmPoly",
na.action = na.omit,
preProcess=c("scale","center"),
trControl= trainControl(method="none"),
tuneGrid = data.frame(degree=1,scale=1,C=1)
)
Warning in preProcess.default(thresh = 0.95, k = 5, freqCut = 19, uniqueCut = 10, :
These variables have zero variances: level_of_positionGENERAL MANAGER, level_of_positionMANAGER
Warning in .local(x, ...) : Variable(s) `' constant. Cannot scale data.
Evaluation Testing LR
model.matrix_2
Confusion Matrix and Statistics
Reference
Prediction RESIGN TERMINATION
RESIGN 3 5
TERMINATION 13 95
Accuracy : 0.8448
95% CI : (0.7659, 0.9054)
No Information Rate : 0.8621
P-Value [Acc > NIR] : 0.75520
Kappa : 0.1741
Mcnemar's Test P-Value : 0.09896
Sensitivity : 0.18750
Specificity : 0.95000
Pos Pred Value : 0.37500
Neg Pred Value : 0.87963
Prevalence : 0.13793
Detection Rate : 0.02586
Detection Prevalence : 0.06897
Balanced Accuracy : 0.56875
'Positive' Class : RESIGN
table(Model.pred_2)
Model.pred_2
RESIGN TERMINATION
8 108
table(TestingSet$attrition)
RESIGN TERMINATION
16 100
logit.perf_2
Predicted
Actual RESIGN TERMINATION
RESIGN 3 13
TERMINATION 5 95
Evaluation Testing Tree
ctree.perf_2
Predict
Actual RESIGN TERMINATION
RESIGN 9 7
TERMINATION 10 90
fit.forest_2
Call:
randomForest(formula = attrition ~ age + salary + marital_status + long_work + gender, data = TrainingSet, na.action = na.roughfix)
Type of random forest: classification
Number of trees: 500
No. of variables tried at each split: 2
OOB estimate of error rate: 8.79%
Confusion matrix:
RESIGN TERMINATION class.error
RESIGN 38 26 0.40625000
TERMINATION 16 398 0.03864734
Evaluation Testing RF
forest.perf_2
Actual
Predict RESIGN TERMINATION
RESIGN 5 8
TERMINATION 11 92
Model_svm_2
Support Vector Machines with Polynomial Kernel
478 samples
5 predictor
2 classes: 'RESIGN', 'TERMINATION'
Pre-processing: scaled (6), centered (6)
Resampling: None
Evaluation Testing SVM
Model.testing.confusion_2
Confusion Matrix and Statistics
Reference
Prediction RESIGN TERMINATION
RESIGN 0 0
TERMINATION 16 100
Accuracy : 0.8621
95% CI : (0.7857, 0.9191)
No Information Rate : 0.8621
P-Value [Acc > NIR] : 0.5661446
Kappa : 0
Mcnemar's Test P-Value : 0.0001768
Sensitivity : 0.0000
Specificity : 1.0000
Pos Pred Value : NaN
Neg Pred Value : 0.8621
Prevalence : 0.1379
Detection Rate : 0.0000
Detection Prevalence : 0.0000
Balanced Accuracy : 0.5000
'Positive' Class : RESIGN
svm.perf_2
Actual
Predict RESIGN TERMINATION
RESIGN 0 0
TERMINATION 16 100
Performance Comparison
performance <- function(table, n=2){
tn <- table[1,1]
fp <- table[1,2]
fn <- table[2,1]
tp <- table[2,2]
sensitivity = tp/(tp+fn) # recall
specificity = tn/(tn+fp)
ppp = tp/(tp+fp) # precision
npp = tn/(tn+fn)
hitrate = (tp+tn)/(tp+tn+fp+fn) # accuracy
fiscore <- 2 * ppp * sensitivity /(ppp+sensitivity)
result <- paste("Sensitivity = ", round(sensitivity, n) ,
"\nSpecificity = ", round(specificity, n),
"\nPositive Predictive Value = ", round(ppp, n),
"\nNegative Predictive Value = ", round(npp, n),
"\nAccuracy = ", round(hitrate, n),
"\nF1 Score = ",round(fiscore,n))
cat(result)
}
Show Result Logistic Regression
performance(logit.perf_2)
Sensitivity = 0.95
Specificity = 0.19
Positive Predictive Value = 0.88
Negative Predictive Value = 0.38
Accuracy = 0.84
F1 Score = 0.91
Show Result Classification Tree
performance(ctree.perf_2)
Sensitivity = 0.9
Specificity = 0.56
Positive Predictive Value = 0.93
Negative Predictive Value = 0.47
Accuracy = 0.85
F1 Score = 0.91
Show Result Random Forest
performance(forest.perf_2)
Sensitivity = 0.89
Specificity = 0.38
Positive Predictive Value = 0.92
Negative Predictive Value = 0.31
Accuracy = 0.84
F1 Score = 0.91
Show Result Support Vector Machine
performance(svm.perf_2)
Sensitivity = 0.86
Specificity = NaN
Positive Predictive Value = 1
Negative Predictive Value = 0
Accuracy = 0.86
F1 Score = 0.93
1 Variabel-variabel yang penting dalam memprediksi karyawan yang terminasi adalah: Usia, Lama Bekerja, Salary Jenis Kelamin dan Dependent.
2 Performa algoritma yang paling baik adalah Ctree dengan sensitifitas 0,75, spesifikasi 0,93, akurasi 0,91 dengan memprediksi pegawai yang terminasi 10.34% dari populasi.
3 Penilaian dari segi bisnis, algoritma classification regression lebih baik, karena dapat memprediksi 16% dari populasi, walau sensitifitasnya lebih rendah yaitu 0,25 tetapi lebih baik pada nilai spesikasi 1 dan akurasi 0,9. Dapat di simpulkan, jika dari 116 pegawai yang di prediksi terminasi, dapat dipastikan 16 pegawai yang terminasi dengan alasan mengundurkan diri “resign” (spesifik) sedangkan jika menggunakan algoritma Ctree dimana memprediksi 16 orang terminasi tetapi masih terdapat 4 pegawai yang terminasi dengan alasan normal terminasi dan 12 dengan alasan mengundurkan diri “resign”. Dengan demikian: - HR lebih focus mengelola pegawai yang sudah diprediksi resign. - Perusahaan dapat menghemat biaya rekrutment, pelatiahan dan pesangon.
4 Disarankan untuk menambah variable KPI dan Unit Kerja untuk menilai apakah memberikan kontribusi yang significant atau tidak.