Load package

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.1
## Warning: package 'readr' was built under R version 4.5.1
## Warning: package 'forcats' was built under R version 4.5.1
## Warning: package 'lubridate' was built under R version 4.5.1
library(caret)
## Warning: package 'caret' was built under R version 4.5.2
library(broom)
library(pROC)
## Warning: package 'pROC' was built under R version 4.5.2
library(ResourceSelection)
## Warning: package 'ResourceSelection' was built under R version 4.5.2

1. Load data CPNS 2024

cpns <- read.csv("D:/STATISTIKA 23/KULIAH/MK SEMESTER 5/ANALISIS DATA KATEGORIK/DataFormasiCPNS2024.csv")
glimpse(cpns)
## Rows: 653,621
## Columns: 14
## $ formation_id       <chr> "8a01869291548667019154b712642868", "8a018692915486…
## $ agency             <chr> "Badan Kependudukan dan Keluarga Berencana Nasional…
## $ admission_path     <chr> "CPNS", "CPNS", "CPNS", "CPNS", "CPNS", "CPNS", "CP…
## $ fomation_category  <chr> "UMUM", "UMUM", "UMUM", "UMUM", "UMUM", "UMUM", "UM…
## $ position           <chr> "PENYULUH KELUARGA BERENCANA AHLI PERTAMA", "PENYUL…
## $ location           <chr> "Perwakilan BKKBN Provinsi Jawa Timur", "Perwakilan…
## $ num_of_formation   <int> 13, 2, 16, 7, 1, 9, 7, 4, 1, 3, 21, 4, 2, 4, 19, 13…
## $ allow_disability   <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ minimum_salary_idr <int> 2785700, 2785700, 2785700, 2785700, 2785700, 278570…
## $ maximum_salary_idr <int> 9024448, 9024448, 9024448, 9024448, 9024448, 902444…
## $ education_code     <int> 5106191, 5106191, 5106191, 5106191, 5106191, 510619…
## $ education_major    <chr> "S-1 ILMU GIZI MASYARAKAT", "S-1 ILMU GIZI MASYARAK…
## $ education_level_id <int> 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,…
## $ education_level    <chr> "S-1/Sarjana", "S-1/Sarjana", "S-1/Sarjana", "S-1/S…
# Ubah allow_disability jadi faktor biner: 0 = Tidak, 1 = Ya
cpns$allow_disability <- factor(
  cpns$allow_disability,
  levels = c(0, 1),
  labels = c("Tidak", "Ya")
)

Data yang digunakan merupakan data formasi CPNS 2024 dengan jumlah observasi yang sangat besar (lebih dari 600 ribu baris). Variabel allow_disability menunjukkan apakah suatu formasi membuka kesempatan bagi pelamar penyandang disabilitas. Pada tahap ini, variabel tersebut diubah menjadi faktor biner dengan dua kategori: “Tidak” dan “Ya”, sehingga dapat digunakan sebagai variabel respons dalam model regresi logistik biner.

2. Pilih variabel yang digunakan dalam model

data_final <- cpns %>%
  select(
    allow_disability,     # Y
    fomation_category,    # X1 (kategori formasi)
    num_of_formation,     # X2 (jumlah formasi)
    minimum_salary_idr,   # X3 (gaji minimum)
    education_level       # X4 (tingkat pendidikan)
  ) %>%
  drop_na()

Pada tahap ini dipilih variabel-variabel yang relevan dengan tujuan analisis. Variabel respons adalah allow_disability, sedangkan variabel prediktor yang digunakan meliputi:

Fungsi drop_na() digunakan untuk menghilangkan baris dengan data yang hilang pada variabel-variabel tersebut, sehingga model dibangun berdasarkan data yang lengkap.

3. Split data: 80% train, 20% test

set.seed(123)
idx_train <- createDataPartition(
  data_final$allow_disability,
  p = 0.8,
  list = FALSE
)

train <- data_final[idx_train, ]
test  <- data_final[-idx_train, ]

# Cek proporsi kelas 
prop.table(table(train$allow_disability))
## 
##     Tidak        Ya 
## 0.3026848 0.6973152
prop.table(table(test$allow_disability))
## 
##     Tidak        Ya 
## 0.3026835 0.6973165

Interpretasi

Data dibagi menjadi dua bagian, yaitu data latih (80%) dan data uji (20%) dengan mempertahankan proporsi kelas menggunakan fungsi createDataPartition. Hasilnya menunjukkan bahwa sekitar 70% formasi termasuk kategori “Ya” (menerima pelamar disabilitas) dan 30% kategori “Tidak”. Artinya, data cenderung tidak seimbang karena mayoritas formasi memang membuka kesempatan bagi penyandang disabilitas. Kondisi ini berpotensi memengaruhi performa model, terutama dalam mengenali kelas minoritas.

4. Model Regresi Logistik Biner

model_logit <- glm(
  allow_disability ~ 
    fomation_category +
    education_level +
    num_of_formation * minimum_salary_idr,
  data = train,
  family = binomial
)
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
summary(model_logit)
## 
## Call:
## glm(formula = allow_disability ~ fomation_category + education_level + 
##     num_of_formation * minimum_salary_idr, family = binomial, 
##     data = train)
## 
## Coefficients:
##                                                      Estimate Std. Error
## (Intercept)                                         3.330e+00  6.510e-01
## fomation_categoryLULUSAN TERBAIK                   -2.439e+00  5.076e-01
## fomation_categoryORANG ASLI PAPUA (OAP)            -4.078e+00  5.071e-01
## fomation_categoryPENYANDANG DISABILITAS             1.333e+01  1.598e+01
## fomation_categoryPUTRA/PUTRI DAERAH TERTINGGAL     -7.558e-01  5.214e-01
## fomation_categoryPUTRA/PUTRI KALIMANTAN            -2.403e+00  5.075e-01
## fomation_categoryPUTRA/PUTRI PAPUA DAN PAPUA BARAT -2.578e+00  5.080e-01
## fomation_categoryUMUM                              -2.227e+00  5.070e-01
## fomation_categoryUMUM (NON OAP)                    -4.220e+00  5.073e-01
## education_levelDiploma III/Sarjana Muda            -3.301e-01  4.083e-01
## education_levelDiploma IV                          -7.040e-02  4.083e-01
## education_levelS-1/Sarjana                         -6.510e-02  4.083e-01
## education_levelS-2                                  2.138e-01  4.085e-01
## education_levelS-3/Doktor                           1.489e+00  4.136e-01
## education_levelSLTA                                -1.028e+00  4.106e-01
## education_levelSLTA Keguruan                        1.034e+00  6.656e-01
## education_levelSLTP                                 6.392e-01  1.155e+00
## education_levelSMK/SLTA Kejuruan                   -1.002e+00  4.103e-01
## num_of_formation                                    1.970e-02  1.059e-03
## minimum_salary_idr                                 -1.003e-08  1.509e-09
## num_of_formation:minimum_salary_idr                -2.258e-09  1.487e-10
##                                                    z value Pr(>|z|)    
## (Intercept)                                          5.116 3.12e-07 ***
## fomation_categoryLULUSAN TERBAIK                    -4.805 1.55e-06 ***
## fomation_categoryORANG ASLI PAPUA (OAP)             -8.042 8.82e-16 ***
## fomation_categoryPENYANDANG DISABILITAS              0.834 0.404286    
## fomation_categoryPUTRA/PUTRI DAERAH TERTINGGAL      -1.450 0.147140    
## fomation_categoryPUTRA/PUTRI KALIMANTAN             -4.735 2.19e-06 ***
## fomation_categoryPUTRA/PUTRI PAPUA DAN PAPUA BARAT  -5.075 3.87e-07 ***
## fomation_categoryUMUM                               -4.392 1.12e-05 ***
## fomation_categoryUMUM (NON OAP)                     -8.319  < 2e-16 ***
## education_levelDiploma III/Sarjana Muda             -0.809 0.418796    
## education_levelDiploma IV                           -0.172 0.863113    
## education_levelS-1/Sarjana                          -0.159 0.873326    
## education_levelS-2                                   0.523 0.600730    
## education_levelS-3/Doktor                            3.602 0.000316 ***
## education_levelSLTA                                 -2.504 0.012273 *  
## education_levelSLTA Keguruan                         1.553 0.120415    
## education_levelSLTP                                  0.553 0.579946    
## education_levelSMK/SLTA Kejuruan                    -2.442 0.014588 *  
## num_of_formation                                    18.614  < 2e-16 ***
## minimum_salary_idr                                  -6.649 2.96e-11 ***
## num_of_formation:minimum_salary_idr                -15.188  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 641199  on 522896  degrees of freedom
## Residual deviance: 583633  on 522876  degrees of freedom
## AIC: 583675
## 
## Number of Fisher Scoring iterations: 15

Interpretasi

Model regresi logistik biner dibangun untuk memodelkan peluang suatu formasi menerima pelamar disabilitas berdasarkan kategori formasi, tingkat pendidikan, jumlah formasi, gaji minimum, serta interaksi antara jumlah formasi dan gaji minimum.

Hasil ringkasan model menunjukkan bahwa sebagian besar kategori formasi memiliki koefisien negatif dan signifikan, seperti LULUSAN TERBAIK, ORANG ASLI PAPUA (OAP), PUTRA/PUTRI KALIMANTAN, dan kategori UMUM. Koefisien negatif ini mengindikasikan bahwa formasi dengan kategori tersebut cenderung memiliki peluang lebih rendah untuk membuka kesempatan bagi penyandang disabilitas dibandingkan kategori referensi. Temuan ini menggambarkan bahwa banyak skema formasi CPNS dirancang untuk sasaran tertentu, sehingga tidak diarahkan secara khusus bagi pelamar disabilitas.

Sebaliknya, kategori PENYANDANG DISABILITAS memiliki koefisien positif tetapi tidak signifikan. Hal ini disebabkan jumlah observasi untuk kategori ini sangat sedikit, sehingga estimasi model menjadi tidak stabil dan kesimpulan statistiknya lemah.

Dari sisi tingkat pendidikan, formasi dengan persyaratan pendidikan sangat tinggi, khususnya S-3, menunjukkan koefisien positif yang signifikan. Ini mengindikasikan bahwa formasi dengan kualifikasi akademik tinggi cenderung lebih terbuka terhadap pelamar disabilitas, yang bisa jadi terkait dengan karakteristik pekerjaan yang lebih bersifat administratif atau analitis. Sebaliknya, formasi yang mensyaratkan pendidikan SLTA atau SMK memiliki koefisien negatif dan signifikan, sehingga peluang membuka akses bagi penyandang disabilitas relatif lebih rendah.

Variabel num_of_formation memiliki koefisien positif dan signifikan, sedangkan minimum_salary_idr dan interaksi num_of_formation:minimum_salary_idr memiliki koefisien negatif dan signifikan. Artinya, jumlah formasi yang lebih besar secara umum meningkatkan peluang inklusi, tetapi efek positif ini berkurang ketika gaji minimum yang ditawarkan semakin tinggi. Dengan kata lain, formasi dengan jumlah lowongan yang banyak cenderung lebih inklusif, namun jika gajinya tinggi, seleksi menjadi lebih ketat sehingga peluang bagi penyandang disabilitas menurun.

5. Odds Ratio (OR) + Confidence Interval

or_table <- tidy(model_logit) %>%
  mutate(
    OR       = exp(estimate),
    CI_lower = exp(estimate - 1.96 * std.error),
    CI_upper = exp(estimate + 1.96 * std.error)
  )

or_table   
## # A tibble: 21 × 8
##    term          estimate std.error statistic  p.value      OR CI_lower CI_upper
##    <chr>            <dbl>     <dbl>     <dbl>    <dbl>   <dbl>    <dbl>    <dbl>
##  1 (Intercept)      3.33      0.651     5.12  3.12e- 7 2.79e+1  7.80e+0 1.00e+ 2
##  2 fomation_cat…   -2.44      0.508    -4.80  1.55e- 6 8.73e-2  3.23e-2 2.36e- 1
##  3 fomation_cat…   -4.08      0.507    -8.04  8.82e-16 1.69e-2  6.27e-3 4.58e- 2
##  4 fomation_cat…   13.3      16.0       0.834 4.04e- 1 6.15e+5  1.53e-8 2.47e+19
##  5 fomation_cat…   -0.756     0.521    -1.45  1.47e- 1 4.70e-1  1.69e-1 1.30e+ 0
##  6 fomation_cat…   -2.40      0.508    -4.74  2.19e- 6 9.04e-2  3.34e-2 2.45e- 1
##  7 fomation_cat…   -2.58      0.508    -5.08  3.87e- 7 7.59e-2  2.80e-2 2.05e- 1
##  8 fomation_cat…   -2.23      0.507    -4.39  1.12e- 5 1.08e-1  3.99e-2 2.91e- 1
##  9 fomation_cat…   -4.22      0.507    -8.32  8.87e-17 1.47e-2  5.44e-3 3.97e- 2
## 10 education_le…   -0.330     0.408    -0.809 4.19e- 1 7.19e-1  3.23e-1 1.60e+ 0
## # ℹ 11 more rows
View(data.frame(or_table))

Interpretasi

Tabel odds ratio (OR) membantu menginterpretasikan besarnya pengaruh setiap variabel. Nilai OR yang lebih kecil dari 1 menunjukkan penurunan peluang (odds) suatu formasi menerima pelamar disabilitas dibanding kategori referensi, sedangkan OR lebih besar dari 1 menunjukkan peningkatan peluang.

Sebagian besar kategori formasi memiliki OR < 1, yang menegaskan bahwa formasi dengan kategori tersebut cenderung lebih kecil peluangnya untuk bersifat inklusif. Misalnya, kategori tertentu hanya memiliki sebagian kecil peluang dibanding kategori referensi. Di sisi lain, kategori pendidikan S-3 memiliki OR > 1 dan signifikan, yang berarti peluang formasi dengan persyaratan S-3 untuk membuka kesempatan bagi penyandang disabilitas beberapa kali lebih besar dibanding kategori pendidikan referensi.

Untuk variabel jumlah formasi dan gaji minimum, OR menunjukkan pola yang konsisten dengan koefisien model: penambahan jumlah formasi cenderung meningkatkan peluang inklusi, tetapi jika terjadi bersama gaji minimum yang tinggi, interaksi keduanya justru mengurangi peluang tersebut.

6. Uji Goodness of Fit (Hosmer–Lemeshow)

prob_train <- predict(model_logit, type = "response")
y_train_num <- ifelse(train$allow_disability == "Ya", 1, 0)

hl <- hoslem.test(y_train_num, prob_train, g = 10)
hl   
## 
##  Hosmer and Lemeshow goodness of fit (GOF) test
## 
## data:  y_train_num, prob_train
## X-squared = 13324, df = 8, p-value < 2.2e-16

Interpretasi

Uji Hosmer–Lemeshow digunakan untuk menilai kesesuaian (goodness of fit) model terhadap data. Hasil uji menunjukkan nilai statistik chi-square yang sangat besar dengan p-value yang sangat kecil (p-value < 0,05). Hal ini secara formal mengindikasikan bahwa model tidak sepenuhnya sesuai dengan distribusi aktual data.

Namun, mengingat jumlah observasi yang sangat besar, perbedaan kecil antara nilai yang diprediksi model dan data aktual pun dapat menjadi signifikan secara statistik. Dengan demikian, hasil uji ini lebih menunjukkan bahwa model belum sempurna dalam mengkalibrasi probabilitas, tetapi masih tetap dapat digunakan untuk memahami pola umum dan faktor-faktor yang berperan penting.

7. Evaluasi Model di Data Test:

Confusion Matrix

prob_test <- predict(model_logit, newdata = test, type = "response")

pred_class <- ifelse(prob_test >= 0.5, "Ya", "Tidak") %>%
  factor(levels = c("Tidak", "Ya"))

cm <- confusionMatrix(
  data = pred_class,
  reference = test$allow_disability,
  positive = "Ya"
)
cm   
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction Tidak    Ya
##      Tidak  8772  3372
##      Ya    30796 87784
##                                          
##                Accuracy : 0.7386         
##                  95% CI : (0.7362, 0.741)
##     No Information Rate : 0.6973         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.2298         
##                                          
##  Mcnemar's Test P-Value : < 2.2e-16      
##                                          
##             Sensitivity : 0.9630         
##             Specificity : 0.2217         
##          Pos Pred Value : 0.7403         
##          Neg Pred Value : 0.7223         
##              Prevalence : 0.6973         
##          Detection Rate : 0.6715         
##    Detection Prevalence : 0.9071         
##       Balanced Accuracy : 0.5924         
##                                          
##        'Positive' Class : Ya             
## 

Interpretasi

Berdasarkan confusion matrix, model memiliki akurasi sebesar 73,86%. Sekilas, nilai akurasi ini tampak cukup baik. Namun, ketika dilihat lebih rinci, model memiliki sensitivity yang sangat tinggi (96,30%) dan specificity yang rendah (22,17%).

Nilai sensitivity yang tinggi menunjukkan bahwa model sangat baik dalam mengenali formasi yang memang membuka kesempatan bagi penyandang disabilitas (kelas “Ya”). Sebaliknya, specificity yang rendah menunjukkan bahwa model kurang mampu mengidentifikasi formasi yang tidak membuka kesempatan bagi penyandang disabilitas (kelas “Tidak”). Hal ini dapat dijelaskan oleh ketidakseimbangan kelas dalam data, di mana sebagian besar formasi memang termasuk kategori “Ya”, sehingga model cenderung “mengikuti” pola mayoritas.

Dengan kata lain, model cenderung lebih sering memprediksi “Ya”, sehingga jarang salah untuk kelas mayoritas, tetapi cukup sering salah ketika formasi sebenarnya termasuk kategori “Tidak”.

ROC Curve & AUC

roc_obj <- roc(
  response = test$allow_disability,
  predictor = prob_test,
  levels = c("Tidak", "Ya"),
  direction = "<"
)

auc(roc_obj)  
## Area under the curve: 0.6602
plot(roc_obj, main = "ROC Curve Model Regresi Logistik Formasi CPNS 2024")

Interpretasi

Nilai Area Under the Curve (AUC) sebesar 0,660 menunjukkan bahwa kemampuan model dalam membedakan antara formasi yang membuka dan yang tidak membuka kesempatan bagi penyandang disabilitas berada pada tingkat sedang. Nilai ini mengindikasikan bahwa model masih mampu memberikan informasi diskriminatif, meskipun belum dapat dikatakan sangat kuat.

Kurva ROC yang dihasilkan juga menggambarkan trade-off antara sensitivitas dan 1–specificity pada berbagai titik cut-off. Dalam praktik, pemilihan cut-off selain 0,5 dapat dipertimbangkan jika fokus kebijakan lebih menekankan pada peningkatan sensitivitas atau specificity, tergantung tujuan analisis.