Application Score Card for Existing Customer

Library

library(readxl) # read Excel File
library(dplyr) #data cleaning 
library(kableExtra) # Pretty Format
library(scorecard) # Scorecard builder
library(rsample) # split train test

Data Source

Dataset yang digunakan adalah data Taiwan Credit. sumber data: Source

Dataset memiliki 25 kolom dan 30,952 dengan penjelasan sebagai berikut:

  • id = id debitur
  • limit_bal = Besaran kredit limit yang diberikan dalam dolar NT
  • sex = jenis kelamin
    • 1 = laki-laki
    • 2 = perempuan
  • education = Pendidikan terakhir
    • 1 = pascasarjana (S2 & S3)
    • 2 = universitas (S1)
    • 3 = high school (SMA)
    • 4 = lain-lain
  • marriage = Status pernikahan
    • 1 = menikah
    • 2 = lajang
    • 3 = lainnya
  • age = Usia dalam tahun
  • pay_* = Status pembayaran dalam bulan April (1) - September (6).
    • 0 = pembayaran tepat waktu
    • 1 = keterlambatan pembayaran satu bulan
    • 2 = keterlambatan pembayaran dua bulan
    • …
    • 8 = keterlambatan pembayaran delapan bulan atau lebih
  • bill_amt* = Jumlah tagihan pada bulan April (1) - September (6) dalam dolar NT
  • pay_amt* = Jumlah pembayaran/pengeluaran sebelumnya pada bulan April (1) - September(6) dalam dolar NT
  • gb_flag = Flagging pembayaran default (gagal bayar) pada bulan berikutnya
    • 1 = default
    • 0 = not default
datasource <- read_excel("data_input/credit_taiwan.xlsx") %>% 
  select(-id) %>% 
  mutate(sex = as.factor(sex),
         education = as.factor(education),
         marriage = as.factor(marriage))
  

datasource %>% 
  head(2) %>% 
  kbl() %>%
  kable_styling()
limit_bal sex education marriage age pay_1 pay_2 pay_3 pay_4 pay_5 pay_6 bill_amt1 bill_amt2 bill_amt3 bill_amt4 bill_amt5 bill_amt6 pay_amt1 pay_amt2 pay_amt3 pay_amt4 pay_amt5 pay_amt6 gb_flag
20000 2 3 2 39 0 0 2 2 3 2 12241 16020 16457 20906 20289 20407 4000 1000 4750 0 600 0 1
100000 1 3 2 49 0 0 0 0 0 0 1440 0 0 0 0 0 0 0 0 0 0 0 0

Function

# EDA
create_eda_report <- function(data) {
  results <- list()
  
  for (column in colnames(data)) {
    column_name <- column
    column_type <- class(data[[column]])
    unique_count <- length(unique(data[[column]]))
    total <- nrow(data)
    null_count <- sum(is.na(data[[column]]))
    non_null_count <- total - null_count
    null_percentage <- sprintf("%.2f%%", (null_count / total * 100))
    
    if (column_type == "character" || column_type == "factor") {
      value_counts <- table(data[[column]])
      most_frequent <- names(sort(value_counts, decreasing = TRUE))[1]
      mode_percentage <- sprintf("%.2f%%", (sort(value_counts, decreasing = TRUE)[1] / total * 100))
      mean_or_top1 <- ""
      min_or_bottom <- names(sort(value_counts))[1]
      if (length(value_counts) >= 2) {
        min_or_bottom <- paste0(min_or_bottom, ": ", sprintf("%.2f%%", (sort(value_counts)[1] / total * 100)))
      }
      max_or_top1 <- names(sort(value_counts, decreasing = TRUE))[1]
      if (length(value_counts) >= 2) {
        max_or_top1 <- paste0(max_or_top1, ": ", sprintf("%.2f%%", (sort(value_counts, decreasing = TRUE)[1] / total * 100)))
      }
    } else {
      most_frequent <- names(sort(table(data[[column]]), decreasing = TRUE))[1]
      mode_percentage <- sprintf("%.2f%%", (sort(table(data[[column]]), decreasing = TRUE)[1] / total * 100))
      mean_or_top1 <- sprintf("%.3f", mean(data[[column]], na.rm = TRUE))
      min_or_bottom <- min(data[[column]], na.rm = TRUE)
      max_or_top1 <- max(data[[column]], na.rm = TRUE)
    }
    
    results[[length(results) + 1]] <- data.frame(
      column_name = column_name,
      type = column_type,
      unique_count = unique_count,
      total = total,
      null_count = null_count,
      non_null_count = non_null_count,
      null_percentage = null_percentage,
      most_frequent = most_frequent,
      mode_percentage = mode_percentage,
      mean = mean_or_top1,
      min_or_bottom = min_or_bottom,
      max_or_top1 = max_or_top1,
      stringsAsFactors = FALSE
    )
  }
  
  column_info <- do.call(rbind, results)
  
  return(column_info)
}

#Punctual & Overdue
count_consecutive_od <- function(row) {
  count <- 0
  max_count <- 0
  
  for (value in row) {
    if (value > 0) {
      count <- count + 1
      max_count <- max(max_count, count)
    } else {
      count <- 0
    }
  }
  
  return(max_count)
}

count_consecutive_punct <- function(row) {
  count <- 0
  max_count <- 0
  
  for (value in row) {
    if (value <= 0) {
      count <- count + 1
      max_count <- max(max_count, count)
    } else {
      count <- 0
    }
  }
  
  return(max_count)
}

# Approval Rate
approval_rate <- function(score, label, positive = 0){

  score_list <- list(data = score)
  label_list <- list(data = label)

  g <- gains_table(score = score_list, label = label_list, positive = positive)
  
  final_df <- g %>% 
    mutate(
      count_approved = max(cum_count) - cum_count,
      neg_approved = max(cum_neg) - cum_neg,
      neg_rate = round((neg_approved / count_approved), 4)
    ) %>% 
    replace(is.na(.), 0) %>% 
    select(bin, approval_rate, neg_rate, 
           count_approved, neg_approved,
           count, neg, pos)
  
  final_df
}

Derivative

Kali ini saya akan menambahkan beberapa variable derivative untuk menambah kombinasi variasi dari setiap parameter. Berikut adalah definisinya:

  • der_sex_education = Penggabungan Jenis kelamin dan pendidikan
  • der_sex_marriage = Penggabungan Jenis kelamin dan Status Perkawinan
  • der_marriage_education = Penggabungan JStatus Perkawinan dan pendidikan
  • der_max_pay = Max Overdue
  • der_max_pay_first_3 = Max Overdue 3 bulan pertama
  • der_max_pay_last_3 = Max Overdue 3 bulan terakhir
  • der_cm_od_first_3 = berapa kali terlambat di 3 bulan pertama
  • der_cm_od_last_3 = berapa kali terlambat di 3 bulan terakhir
  • der_cm_od = berapa kali terlambat
  • der_cm_punct_first_3 = berapa kali tepat waktu di 3 bulan pertama
  • der_cm_punct_last_3 = berapa kali tepat waktu di 3 bulan terakhir
  • der_cm_punct = berapa kali tepat waktu
datasource$der_sex_education <- paste(datasource$sex, datasource$education, sep = "-")
datasource$der_sex_marriage <- paste(datasource$sex, datasource$marriage, sep = "-")
datasource$der_marriage_education <- paste(datasource$marriage, datasource$education, sep = "-")
datasource$der_max_pay <- apply(datasource[, 6:11], 1, max)
datasource$der_max_pay_first_3 <- apply(datasource[, 6:9], 1, max)
datasource$der_max_pay_last_3 <- apply(datasource[, 9:11], 1, max)
datasource$der_cm_od_first_3 <- apply(datasource[, 6:8], 1, count_consecutive_od)
datasource$der_cm_od_last_3 <- apply(datasource[, 9:11], 1, count_consecutive_od)
datasource$der_cm_od <- apply(datasource[, 6:11], 1, count_consecutive_od)
datasource$der_cm_punct_first_3 <- apply(datasource[, 6:9], 1, count_consecutive_punct)
datasource$der_cm_punct_last_3 <- apply(datasource[, 9:11], 1, count_consecutive_punct)
datasource$der_cm_punct <- apply(datasource[, 6:11], 1, count_consecutive_punct)

Minor Data Cleaning

Untuk memastikan variable derifatif yang bersifat kategorik bertipe data factor

datasource <-datasource %>%  
  mutate(der_sex_education = as.factor(der_sex_education),
         der_sex_marriage = as.factor(der_sex_marriage),
         der_marriage_education = as.factor(der_marriage_education))

datasource %>% 
  head(2) %>% 
  kbl() %>%
  kable_styling()
limit_bal sex education marriage age pay_1 pay_2 pay_3 pay_4 pay_5 pay_6 bill_amt1 bill_amt2 bill_amt3 bill_amt4 bill_amt5 bill_amt6 pay_amt1 pay_amt2 pay_amt3 pay_amt4 pay_amt5 pay_amt6 gb_flag der_sex_education der_sex_marriage der_marriage_education der_max_pay der_max_pay_first_3 der_max_pay_last_3 der_cm_od_first_3 der_cm_od_last_3 der_cm_od der_cm_punct_first_3 der_cm_punct_last_3 der_cm_punct
20000 2 3 2 39 0 0 2 2 3 2 12241 16020 16457 20906 20289 20407 4000 1000 4750 0 600 0 1 2-3 2-2 2-3 3 2 3 1 3 4 2 0 2
100000 1 3 2 49 0 0 0 0 0 0 1440 0 0 0 0 0 0 0 0 0 0 0 0 1-3 1-2 2-3 0 0 0 0 0 0 4 3 6

EDA

datasource_eda <- create_eda_report(datasource) %>% 
  kbl() %>%
  kable_styling()

datasource_eda
column_name type unique_count total null_count non_null_count null_percentage most_frequent mode_percentage mean min_or_bottom max_or_top1
limit_bal numeric 79 30952 0 30952 0.00% 50000 13.08% 145680.646 10000 800000
sex factor 2 30952 0 30952 0.00% 2 59.04% 1: 40.96% 2: 59.04%
education factor 4 30952 0 30952 0.00% 2 48.80% 4: 1.17% 2: 48.80%
marriage factor 4 30952 0 30952 0.00% 2 52.96% 0: 0.17% 2: 52.96%
age numeric 55 30952 0 30952 0.00% 29 5.00% 35.321 21 75
pay_1 numeric 9 30952 0 30952 0.00% 0 63.16% 0.562 0 8
pay_2 numeric 9 30952 0 30952 0.00% 0 70.43% 0.637 0 8
pay_3 numeric 9 30952 0 30952 0.00% 0 73.76% 0.568 0 8
pay_4 numeric 9 30952 0 30952 0.00% 0 78.89% 0.469 0 8
pay_5 numeric 8 30952 0 30952 0.00% 0 81.72% 0.412 0 8
pay_6 numeric 8 30952 0 30952 0.00% 0 81.54% 0.410 0 8
bill_amt1 numeric 17193 30952 0 30952 0.00% 0 5.90% 50803.231 0 746814
bill_amt2 numeric 16808 30952 0 30952 0.00% 0 7.04% 49322.664 0 581775
bill_amt3 numeric 16523 30952 0 30952 0.00% 0 8.16% 47315.515 0 578971
bill_amt4 numeric 16166 30952 0 30952 0.00% 0 9.06% 43861.488 0 628699
bill_amt5 numeric 15764 30952 0 30952 0.00% 0 10.11% 40687.128 0 587067
bill_amt6 numeric 15420 30952 0 30952 0.00% 0 12.01% 39096.694 0 527711
pay_amt1 numeric 6433 30952 0 30952 0.00% 0 20.20% 5185.777 0 873552
pay_amt2 numeric 6472 30952 0 30952 0.00% 0 19.60% 5180.542 0 1215471
pay_amt3 numeric 6130 30952 0 30952 0.00% 0 20.98% 4763.255 0 889043
pay_amt4 numeric 5684 30952 0 30952 0.00% 0 22.20% 4360.124 0 621000
pay_amt5 numeric 5629 30952 0 30952 0.00% 0 22.93% 4314.481 0 426529
pay_amt6 numeric 5695 30952 0 30952 0.00% 0 24.81% 4587.026 0 528666
gb_flag numeric 2 30952 0 30952 0.00% 0 53.91% 0.461 0 1
der_sex_education factor 8 30952 0 30952 0.00% 2-2 29.15% 1-4: 0.41% 2-2: 29.15%
der_sex_marriage factor 8 30952 0 30952 0.00% 2-2 30.33% 1-0: 0.04% 2-2: 30.33%
der_marriage_education factor 15 30952 0 30952 0.00% 2-2 24.77% 0-1: 0.01% 2-2: 24.77%
der_max_pay numeric 9 30952 0 30952 0.00% 0 43.95% 1.196 0 8
der_max_pay_first_3 numeric 9 30952 0 30952 0.00% 0 47.97% 1.094 0 8
der_max_pay_last_3 numeric 9 30952 0 30952 0.00% 0 70.20% 0.665 0 8
der_cm_od_first_3 numeric 4 30952 0 30952 0.00% 0 51.47% 0.922 0 3
der_cm_od_last_3 numeric 4 30952 0 30952 0.00% 0 70.20% 0.578 0 3
der_cm_od numeric 7 30952 0 30952 0.00% 0 43.95% 1.432 0 6
der_cm_punct_first_3 numeric 5 30952 0 30952 0.00% 4 47.97% 2.769 0 4
der_cm_punct_last_3 numeric 4 30952 0 30952 0.00% 3 70.20% 2.401 0 3
der_cm_punct numeric 7 30952 0 30952 0.00% 6 43.95% 4.252 0 6

Dari hasil EDA dapat disimpulkan bahwa dari dokumentasi variable terdapat null value yang di ganti dengan nilai 0 di marriage status yang akan diinterpretasikan sebagai debitur yang tidak menginput marriage status. Untuk Variable lain didapati 0% Missing value

Data Splitting

Metode splitting dengan mengambil 70% untuk training data dan 30% untuk validasi / Test data

RNGkind(sample.kind= "Rounding")
set.seed(52)

splitter <- initial_split(data = datasource,
                          prop = 0.7) 

train <- training(splitter)
test <- testing(splitter)

Binning

binning <- woebin(dt = train,
                  y = 'gb_flag',
                  positive = 0)
#> ✔ Binning on 21666 rows and 36 columns in 00:00:14
binning_df <- bind_rows(binning, .id = "variable")

binning_df %>% 
  kbl() %>%
  kable_styling()
variable bin count count_distr neg pos posprob woe bin_iv total_iv breaks is_special_values
limit_bal [-Inf,50000) 4253 0.1962983 3127 1126 0.2647543 -1.1730820 0.2529945 0.6860026 50000 FALSE
limit_bal [50000,150000) 8784 0.4054279 4810 3974 0.4524135 -0.3426033 0.0477409 0.6860026 150000 FALSE
limit_bal [150000,250000) 4622 0.2133296 1332 3290 0.7118131 0.7525266 0.1123550 0.6860026 250000 FALSE
limit_bal [250000, Inf) 4007 0.1849442 744 3263 0.8143249 1.3266819 0.2729122 0.6860026 Inf FALSE
sex 1 8874 0.4095818 4441 4433 0.4995492 -0.1534824 0.0096857 0.0164647 1 FALSE
sex 2 12792 0.5904182 5572 7220 0.5644153 0.1074215 0.0067790 0.0164647 2 FALSE
education 1 6995 0.3228561 2533 4462 0.6378842 0.4145133 0.0538596 0.0786904 1 FALSE
education 2 10586 0.4885996 5394 5192 0.4904591 -0.1898477 0.0176842 0.0786904 2 FALSE
education 3%,%4 4085 0.1885443 2086 1999 0.4893513 -0.1942807 0.0071467 0.0786904 3%,%4 FALSE
marriage 0%,%1 9851 0.4546755 4574 5277 0.5356817 -0.0087098 0.0000345 0.0000633 0%,%1 FALSE
marriage 2%,%3 11815 0.5453245 5439 6376 0.5396530 0.0072663 0.0000288 0.0000633 2%,%3 FALSE
age [-Inf,26) 3202 0.1477892 1856 1346 0.4203623 -0.4729658 0.0330377 0.0498132 26 FALSE
age [26,29) 3047 0.1406351 1404 1643 0.5392189 0.0055191 0.0000043 0.0498132 29 FALSE
age [29,46) 12000 0.5538632 5068 6932 0.5776667 0.1615227 0.0143313 0.0498132 46 FALSE
age [46, Inf) 3417 0.1577125 1685 1732 0.5068774 -0.1241682 0.0024399 0.0498132 Inf FALSE
pay_1 [-Inf,1) 13680 0.6314040 3953 9727 0.7110380 0.7487513 0.3294011 0.9015646 1 FALSE
pay_1 [1,2) 4484 0.2069602 3363 1121 0.2500000 -1.2502917 0.2996511 0.9015646 2 FALSE
pay_1 [2, Inf) 3502 0.1616357 2697 805 0.2298686 -1.3607325 0.2725124 0.9015646 Inf FALSE
pay_2 [-Inf,1) 15288 0.7056217 5037 10251 0.6705259 0.5588852 0.2104994 0.7447301 1 FALSE
pay_2 [1, Inf) 6378 0.2943783 4976 1402 0.2198181 -1.4184060 0.5342307 0.7447301 Inf FALSE
pay_3 [-Inf,2) 15940 0.7357149 5436 10504 0.6589711 0.5070332 0.1817737 0.7316592 2 FALSE
pay_3 [2, Inf) 5726 0.2642851 4577 1149 0.2006636 -1.5338312 0.5498854 0.7316592 Inf FALSE
pay_4 [-Inf,2) 17062 0.7875012 5994 11068 0.6486930 0.4616197 0.1621100 0.8921555 2 FALSE
pay_4 [2, Inf) 4604 0.2124988 4019 585 0.1270634 -2.0788560 0.7300454 0.8921555 Inf FALSE
pay_5 [-Inf,2) 17647 0.8145020 6422 11225 0.6360855 0.4067344 0.1309299 0.8644685 2 FALSE
pay_5 [2, Inf) 4019 0.1854980 3591 428 0.1064942 -2.2787422 0.7335386 0.8644685 Inf FALSE
pay_6 [-Inf,2) 17639 0.8141327 6533 11106 0.6296275 0.3789398 0.1139122 0.7157338 2 FALSE
pay_6 [2, Inf) 4027 0.1858673 3480 547 0.1358331 -2.0020182 0.6018217 0.7157338 Inf FALSE
bill_amt1 [-Inf,5000) 4823 0.2226068 1236 3587 0.7437280 0.9137564 0.1684768 0.2417832 5000 FALSE
bill_amt1 [5000,10000) 1895 0.0874642 763 1132 0.5973615 0.2428038 0.0050847 0.2417832 10000 FALSE
bill_amt1 [10000,170000) 13491 0.6226807 7121 6370 0.4721666 -0.2631281 0.0432938 0.2417832 170000 FALSE
bill_amt1 [170000, Inf) 1457 0.0672482 893 564 0.3870968 -0.6112117 0.0249280 0.2417832 Inf FALSE
bill_amt2 [-Inf,5000) 4986 0.2301302 1222 3764 0.7549138 0.9733140 0.1956026 0.2786240 5000 FALSE
bill_amt2 [5000,10000) 1759 0.0811871 673 1086 0.6173962 0.3268318 0.0084918 0.2786240 10000 FALSE
bill_amt2 [10000, Inf) 14921 0.6886827 8118 6803 0.4559346 -0.3283995 0.0745296 0.2786240 Inf FALSE
bill_amt3 [-Inf,5000) 5097 0.2352534 1223 3874 0.7600549 1.0013013 0.2105790 0.3014430 5000 FALSE
bill_amt3 [5000,10000) 1752 0.0808640 666 1086 0.6198630 0.3372874 0.0089993 0.3014430 10000 FALSE
bill_amt3 [10000, Inf) 14817 0.6838826 8124 6693 0.4517109 -0.3454398 0.0818647 0.3014430 Inf FALSE
bill_amt4 [-Inf,5000) 5239 0.2418074 1276 3963 0.7564421 0.9815917 0.2087352 0.3455206 5000 FALSE
bill_amt4 [5000,15000) 3212 0.1482507 1253 1959 0.6099004 0.2952141 0.0126865 0.3455206 15000 FALSE
bill_amt4 [15000,135000) 11526 0.5319856 6352 5174 0.4488981 -0.3568030 0.0679244 0.3455206 135000 FALSE
bill_amt4 [135000, Inf) 1689 0.0779562 1132 557 0.3297809 -0.8608554 0.0561744 0.3455206 Inf FALSE
bill_amt5 [-Inf,10000) 7444 0.3435798 2036 5408 0.7264911 0.8252128 0.2151749 0.3427841 10000 FALSE
bill_amt5 [10000,130000) 12586 0.5809102 6853 5733 0.4555061 -0.3301270 0.0635276 0.3427841 130000 FALSE
bill_amt5 [130000, Inf) 1636 0.0755100 1124 512 0.3129584 -0.9380038 0.0640815 0.3427841 Inf FALSE
bill_amt6 [-Inf,10000) 7843 0.3619958 2151 5692 0.7257427 0.8214494 0.2247791 0.3650515 10000 FALSE
bill_amt6 [10000,130000) 12318 0.5685406 6814 5504 0.4468258 -0.3651836 0.0760278 0.3650515 130000 FALSE
bill_amt6 [130000, Inf) 1505 0.0694637 1048 457 0.3036545 -0.9816349 0.0642446 0.3650515 Inf FALSE
pay_amt1 [-Inf,500) 5189 0.2394997 2872 2317 0.4465215 -0.3664148 0.0322424 0.0924670 500 FALSE
pay_amt1 [500,4500) 10771 0.4971384 5002 5769 0.5356049 -0.0090185 0.0000404 0.0924670 4500 FALSE
pay_amt1 [4500,16000) 4583 0.2115296 1880 2703 0.5897883 0.2114111 0.0093447 0.0924670 16000 FALSE
pay_amt1 [16000, Inf) 1123 0.0518324 259 864 0.7693678 1.0530653 0.0508395 0.0924670 Inf FALSE
pay_amt2 [-Inf,500) 5237 0.2417151 2723 2514 0.4800458 -0.2315385 0.0130143 0.0965159 500 FALSE
pay_amt2 [500,1500) 3022 0.1394812 1264 1758 0.5817340 0.1782161 0.0043888 0.0965159 1500 FALSE
pay_amt2 [1500,15000) 12226 0.5642943 5802 6424 0.5254376 -0.0498411 0.0014041 0.0965159 15000 FALSE
pay_amt2 [15000, Inf) 1181 0.0545094 224 957 0.8103302 1.3004779 0.0777086 0.0965159 Inf FALSE
pay_amt3 [-Inf,500) 5748 0.2653005 2879 2869 0.4991301 -0.1551589 0.0064117 0.0660322 500 FALSE
pay_amt3 [500,5000) 11345 0.5236315 5470 5875 0.5178493 -0.0802520 0.0033808 0.0660322 5000 FALSE
pay_amt3 [5000,12500) 3185 0.1470045 1313 1872 0.5877551 0.2030134 0.0059921 0.0660322 12500 FALSE
pay_amt3 [12500, Inf) 1388 0.0640635 351 1037 0.7471182 0.9316216 0.0502475 0.0660322 Inf FALSE
pay_amt4 [-Inf,800) 7835 0.3616265 3658 4177 0.5331206 -0.0190027 0.0001307 0.0441811 800 FALSE
pay_amt4 [800,4400) 9247 0.4267977 4568 4679 0.5060019 -0.1276705 0.0069809 0.0441811 4400 FALSE
pay_amt4 [4400,13800) 3420 0.1578510 1471 1949 0.5698830 0.1296946 0.0026385 0.0441811 13800 FALSE
pay_amt4 [13800, Inf) 1164 0.0537247 316 848 0.7285223 0.8354590 0.0344309 0.0441811 Inf FALSE
pay_amt5 [-Inf,1000) 8358 0.3857657 3821 4537 0.5428332 0.0200744 0.0001553 0.0539732 1000 FALSE
pay_amt5 [1000,12200) 12042 0.5558017 5877 6165 0.5119581 -0.1038377 0.0060110 0.0539732 12200 FALSE
pay_amt5 [12200, Inf) 1266 0.0584326 315 951 0.7511848 0.9532620 0.0478068 0.0539732 Inf FALSE
pay_amt6 [-Inf,5000) 17580 0.8114096 8544 9036 0.5139932 -0.0956921 0.0074514 0.0688558 5000 FALSE
pay_amt6 [5000,9800) 2260 0.1043109 992 1268 0.5610619 0.0937936 0.0009137 0.0688558 9800 FALSE
pay_amt6 [9800, Inf) 1826 0.0842795 477 1349 0.7387733 0.8879230 0.0604907 0.0688558 Inf FALSE
der_sex_education 1-1 2935 0.1354657 1171 1764 0.6010221 0.2580465 0.0088844 0.1066117 1-1 FALSE
der_sex_education 1-2%,%1-3 5849 0.2699622 3258 2591 0.4429817 -0.3807490 0.0392289 0.1066117 1-2%,%1-3 FALSE
der_sex_education 1-4%,%2-1 4150 0.1915444 1374 2776 0.6689157 0.5516054 0.0557123 0.1066117 1-4%,%2-1 FALSE
der_sex_education 2-2 6291 0.2903628 3012 3279 0.5212208 -0.0667452 0.0012963 0.1066117 2-2 FALSE
der_sex_education 2-3%,%2-4 2441 0.1126650 1198 1243 0.5092175 -0.1148051 0.0014898 0.1066117 2-3%,%2-4 FALSE
der_sex_marriage 1-0%,%1-1%,%1-2%,%1-3 8874 0.4095818 4441 4433 0.4995492 -0.1534824 0.0096857 0.0172017 1-0%,%1-1%,%1-2%,%1-3 FALSE
der_sex_marriage 2-0%,%2-1 6009 0.2773470 2673 3336 0.5551672 0.0698916 0.0013507 0.0172017 2-0%,%2-1 FALSE
der_sex_marriage 2-2%,%2-3 6783 0.3130712 2899 3884 0.5726080 0.1408203 0.0061653 0.0172017 2-2%,%2-3 FALSE
der_marriage_education 0-1%,%0-2%,%0-3%,%1-1 2418 0.1116034 803 1615 0.6679074 0.5470561 0.0319454 0.0937910 0-1%,%0-2%,%0-3%,%1-1 FALSE
der_marriage_education 1-2 5028 0.2320687 2494 2534 0.5039777 -0.1357682 0.0042932 0.0937910 1-2 FALSE
der_marriage_education 1-3 2288 0.1056032 1262 1026 0.4484266 -0.3587094 0.0136274 0.0937910 1-3 FALSE
der_marriage_education 1-4%,%2-1 4690 0.2164682 1739 2951 0.6292111 0.3771545 0.0300084 0.0937910 1-4%,%2-1 FALSE
der_marriage_education 2-2%,%2-3%,%2-4%,%3-1%,%3-2%,%3-3%,%3-4 7242 0.3342564 3715 3527 0.4870202 -0.2036104 0.0139165 0.0937910 2-2%,%2-3%,%2-4%,%3-1%,%3-2%,%3-3%,%3-4 FALSE
der_max_pay [-Inf,1) 9531 0.4399058 1821 7710 0.8089393 1.2914530 0.6195986 1.2436362 1 FALSE
der_max_pay [1,3) 10480 0.4837072 6657 3823 0.3647901 -0.7063129 0.2378619 1.2436362 3 FALSE
der_max_pay [3, Inf) 1655 0.0763870 1535 120 0.0725076 -2.7004733 0.3861756 1.2436362 Inf FALSE
der_max_pay_first_3 [-Inf,1) 10400 0.4800148 2282 8118 0.7805769 1.1173522 0.5237487 1.1434558 1 FALSE
der_max_pay_first_3 [1,2) 1118 0.0516016 564 554 0.4955277 -0.1695690 0.0014897 1.1434558 2 FALSE
der_max_pay_first_3 [2,3) 8757 0.4041817 5877 2880 0.3288798 -0.8649355 0.2938967 1.1434558 3 FALSE
der_max_pay_first_3 [3, Inf) 1391 0.0642020 1290 101 0.0726096 -2.6989564 0.3243207 1.1434558 Inf FALSE
der_max_pay_last_3 [-Inf,1) 15183 0.7007754 4744 10439 0.6875453 0.6369887 0.2688326 0.9523631 1 FALSE
der_max_pay_last_3 [1, Inf) 6483 0.2992246 5269 1214 0.1872590 -1.6195993 0.6835304 0.9523631 Inf FALSE
der_cm_od_first_3 [-Inf,1) 11153 0.5147697 2768 8385 0.7518157 0.9566399 0.4239030 1.4076258 1 FALSE
der_cm_od_first_3 [1,2) 4860 0.2243146 2457 2403 0.4944444 -0.1739025 0.0068114 1.4076258 2 FALSE
der_cm_od_first_3 [2,3) 1841 0.0849718 1239 602 0.3269962 -0.8734818 0.0629594 1.4076258 3 FALSE
der_cm_od_first_3 [3, Inf) 3812 0.1759439 3549 263 0.0689927 -2.7539465 0.9139521 1.4076258 Inf FALSE
der_cm_od_last_3 [-Inf,1) 15183 0.7007754 4744 10439 0.6875453 0.6369887 0.2688326 1.2168217 1 FALSE
der_cm_od_last_3 [1,2) 2899 0.1338041 1935 964 0.3325285 -0.8484507 0.0937736 1.2168217 2 FALSE
der_cm_od_last_3 [2, Inf) 3584 0.1654205 3334 250 0.0697545 -2.7421466 0.8542155 1.2168217 Inf FALSE
der_cm_od [-Inf,1) 9531 0.4399058 1821 7710 0.8089393 1.2914530 0.6195986 2.5203618 1 FALSE
der_cm_od [1,3) 7556 0.3487492 3995 3561 0.4712811 -0.2666816 0.0249067 2.5203618 3 FALSE
der_cm_od [3,6) 2624 0.1211114 2243 381 0.1451982 -1.9244496 0.3681729 2.5203618 6 FALSE
der_cm_od [6, Inf) 1955 0.0902335 1954 1 0.0005115 -7.7293132 1.5076837 2.5203618 Inf FALSE
der_cm_punct_first_3 [-Inf,1) 2928 0.1351426 2833 95 0.0324454 -3.5468940 0.9746148 1.6155059 1 FALSE
der_cm_punct_first_3 [1,2) 1322 0.0610173 934 388 0.2934947 -1.0301505 0.0617911 1.6155059 2 FALSE
der_cm_punct_first_3 [2,4) 7016 0.3238253 3964 3052 0.4350057 -0.4131359 0.0553513 1.6155059 4 FALSE
der_cm_punct_first_3 [4, Inf) 10400 0.4800148 2282 8118 0.7805769 1.1173522 0.5237487 1.6155059 Inf FALSE
der_cm_punct_last_3 [-Inf,1) 2569 0.1185729 2481 88 0.0342546 -3.4907596 0.8385719 1.3066992 1 FALSE
der_cm_punct_last_3 [1,2) 1467 0.0677098 1118 349 0.2379005 -1.3159041 0.1075166 1.3066992 2 FALSE
der_cm_punct_last_3 [2,3) 2447 0.1129419 1670 777 0.3175317 -0.9168180 0.0917781 1.3066992 3 FALSE
der_cm_punct_last_3 [3, Inf) 15183 0.7007754 4744 10439 0.6875453 0.6369887 0.2688326 1.3066992 Inf FALSE
der_cm_punct [-Inf,1) 1955 0.0902335 1954 1 0.0005115 -7.7293132 1.5076837 2.4456198 1 FALSE
der_cm_punct [1,3) 2516 0.1161267 2064 452 0.1796502 -1.6703984 0.2795307 2.4456198 3 FALSE
der_cm_punct [3,6) 7664 0.3537340 4174 3490 0.4553758 -0.3306525 0.0388068 2.4456198 6 FALSE
der_cm_punct [6, Inf) 9531 0.4399058 1821 7710 0.8089393 1.2914530 0.6195986 2.4456198 Inf FALSE

Transform to WoE

Transformasi nilai asli dengan hasil WoE per masing masing bin variable untuk pemodelan scorecard

train_woe <- woebin_ply(dt = train,
                        bins = binning)
#> ✔ Woe transformating on 21666 rows and 35 columns in 00:00:12
test_woe <- woebin_ply(dt = test,
                        bins = binning)
#> ✔ Woe transformating on 9286 rows and 35 columns in 00:00:02

Information Value

Karena memang dikhususkan untuk existing customer variable derivatif terkait jumlah berapa kali pembayaran terlambat mendapat IV tertinggi, kemungkinan dikarenakan dalam penentuan target variable diambil dari riwayat pembiayaan.

info_val <- iv(dt = train_woe,
   y ='gb_flag',
   positive = 0)



info_val
#>                       variable    info_value
#>  1:              der_cm_od_woe 2.52036183299
#>  2:           der_cm_punct_woe 2.44561980495
#>  3:   der_cm_punct_first_3_woe 1.61550587939
#>  4:      der_cm_od_first_3_woe 1.40762584814
#>  5:    der_cm_punct_last_3_woe 1.30669920771
#>  6:            der_max_pay_woe 1.24363616181
#>  7:       der_cm_od_last_3_woe 1.21682171977
#>  8:    der_max_pay_first_3_woe 1.14345582141
#>  9:     der_max_pay_last_3_woe 0.95236305086
#> 10:                  pay_1_woe 0.90156463822
#> 11:                  pay_4_woe 0.89215545424
#> 12:                  pay_5_woe 0.86446845529
#> 13:                  pay_2_woe 0.74473009488
#> 14:                  pay_3_woe 0.73165916222
#> 15:                  pay_6_woe 0.71573380240
#> 16:              limit_bal_woe 0.68600256213
#> 17:              bill_amt6_woe 0.36505153390
#> 18:              bill_amt4_woe 0.34552057008
#> 19:              bill_amt5_woe 0.34278407367
#> 20:              bill_amt3_woe 0.30144297443
#> 21:              bill_amt2_woe 0.27862402949
#> 22:              bill_amt1_woe 0.24178320934
#> 23:      der_sex_education_woe 0.10661170429
#> 24:               pay_amt2_woe 0.09651588574
#> 25: der_marriage_education_woe 0.09379099179
#> 26:               pay_amt1_woe 0.09246700895
#> 27:              education_woe 0.07869044349
#> 28:               pay_amt6_woe 0.06885583223
#> 29:               pay_amt3_woe 0.06603215570
#> 30:               pay_amt5_woe 0.05397319591
#> 31:                    age_woe 0.04981323815
#> 32:               pay_amt4_woe 0.04418106082
#> 33:       der_sex_marriage_woe 0.01720165935
#> 34:                    sex_woe 0.01646469643
#> 35:               marriage_woe 0.00006328743
#>                       variable    info_value

Feature selection

Setelah di transform ke WoE maka dilakukan feature selection dengan mengeliminasi variable yang saling berkorelasi agar tidak terkena double punishment dan apabila saling berkorelasi maka dipilih yang IV nya lebih tinggi

cor_matrix <- cor(train_woe %>% select(-gb_flag))
rounded_abs_cor_matrix <- round(abs(cor_matrix), 2)

formatted_matrix <- rounded_abs_cor_matrix %>%
  as.data.frame() %>%
  mutate_all(~ cell_spec(., "html", color = "white", background = ifelse(. > 0.4, "red", "white")))


formatted_matrix %>%
  kbl(escape = FALSE) %>%
  kable_styling()
limit_bal_woe sex_woe education_woe marriage_woe age_woe pay_1_woe pay_2_woe pay_3_woe pay_4_woe pay_5_woe pay_6_woe bill_amt1_woe bill_amt2_woe bill_amt3_woe bill_amt4_woe bill_amt5_woe bill_amt6_woe pay_amt1_woe pay_amt2_woe pay_amt3_woe pay_amt4_woe pay_amt5_woe pay_amt6_woe der_sex_education_woe der_sex_marriage_woe der_marriage_education_woe der_max_pay_woe der_max_pay_first_3_woe der_max_pay_last_3_woe der_cm_od_first_3_woe der_cm_od_last_3_woe der_cm_od_woe der_cm_punct_first_3_woe der_cm_punct_last_3_woe der_cm_punct_woe
limit_bal_woe 1 0.06 0.26 0.08 0.3 0.26 0.24 0.23 0.26 0.23 0.23 0.06 0.13 0.13 0.01 0.01 0.02 0.27 0.17 0.33 0.27 0.16 0.31 0.26 0.05 0.29 0.33 0.31 0.3 0.29 0.29 0.27 0.29 0.28 0.27
sex_woe 0.06 1 0.01 0.04 0.07 0.03 0.04 0.03 0.03 0.04 0.04 0.06 0.06 0.06 0.05 0.04 0.04 0.01 0 0 0.01 0.01 0.01 0.42 0.98 0.02 0.05 0.05 0.04 0.05 0.04 0.04 0.04 0.04 0.04
education_woe 0.26 0.01 1 0.16 0.08 0.08 0.08 0.07 0.08 0.05 0.05 0.12 0.12 0.12 0.09 0.08 0.08 0.08 0.05 0.1 0.11 0.07 0.1 0.88 0.02 0.95 0.09 0.09 0.07 0.09 0.07 0.08 0.09 0.07 0.07
marriage_woe 0.08 0.04 0.16 1 0.22 0.01 0.01 0.01 0.01 0.01 0.01 0 0.01 0 0.01 0.02 0.01 0.02 0.01 0.01 0.02 0.01 0.02 0.13 0.12 0.06 0.01 0 0 0.01 0.01 0.01 0.02 0.01 0.01
age_woe 0.3 0.07 0.08 0.22 1 0.07 0.06 0.05 0.05 0.05 0.05 0.02 0.04 0.04 0 0.02 0.02 0.08 0.05 0.1 0.08 0.05 0.09 0.04 0.11 0.11 0.1 0.09 0.06 0.07 0.06 0.06 0.06 0.05 0.06
pay_1_woe 0.26 0.03 0.08 0.01 0.07 1 0.63 0.39 0.36 0.34 0.3 0.07 0.1 0.11 0.11 0.13 0.13 0.28 0.14 0.13 0.09 0.08 0.1 0.09 0.03 0.08 0.66 0.69 0.34 0.8 0.38 0.62 0.74 0.38 0.61
pay_2_woe 0.24 0.04 0.08 0.01 0.06 0.63 1 0.55 0.42 0.39 0.35 0.13 0.13 0.14 0.13 0.14 0.14 0.32 0.12 0.11 0.08 0.07 0.09 0.1 0.05 0.08 0.61 0.68 0.4 0.86 0.44 0.67 0.76 0.45 0.64
pay_3_woe 0.23 0.03 0.07 0.01 0.05 0.39 0.55 1 0.59 0.45 0.4 0.1 0.14 0.12 0.12 0.14 0.14 0.08 0.21 0.12 0.08 0.07 0.09 0.08 0.03 0.07 0.59 0.66 0.49 0.8 0.54 0.72 0.78 0.56 0.68
pay_4_woe 0.26 0.03 0.08 0.01 0.05 0.36 0.42 0.59 1 0.68 0.5 0.12 0.14 0.16 0.14 0.16 0.18 0.11 0.09 0.19 0.09 0.08 0.11 0.09 0.03 0.09 0.54 0.58 0.79 0.58 0.84 0.74 0.77 0.84 0.74
pay_5_woe 0.23 0.04 0.05 0.01 0.05 0.34 0.39 0.45 0.68 1 0.67 0.12 0.14 0.16 0.16 0.17 0.19 0.12 0.08 0.07 0.08 0.07 0.1 0.07 0.04 0.06 0.5 0.44 0.73 0.49 0.91 0.74 0.6 0.88 0.74
pay_6_woe 0.23 0.04 0.05 0.01 0.05 0.3 0.35 0.4 0.5 0.67 1 0.12 0.14 0.15 0.14 0.17 0.18 0.1 0.08 0.08 0.05 0.05 0.09 0.06 0.04 0.05 0.48 0.37 0.73 0.44 0.8 0.71 0.49 0.84 0.72
bill_amt1_woe 0.06 0.06 0.12 0 0.02 0.07 0.13 0.1 0.12 0.12 0.12 1 0.83 0.77 0.74 0.68 0.64 0.23 0.08 0.13 0.04 0.02 0.1 0.13 0.06 0.12 0.04 0.06 0.15 0.13 0.14 0.12 0.1 0.14 0.1
bill_amt2_woe 0.13 0.06 0.12 0.01 0.04 0.1 0.13 0.14 0.14 0.14 0.14 0.83 1 0.84 0.76 0.69 0.65 0.36 0.07 0.1 0.01 0.05 0.07 0.14 0.06 0.12 0.07 0.09 0.17 0.15 0.17 0.14 0.12 0.16 0.13
bill_amt3_woe 0.13 0.06 0.12 0 0.04 0.11 0.14 0.12 0.16 0.16 0.15 0.77 0.84 1 0.82 0.73 0.68 0.26 0.21 0.1 0.01 0.04 0.08 0.14 0.06 0.12 0.08 0.09 0.19 0.16 0.18 0.15 0.14 0.18 0.14
bill_amt4_woe 0.01 0.05 0.09 0.01 0 0.11 0.13 0.12 0.14 0.16 0.14 0.74 0.76 0.82 1 0.82 0.76 0.28 0.15 0.32 0.03 0.04 0.13 0.11 0.05 0.09 0.07 0.08 0.17 0.15 0.18 0.15 0.13 0.17 0.14
bill_amt5_woe 0.01 0.04 0.08 0.02 0.02 0.13 0.14 0.14 0.16 0.17 0.17 0.68 0.69 0.73 0.82 1 0.84 0.23 0.11 0.23 0.18 0.05 0.14 0.09 0.04 0.08 0.1 0.1 0.19 0.17 0.19 0.17 0.15 0.19 0.16
bill_amt6_woe 0.02 0.04 0.08 0.01 0.02 0.13 0.14 0.14 0.18 0.19 0.18 0.64 0.65 0.68 0.76 0.84 1 0.22 0.09 0.2 0.11 0.1 0.13 0.09 0.04 0.07 0.11 0.11 0.21 0.18 0.21 0.18 0.16 0.21 0.17
pay_amt1_woe 0.27 0.01 0.08 0.02 0.08 0.28 0.32 0.08 0.11 0.12 0.1 0.23 0.36 0.26 0.28 0.23 0.22 1 0.27 0.34 0.24 0.17 0.3 0.07 0.01 0.08 0.26 0.26 0.12 0.25 0.13 0.18 0.23 0.12 0.19
pay_amt2_woe 0.17 0 0.05 0.01 0.05 0.14 0.12 0.21 0.09 0.08 0.08 0.08 0.07 0.21 0.15 0.11 0.09 0.27 1 0.28 0.24 0.21 0.24 0.04 0 0.06 0.19 0.19 0.09 0.18 0.1 0.15 0.16 0.1 0.14
pay_amt3_woe 0.33 0 0.1 0.01 0.1 0.13 0.11 0.12 0.19 0.07 0.08 0.13 0.1 0.1 0.32 0.23 0.2 0.34 0.28 1 0.33 0.24 0.35 0.09 0 0.11 0.16 0.18 0.14 0.15 0.13 0.14 0.18 0.14 0.14
pay_amt4_woe 0.27 0.01 0.11 0.02 0.08 0.09 0.08 0.08 0.09 0.08 0.05 0.04 0.01 0.01 0.03 0.18 0.11 0.24 0.24 0.33 1 0.26 0.33 0.09 0.01 0.11 0.1 0.1 0.08 0.1 0.09 0.09 0.1 0.09 0.09
pay_amt5_woe 0.16 0.01 0.07 0.01 0.05 0.08 0.07 0.07 0.08 0.07 0.05 0.02 0.05 0.04 0.04 0.05 0.1 0.17 0.21 0.24 0.26 1 0.28 0.06 0 0.08 0.08 0.08 0.08 0.09 0.08 0.08 0.09 0.08 0.07
pay_amt6_woe 0.31 0.01 0.1 0.02 0.09 0.1 0.09 0.09 0.11 0.1 0.09 0.1 0.07 0.08 0.13 0.14 0.13 0.3 0.24 0.35 0.33 0.28 1 0.09 0.01 0.11 0.13 0.12 0.12 0.11 0.12 0.11 0.12 0.11 0.11
der_sex_education_woe 0.26 0.42 0.88 0.13 0.04 0.09 0.1 0.08 0.09 0.07 0.06 0.13 0.14 0.14 0.11 0.09 0.09 0.07 0.04 0.09 0.09 0.06 0.09 1 0.44 0.85 0.1 0.11 0.09 0.11 0.09 0.09 0.11 0.08 0.09
der_sex_marriage_woe 0.05 0.98 0.02 0.12 0.11 0.03 0.05 0.03 0.03 0.04 0.04 0.06 0.06 0.06 0.05 0.04 0.04 0.01 0 0 0.01 0 0.01 0.44 1 0 0.05 0.05 0.04 0.05 0.04 0.05 0.05 0.04 0.05
der_marriage_education_woe 0.29 0.02 0.95 0.06 0.11 0.08 0.08 0.07 0.09 0.06 0.05 0.12 0.12 0.12 0.09 0.08 0.07 0.08 0.06 0.11 0.11 0.08 0.11 0.85 0 1 0.1 0.1 0.08 0.1 0.08 0.08 0.1 0.07 0.08
der_max_pay_woe 0.33 0.05 0.09 0.01 0.1 0.66 0.61 0.59 0.54 0.5 0.48 0.04 0.07 0.08 0.07 0.1 0.11 0.26 0.19 0.16 0.1 0.08 0.13 0.1 0.05 0.1 1 0.92 0.61 0.73 0.6 0.68 0.76 0.59 0.68
der_max_pay_first_3_woe 0.31 0.05 0.09 0 0.09 0.69 0.68 0.66 0.58 0.44 0.37 0.06 0.09 0.09 0.08 0.1 0.11 0.26 0.19 0.18 0.1 0.08 0.12 0.11 0.05 0.1 0.92 1 0.52 0.79 0.54 0.68 0.82 0.54 0.68
der_max_pay_last_3_woe 0.3 0.04 0.07 0 0.06 0.34 0.4 0.49 0.79 0.73 0.73 0.15 0.17 0.19 0.17 0.19 0.21 0.12 0.09 0.14 0.08 0.08 0.12 0.09 0.04 0.08 0.61 0.52 1 0.51 0.91 0.66 0.64 0.88 0.69
der_cm_od_first_3_woe 0.29 0.05 0.09 0.01 0.07 0.8 0.86 0.8 0.58 0.49 0.44 0.13 0.15 0.16 0.15 0.17 0.18 0.25 0.18 0.15 0.1 0.09 0.11 0.11 0.05 0.1 0.73 0.79 0.51 1 0.57 0.83 0.93 0.59 0.8
der_cm_od_last_3_woe 0.29 0.04 0.07 0.01 0.06 0.38 0.44 0.54 0.84 0.91 0.8 0.14 0.17 0.18 0.18 0.19 0.21 0.13 0.1 0.13 0.09 0.08 0.12 0.09 0.04 0.08 0.6 0.54 0.91 0.57 1 0.78 0.7 0.96 0.8
der_cm_od_woe 0.27 0.04 0.08 0.01 0.06 0.62 0.67 0.72 0.74 0.74 0.71 0.12 0.14 0.15 0.15 0.17 0.18 0.18 0.15 0.14 0.09 0.08 0.11 0.09 0.05 0.08 0.68 0.68 0.66 0.83 0.78 1 0.89 0.86 0.98
der_cm_punct_first_3_woe 0.29 0.04 0.09 0.02 0.06 0.74 0.76 0.78 0.77 0.6 0.49 0.1 0.12 0.14 0.13 0.15 0.16 0.23 0.16 0.18 0.1 0.09 0.12 0.11 0.05 0.1 0.76 0.82 0.64 0.93 0.7 0.89 1 0.72 0.88
der_cm_punct_last_3_woe 0.28 0.04 0.07 0.01 0.05 0.38 0.45 0.56 0.84 0.88 0.84 0.14 0.16 0.18 0.17 0.19 0.21 0.12 0.1 0.14 0.09 0.08 0.11 0.08 0.04 0.07 0.59 0.54 0.88 0.59 0.96 0.86 0.72 1 0.86
der_cm_punct_woe 0.27 0.04 0.07 0.01 0.06 0.61 0.64 0.68 0.74 0.74 0.72 0.1 0.13 0.14 0.14 0.16 0.17 0.19 0.14 0.14 0.09 0.07 0.11 0.09 0.05 0.08 0.68 0.68 0.69 0.8 0.8 0.98 0.88 0.86 1

Binning Plot

Mari highlight variable der_cm_od_woe, dapat dilihat bahwa semakin sering seseorang tepat waktu maka akan semakin kecil probability of default nya. Antar Bin sudah risk rank dan merepresentasikan bin yang baik. Hasil IV bisa tinggi kemungkinan karena dalam penentuan badrate dilakukan analisa seperti Roll rate analysis yang diambil dari riwayat pembiayaan juga

plot <- woebin_plot(bins = binning)
plot$der_cm_od

Final Selection

pada tahap akhir setelah mendapatkan nilai IV tertinggi dan variable yang tidak saling berkorelasi, didapatkan variable berikut: der_cm_od_woe,limit_bal_woe,bill_amt6_woe,der_sex_education_woe,pay_amt2_woe,age_woe

train_woe_final<- train_woe %>% 
  select(c(der_cm_od_woe,limit_bal_woe,bill_amt6_woe,der_sex_education_woe,pay_amt2_woe,age_woe,gb_flag))

test_woe_final<- test_woe %>% 
  select(c(der_cm_od_woe,limit_bal_woe,bill_amt6_woe,der_sex_education_woe,pay_amt2_woe,age_woe,gb_flag))
train_woe_final %>% 
  head(2) %>% 
  kbl() %>%
  kable_styling()
der_cm_od_woe limit_bal_woe bill_amt6_woe der_sex_education_woe pay_amt2_woe age_woe gb_flag
-7.729313 -0.3426033 -0.3651836 -0.3807490 -0.0498411 0.1615227 1
1.291453 -1.1730820 0.8214494 0.5516054 -0.0498411 -0.4729658 0

Model Building

Semua variable yang digunakan dalam pembuatan model signifikan terhadap target kecuali variable umur

model <- glm(formula = gb_flag ~ .,
             data = train_woe_final,
             family = "binomial")

summary(model) 
#> 
#> Call:
#> glm(formula = gb_flag ~ ., family = "binomial", data = train_woe_final)
#> 
#> Deviance Residuals: 
#>     Min       1Q   Median       3Q      Max  
#> -3.9496  -0.6513  -0.2721   0.6772   2.4296  
#> 
#> Coefficients:
#>                       Estimate Std. Error z value             Pr(>|z|)    
#> (Intercept)           -0.15801    0.01857  -8.507 < 0.0000000000000002 ***
#> der_cm_od_woe         -0.86343    0.01793 -48.152 < 0.0000000000000002 ***
#> limit_bal_woe         -0.84729    0.02421 -35.000 < 0.0000000000000002 ***
#> bill_amt6_woe         -1.11035    0.03081 -36.037 < 0.0000000000000002 ***
#> der_sex_education_woe -0.32730    0.05701  -5.741   0.0000000094126076 ***
#> pay_amt2_woe          -0.47269    0.06219  -7.601   0.0000000000000293 ***
#> age_woe               -0.08688    0.08181  -1.062                0.288    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> (Dispersion parameter for binomial family taken to be 1)
#> 
#>     Null deviance: 29911  on 21665  degrees of freedom
#> Residual deviance: 18937  on 21659  degrees of freedom
#> AIC: 18951
#> 
#> Number of Fisher Scoring iterations: 6

Vif

Untuk membuktikan korelasi antar variable yang digunakan dalam model

vif(model)
#>                 variable     gvif
#> 1:         der_cm_od_woe 1.025403
#> 2:         limit_bal_woe 1.213765
#> 3:         bill_amt6_woe 1.092026
#> 4: der_sex_education_woe 1.053359
#> 5:          pay_amt2_woe 1.037778
#> 6:               age_woe 1.093182

Prediction

test_woe_final$pred_risk <- predict(object = model,
                                    newdata = test_woe_final,
                                    type = "response")
test_woe_final %>% 
  head(2) %>% 
  kbl() %>%
  kable_styling()
der_cm_od_woe limit_bal_woe bill_amt6_woe der_sex_education_woe pay_amt2_woe age_woe gb_flag pred_risk
-1.924450 -1.1730820 -0.3651836 -0.1148051 0.1782161 0.1615227 1 0.9449212
1.291453 -0.3426033 0.8214494 -0.3807490 -0.2315385 -0.1241682 0 0.1611022

Model Performance

Jika dilihat nilai KS sebesar 0,57 yang berarti model mampu membedakan kelas negatif dan positif dengan jarak 57% (cukup besar kemampuan nya dalam membedakan kelas positif dan negatif, sehingga meminimalisir prediksi yang salah)

list_pred <- list(test = test_woe_final$pred_risk)
list_label <- list(test = test_woe_final$gb_flag)

perf_eva(pred = list_pred,
         label = list_label,
         confusion_matrix = TRUE,
         threshold = 0.5,
         show_plot = c("ks", "roc"))

#> $binomial_metric
#> $binomial_metric$test
#>          MSE      RMSE   LogLoss        R2        KS       AUC      Gini
#> 1: 0.1466613 0.3829638 0.4400123 0.4092079 0.5712766 0.8743167 0.7486334
#> 
#> 
#> $confusion_matrix
#> $confusion_matrix$test
#>    label pred_0 pred_1     error
#> 1:     0   4242    790 0.1569952
#> 2:     1   1237   3017 0.2907851
#> 3: total   5479   3807 0.2182856
#> 
#> 
#> $pic
#> TableGrob (1 x 2) "arrange": 2 grobs
#>   z     cells    name           grob
#> 1 1 (1-1,1-1) arrange gtable[layout]
#> 2 2 (1-1,2-2) arrange gtable[layout]

Pembuatan Scorecard

score_card <- scorecard(bins = binning, 
                        model = model,
                        odds0 = 1/19,
                        points0 = 600,
                        pdo = 20)

scorecard_df <- bind_rows(score_card, .id = "variable")

scorecard_df %>% 
  kbl() %>%
  kable_styling()
variable bin woe points count count_distr neg pos posprob bin_iv total_iv breaks is_special_values
basepoints NA NA 520 NA NA NA NA NA NA NA NA NA
der_cm_od [-Inf,1) 1.2914530 32 9531 0.4399058 1821 7710 0.8089393 0.6195986 2.5203618 1 FALSE
der_cm_od [1,3) -0.2666816 -7 7556 0.3487492 3995 3561 0.4712811 0.0249067 2.5203618 3 FALSE
der_cm_od [3,6) -1.9244496 -48 2624 0.1211114 2243 381 0.1451982 0.3681729 2.5203618 6 FALSE
der_cm_od [6, Inf) -7.7293132 -193 1955 0.0902335 1954 1 0.0005115 1.5076837 2.5203618 Inf FALSE
limit_bal [-Inf,50000) -1.1730820 -29 4253 0.1962983 3127 1126 0.2647543 0.2529945 0.6860026 50000 FALSE
limit_bal [50000,150000) -0.3426033 -8 8784 0.4054279 4810 3974 0.4524135 0.0477409 0.6860026 150000 FALSE
limit_bal [150000,250000) 0.7525266 18 4622 0.2133296 1332 3290 0.7118131 0.1123550 0.6860026 250000 FALSE
limit_bal [250000, Inf) 1.3266819 32 4007 0.1849442 744 3263 0.8143249 0.2729122 0.6860026 Inf FALSE
bill_amt6 [-Inf,10000) 0.8214494 26 7843 0.3619958 2151 5692 0.7257427 0.2247791 0.3650515 10000 FALSE
bill_amt6 [10000,130000) -0.3651836 -12 12318 0.5685406 6814 5504 0.4468258 0.0760278 0.3650515 130000 FALSE
bill_amt6 [130000, Inf) -0.9816349 -31 1505 0.0694637 1048 457 0.3036545 0.0642446 0.3650515 Inf FALSE
der_sex_education 1-1 0.2580465 2 2935 0.1354657 1171 1764 0.6010221 0.0088844 0.1066117 1-1 FALSE
der_sex_education 1-2%,%1-3 -0.3807490 -4 5849 0.2699622 3258 2591 0.4429817 0.0392289 0.1066117 1-2%,%1-3 FALSE
der_sex_education 1-4%,%2-1 0.5516054 5 4150 0.1915444 1374 2776 0.6689157 0.0557123 0.1066117 1-4%,%2-1 FALSE
der_sex_education 2-2 -0.0667452 -1 6291 0.2903628 3012 3279 0.5212208 0.0012963 0.1066117 2-2 FALSE
der_sex_education 2-3%,%2-4 -0.1148051 -1 2441 0.1126650 1198 1243 0.5092175 0.0014898 0.1066117 2-3%,%2-4 FALSE
pay_amt2 [-Inf,500) -0.2315385 -3 5237 0.2417151 2723 2514 0.4800458 0.0130143 0.0965159 500 FALSE
pay_amt2 [500,1500) 0.1782161 2 3022 0.1394812 1264 1758 0.5817340 0.0043888 0.0965159 1500 FALSE
pay_amt2 [1500,15000) -0.0498411 -1 12226 0.5642943 5802 6424 0.5254376 0.0014041 0.0965159 15000 FALSE
pay_amt2 [15000, Inf) 1.3004779 18 1181 0.0545094 224 957 0.8103302 0.0777086 0.0965159 Inf FALSE
age [-Inf,26) -0.4729658 -1 3202 0.1477892 1856 1346 0.4203623 0.0330377 0.0498132 26 FALSE
age [26,29) 0.0055191 0 3047 0.1406351 1404 1643 0.5392189 0.0000043 0.0498132 29 FALSE
age [29,46) 0.1615227 0 12000 0.5538632 5068 6932 0.5776667 0.0143313 0.0498132 46 FALSE
age [46, Inf) -0.1241682 0 3417 0.1577125 1685 1732 0.5068774 0.0024399 0.0498132 Inf FALSE
score_train <- scorecard_ply(dt = train,
                       card = score_card,
                       only_total_score = F)

score_test <- scorecard_ply(dt = test,
                       card = score_card,
                       only_total_score = F)

score_train %>% head() %>% 
  kbl() %>%
  kable_styling()
der_cm_od_points limit_bal_points bill_amt6_points der_sex_education_points pay_amt2_points age_points score
-193 -8 -12 -4 -1 0 302
32 -29 26 5 -1 -1 552
-193 -8 -12 -1 -1 0 305
32 32 26 5 -3 0 612
32 -8 -12 -1 -1 0 530
32 32 -12 -1 -1 0 570

PSI

Dapat dismpulkan bahwa PSI antara train dan test sebesar 0.001937147 yang berarti tidak ada pergeseran signifikan antar variable yang digunakan dalam pembuatan scoring sehingga dapat dikatakan variable di data train dan test stabil

score_list <- list(train = score_train$score, 
                   test = score_test$score)

label_list <- list(train = train_woe_final$gb_flag, 
                   test = test_woe_final$gb_flag)

psi <- perf_psi(score = score_list, 
                label = label_list, 
                positive = 0)
psi$psi # psi data frame
#>    variable    dataset         psi
#> 1:     pred train_test 0.001937147
head(score_test,2) %>% 
    kbl() %>%
  kable_styling()
der_cm_od_points limit_bal_points bill_amt6_points der_sex_education_points pay_amt2_points age_points score
-48 -29 -12 -1 2 0 432
32 -8 26 -4 -3 0 563

Approval Rate

approval_rate_table <- approval_rate(score = score_test$score,
              label = test_woe_final$gb_flag,
              positive = 0)

approval_rate_table %>% 
  kbl() %>%
  kable_styling()
bin approval_rate neg_rate count_approved neg_approved count neg pos
[-Inf,426) 0.9039 0.4014 8394 3369 892 885 7
[426,470) 0.8020 0.3443 7447 2564 947 805 142
[470,491) 0.7169 0.3031 6657 2018 790 546 244
[491,511) 0.6049 0.2370 5617 1331 1040 687 353
[511,529) 0.5016 0.1773 4658 826 959 505 454
[529,536) 0.4010 0.1208 3724 450 934 376 558
[536,556) 0.3063 0.0654 2844 186 880 264 616
[556,569) 0.2015 0.0241 1871 45 973 141 832
[569,592) 0.1092 0.0059 1014 6 857 39 818
[592, Inf) 0.0000 0.0000 0 0 1014 6 1008

Kesimpulan

Cut-off score yang dapat diambil >=426 dengan menghasilkan approval rate sekitar 80% dan menyisakan badrate sekitar 34%