Laporan ini menganalisis risiko kredit menggunakan empat dataset sekunder yang berbeda. Semua model berada dalam tema yang sama, yaitu risiko ketika peminjam tidak mampu membayar kewajibannya sesuai perjanjian. Setiap dataset dipakai untuk satu jenis model karena bentuk variabel responnya berbeda.
Empat model yang digunakan adalah:
| Istilah | dalam laporan ini |
|---|---|
| Risiko kredit | Risiko bahwa peminjam tidak membayar pinjaman sesuai jadwal atau perjanjian. |
| Default / gagal bayar | Kondisi ketika nasabah atau peminjam tidak memenuhi kewajiban
pembayaran. Dalam data biner, 1 berarti default dan
0 berarti tidak default. |
| Charged-off / CHGOFF | Pinjaman yang sudah dianggap macet atau rugi oleh lembaga pemberi pinjaman. Dalam laporan ini, istilah ini disebut sebagai pinjaman bermasalah. |
| PIF / Paid in Full | Pinjaman sudah lunas dibayar. Dalam analisis SBA, ini dipakai sebagai kondisi tidak bermasalah. |
| Grade pinjaman | Tingkat risiko pinjaman. Grade A dianggap risiko lebih rendah, sedangkan grade G dianggap risiko lebih tinggi. |
| Odds ratio / OR | Ukuran untuk membaca pengaruh prediktor pada model logistik. Untuk
model ordinal dengan MASS::polr, OR = exp(beta) dibaca
sebagai perubahan odds untuk berada pada kategori yang lebih tinggi,
karena spesifikasi modelnya adalah
logit(P(Y <= j)) = alpha_j - x beta. |
| Relative risk ratio / RRR | Ukuran untuk membaca pengaruh prediktor pada regresi multinomial. RRR membandingkan satu kategori respon terhadap kategori acuan. |
| Incidence rate ratio / IRR | Ukuran untuk membaca pengaruh prediktor pada regresi Poisson. IRR lebih dari 1 berarti rate/jumlah kejadian per exposure lebih tinggi. |
| Data leakage | Kondisi ketika model diberi variabel yang sebenarnya sudah mengandung jawaban. Variabel seperti ini harus dihindari agar model tidak terlihat bagus secara palsu. |
Dataset yang digunakan bersumber dari repositori publik/sekunder: UCI Machine Learning Repository untuk data default kartu kredit, OpenIntro untuk Lending Club loan data, Prosper/Udacity public loan data untuk data Prosper, dan SBA Open Data untuk FOIA 7(a) loan data.
| Model | Dataset | Variabel respon | Bentuk respon | Tujuan analisis |
|---|---|---|---|---|
| Logistik biner | Default of Credit Card Clients | Y |
0/1 | Menjelaskan peluang gagal bayar kartu kredit |
| Ordinal | Lending Club loans_full_schema |
grade |
A < B < C < D < E < F < G | Menjelaskan tingkat risiko pinjaman |
| Multinomial | Prosper Loan Data | LoanStatus_recode |
Banyak kategori tanpa urutan | Menjelaskan status pinjaman |
| Poisson | SBA 7(a) FOIA | Jumlah_ChargedOff |
Hitungan/count | Menjelaskan jumlah pinjaman bermasalah |
Regresi logistik biner dipakai ketika respon hanya memiliki dua kategori. Dalam laporan ini, responnya adalah gagal bayar atau tidak gagal bayar.
\[ \log\left(\frac{P(Y=1)}{P(Y=0)}\right) = \beta_0 + \beta_1X_1 + \cdots + \beta_pX_p \]
Regresi ordinal dipakai ketika respon memiliki urutan. Dalam laporan ini, responnya adalah grade pinjaman A sampai G.
Pada analisis ini model diestimasi menggunakan fungsi
MASS::polr. Spesifikasi model polr adalah:
\[ \log\left(\frac{P(Y \leq j)}{P(Y > j)}\right) = \alpha_j - x\beta \]
Artinya, tanda koefisien harus dibaca dengan hati-hati. Jika
koefisien beta bernilai positif, maka nilai
alpha_j - x beta menjadi lebih kecil. Akibatnya, peluang
kumulatif untuk berada pada kategori rendah P(Y <= j)
menurun, sehingga peluang berada pada kategori yang lebih tinggi
meningkat. Dengan urutan grade
$A < B < C < D < E < F < G$, koefisien
positif berarti kecenderungan pinjaman bergeser ke grade yang lebih
buruk atau lebih berisiko.
Regresi multinomial dipakai ketika respon memiliki lebih dari dua
kategori dan kategorinya tidak diperlakukan sebagai urutan. Dalam
laporan ini, status pinjaman dibandingkan terhadap kategori acuan
Completed.
Regresi Poisson dipakai ketika respon berupa jumlah kejadian. Dalam
laporan ini, responnya adalah jumlah pinjaman bermasalah
(CHGOFF) pada setiap kelompok pinjaman SBA.
\[ Y_i \sim Poisson(\mu_i) \]
\[ \log(\mu_i) = \beta_0 + \beta_1X_1 + \cdots + \log(Total\_Loan_i) \]
Total_Loan digunakan sebagai offset,
supaya model menganalisis rate pinjaman bermasalah, bukan hanya jumlah
mentah.
required_packages <- c(
"readxl", "readr", "dplyr", "tidyr", "ggplot2",
"MASS", "nnet", "broom", "knitr", "scales", "stringr", "forcats", "tibble", "purrr",
"pROC", "ordinal"
)
missing_packages <- required_packages[!(required_packages %in% rownames(installed.packages()))]
if (length(missing_packages) > 0) {
install.packages(missing_packages, repos = "https://cloud.r-project.org")
}
invisible(lapply(required_packages, library, character.only = TRUE))data_dir <- "."
file_biner <- file.path(data_dir, "default of credit card clients.xls")
file_ordinal <- file.path(data_dir, "loans_full_schema.csv")
file_multinom <- file.path(data_dir, "prosperLoanData.csv")
file_poisson <- file.path(data_dir, "foia-7a-fy2010-fy2019-asof-260331.csv")
check_file <- function(path) {
if (!file.exists(path)) {
stop(paste("File tidak ditemukan:", path, "\nPastikan file Rmd dan dataset berada di folder yang sama atau ubah data_dir."))
}
}
invisible(lapply(c(file_biner, file_ordinal, file_multinom, file_poisson), check_file))
data_biner_raw <- readxl::read_excel(file_biner, skip = 1)
data_ordinal_raw <- readr::read_csv(file_ordinal, show_col_types = FALSE)
data_multinom_raw <- readr::read_csv(file_multinom, show_col_types = FALSE)
data_poisson_raw <- readr::read_csv(file_poisson, show_col_types = FALSE)dimensi_data <- tibble::tibble(
Dataset = c("Default Credit Card", "Lending Club", "Prosper Loan", "SBA 7(a) FOIA"),
Jumlah_Baris = c(nrow(data_biner_raw), nrow(data_ordinal_raw), nrow(data_multinom_raw), nrow(data_poisson_raw)),
Jumlah_Kolom = c(ncol(data_biner_raw), ncol(data_ordinal_raw), ncol(data_multinom_raw), ncol(data_poisson_raw))
)
knitr::kable(dimensi_data, caption = "Dimensi Data Awal")| Dataset | Jumlah_Baris | Jumlah_Kolom |
|---|---|---|
| Default Credit Card | 30000 | 25 |
| Lending Club | 10000 | 55 |
| Prosper Loan | 113937 | 81 |
| SBA 7(a) FOIA | 545751 | 43 |
Tujuan analisis ini adalah mengetahui faktor-faktor yang berhubungan dengan peluang nasabah kartu kredit mengalami gagal bayar pada bulan berikutnya. Gagal bayar berarti nasabah tidak membayar sesuai kewajiban pada periode yang diamati.
Variabel respon adalah Y:
Nilai Y |
Arti sederhana |
|---|---|
| 0 | Nasabah tidak gagal bayar |
| 1 | Nasabah gagal bayar |
Prediktor yang digunakan adalah X1 sampai
X23. Seluruh prediktor ini digunakan karena dataset memang
dirancang dengan 23 variabel penjelas untuk menganalisis default
pembayaran kartu kredit.
| Variabel | Makna | Alasan_dipakai |
|---|---|---|
| X1 | Jumlah kredit yang diberikan | Menggambarkan kapasitas/limit kredit nasabah |
| X2 | Gender | Karakteristik demografi nasabah |
| X3 | Pendidikan | Karakteristik sosial ekonomi nasabah |
| X4 | Status perkawinan | Karakteristik demografi nasabah |
| X5 | Umur | Umur dapat berkaitan dengan perilaku pembayaran |
| X6-X11 | Riwayat status pembayaran April-September 2005 | Riwayat keterlambatan adalah indikator penting risiko gagal bayar |
| X12-X17 | Jumlah tagihan April-September 2005 | Tagihan menggambarkan beban kewajiban nasabah |
| X18-X23 | Jumlah pembayaran sebelumnya April-September 2005 | Pembayaran sebelumnya menggambarkan kemampuan dan kemauan bayar |
# Setelah skip = 1, kolom pertama sampai ke-25 adalah ID, X1-X23, dan Y.
names(data_biner_raw)[1:25] <- c("ID", paste0("X", 1:23), "Y")
money_vars_biner <- c("X1", paste0("X", 12:23))
data_biner <- data_biner_raw %>%
dplyr::select(ID, dplyr::all_of(paste0("X", 1:23)), Y) %>%
dplyr::mutate(dplyr::across(dplyr::everything(), as.numeric)) %>%
tidyr::drop_na() %>%
dplyr::mutate(
Y_num = Y,
Y_label = factor(Y, levels = c(0, 1), labels = c("Tidak gagal bayar", "Gagal bayar")),
X2 = factor(dplyr::case_when(
X2 == 1 ~ "Male",
X2 == 2 ~ "Female",
TRUE ~ "Other"
)),
X3 = factor(dplyr::case_when(
X3 == 1 ~ "Graduate school",
X3 == 2 ~ "University",
X3 == 3 ~ "High school",
TRUE ~ "Others"
)),
X4 = factor(dplyr::case_when(
X4 == 1 ~ "Married",
X4 == 2 ~ "Single",
TRUE ~ "Others"
))
) %>%
dplyr::mutate(dplyr::across(dplyr::all_of(money_vars_biner), ~ .x / 1000, .names = "{.col}_k"))
knitr::kable(head(data_biner, 6), caption = "Cuplikan Data Biner Setelah Cleaning")| ID | X1 | X2 | X3 | X4 | X5 | X6 | X7 | X8 | X9 | X10 | X11 | X12 | X13 | X14 | X15 | X16 | X17 | X18 | X19 | X20 | X21 | X22 | X23 | Y | Y_num | Y_label | X1_k | X12_k | X13_k | X14_k | X15_k | X16_k | X17_k | X18_k | X19_k | X20_k | X21_k | X22_k | X23_k |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 20000 | Female | University | Married | 24 | 2 | 2 | -1 | -1 | -2 | -2 | 3913 | 3102 | 689 | 0 | 0 | 0 | 0 | 689 | 0 | 0 | 0 | 0 | 1 | 1 | Gagal bayar | 20 | 3.913 | 3.102 | 0.689 | 0.000 | 0.000 | 0.000 | 0.000 | 0.689 | 0.000 | 0.0 | 0.000 | 0.000 |
| 2 | 120000 | Female | University | Single | 26 | -1 | 2 | 0 | 0 | 0 | 2 | 2682 | 1725 | 2682 | 3272 | 3455 | 3261 | 0 | 1000 | 1000 | 1000 | 0 | 2000 | 1 | 1 | Gagal bayar | 120 | 2.682 | 1.725 | 2.682 | 3.272 | 3.455 | 3.261 | 0.000 | 1.000 | 1.000 | 1.0 | 0.000 | 2.000 |
| 3 | 90000 | Female | University | Single | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 29239 | 14027 | 13559 | 14331 | 14948 | 15549 | 1518 | 1500 | 1000 | 1000 | 1000 | 5000 | 0 | 0 | Tidak gagal bayar | 90 | 29.239 | 14.027 | 13.559 | 14.331 | 14.948 | 15.549 | 1.518 | 1.500 | 1.000 | 1.0 | 1.000 | 5.000 |
| 4 | 50000 | Female | University | Married | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 46990 | 48233 | 49291 | 28314 | 28959 | 29547 | 2000 | 2019 | 1200 | 1100 | 1069 | 1000 | 0 | 0 | Tidak gagal bayar | 50 | 46.990 | 48.233 | 49.291 | 28.314 | 28.959 | 29.547 | 2.000 | 2.019 | 1.200 | 1.1 | 1.069 | 1.000 |
| 5 | 50000 | Male | University | Married | 57 | -1 | 0 | -1 | 0 | 0 | 0 | 8617 | 5670 | 35835 | 20940 | 19146 | 19131 | 2000 | 36681 | 10000 | 9000 | 689 | 679 | 0 | 0 | Tidak gagal bayar | 50 | 8.617 | 5.670 | 35.835 | 20.940 | 19.146 | 19.131 | 2.000 | 36.681 | 10.000 | 9.0 | 0.689 | 0.679 |
| 6 | 50000 | Male | Graduate school | Single | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 64400 | 57069 | 57608 | 19394 | 19619 | 20024 | 2500 | 1815 | 657 | 1000 | 1000 | 800 | 0 | 0 | Tidak gagal bayar | 50 | 64.400 | 57.069 | 57.608 | 19.394 | 19.619 | 20.024 | 2.500 | 1.815 | 0.657 | 1.0 | 1.000 | 0.800 |
Variabel uang seperti X1, X12 sampai
X23 diskalakan dalam ribuan agar interpretasi lebih mudah.
X1_k berarti limit kredit dalam ribuan NT dollar.
dist_biner <- data_biner %>%
dplyr::count(Y_label) %>%
dplyr::mutate(Persen = scales::percent(n / sum(n)))
knitr::kable(dist_biner, caption = "Distribusi Status Gagal Bayar")| Y_label | n | Persen |
|---|---|---|
| Tidak gagal bayar | 23364 | 78% |
| Gagal bayar | 6636 | 22% |
summary_biner <- data_biner %>%
dplyr::summarise(
Rata_rata_limit_k = mean(X1_k),
Median_limit_k = median(X1_k),
Rata_rata_umur = mean(X5),
Median_umur = median(X5)
)
knitr::kable(summary_biner, caption = "Ringkasan Prediktor Utama Data Biner")| Rata_rata_limit_k | Median_limit_k | Rata_rata_umur | Median_umur |
|---|---|---|---|
| 167.4843 | 140 | 35.4855 | 34 |
ggplot(data_biner, aes(x = Y_label)) +
geom_bar() +
labs(
title = "Distribusi Gagal Bayar Kartu Kredit",
x = "Status nasabah",
y = "Jumlah nasabah"
) +
theme_minimal()Model biner dibentuk untuk menjelaskan peluang Y = 1,
yaitu nasabah gagal bayar.
\[ \log\left(\frac{P(Y=1)}{P(Y=0)}\right) = \beta_0 + \beta_1X_1 + \cdots + \beta_{23}X_{23} \]
formula_biner <- as.formula(paste(
"Y_num ~ X1_k + X2 + X3 + X4 + X5 +",
paste(paste0("X", 6:11), collapse = " + "), "+",
paste(paste0("X", 12:23, "_k"), collapse = " + ")
))
model_biner <- glm(
formula_biner,
data = data_biner,
family = binomial(link = "logit")
)
summary(model_biner)##
## Call:
## glm(formula = formula_biner, family = binomial(link = "logit"),
## data = data_biner)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.1074252 0.0821938 -13.473 < 0.0000000000000002 ***
## X1_k -0.0007133 0.0001577 -4.522 0.000006114973 ***
## X2Male 0.1129693 0.0307258 3.677 0.000236 ***
## X3High school -0.1130401 0.0475987 -2.375 0.017556 *
## X3Others -1.1624892 0.1884460 -6.169 0.000000000688 ***
## X3University -0.0845189 0.0355734 -2.376 0.017506 *
## X4Others -0.1932064 0.1319446 -1.464 0.143112
## X4Single -0.1877621 0.0346303 -5.422 0.000000058970 ***
## X5 0.0056350 0.0018594 3.031 0.002441 **
## X6 0.5774743 0.0177087 32.610 < 0.0000000000000002 ***
## X7 0.0811208 0.0201961 4.017 0.000059030160 ***
## X8 0.0710667 0.0226075 3.143 0.001669 **
## X9 0.0228907 0.0250040 0.915 0.359938
## X10 0.0341754 0.0268869 1.271 0.203700
## X11 0.0071786 0.0221513 0.324 0.745886
## X12_k -0.0054952 0.0011374 -4.831 0.000001355474 ***
## X13_k 0.0023935 0.0015047 1.591 0.111683
## X14_k 0.0013958 0.0013238 1.054 0.291694
## X15_k -0.0001765 0.0013519 -0.131 0.896140
## X16_k 0.0007716 0.0015225 0.507 0.612305
## X17_k 0.0001770 0.0011977 0.148 0.882525
## X18_k -0.0136808 0.0023079 -5.928 0.000000003069 ***
## X19_k -0.0095322 0.0020889 -4.563 0.000005034879 ***
## X20_k -0.0026224 0.0017191 -1.525 0.127151
## X21_k -0.0040673 0.0017859 -2.278 0.022756 *
## X22_k -0.0031418 0.0017786 -1.766 0.077325 .
## X23_k -0.0020692 0.0012966 -1.596 0.110534
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 31705 on 29999 degrees of freedom
## Residual deviance: 27840 on 29973 degrees of freedom
## AIC: 27894
##
## Number of Fisher Scoring iterations: 6
Chunk model-biner di atas sudah membangun model
regresi logistik biner menggunakan fungsi glm()
dengan family = binomial(link = "logit"). Model yang
diestimasi adalah model peluang gagal bayar, yaitu peluang ketika
Y_num = 1.
Persamaan umumnya adalah:
\[ \widehat{\eta_i} = \log\left(\frac{\widehat{P}(Y_i=1)}{\widehat{P}(Y_i=0)}\right) = \hat{\beta}_0 + \hat{\beta}_1X_{1i} + \cdots + \hat{\beta}_{23}X_{23i} \]
Persamaan hasil estimasi model biner dapat ditulis sebagai berikut:
\[ \widehat{\eta_i} = -1.1074 - 0.0007\,X_{1k} + 0.113\,X_{2Male} - 0.113\,X_{3HighSchool} - 1.1625\,X_{3Others} - 0.0845\,X_{3University} - 0.1932\,X_{4Others} - 0.1878\,X_{4Single} + 0.0056\,X_5 + 0.5775\,X_6 + 0.0811\,X_7 + 0.0711\,X_8 + 0.0229\,X_9 + 0.0342\,X_{10} + 0.0072\,X_{11} - 0.0055\,X_{12k} + 0.0024\,X_{13k} + 0.0014\,X_{14k} - 0.0002\,X_{15k} + 0.0008\,X_{16k} + 0.0002\,X_{17k} - 0.0137\,X_{18k} - 0.0095\,X_{19k} - 0.0026\,X_{20k} - 0.0041\,X_{21k} - 0.0031\,X_{22k} - 0.0021\,X_{23k} \]
\[ \widehat{\eta_i} = \log\left(\frac{\widehat{P}(Y_i=1)}{\widehat{P}(Y_i=0)}\right) \]
Dengan:
\[ \widehat{P}(Y_i=1) = \frac{\exp(\widehat{\eta_i})}{1+\exp(\widehat{\eta_i})} \]
Persamaan tersebut menunjukkan bahwa setiap koefisien masuk ke dalam log-odds gagal bayar. Koefisien positif meningkatkan log-odds gagal bayar, sedangkan koefisien negatif menurunkan log-odds gagal bayar.
| Variabel_Mudah | term | estimate | Odds_Ratio |
|---|---|---|---|
| (Intercept) | (Intercept) | -1.1074 | 0.3304 |
| jumlah limit kredit (per 1.000 NT dollar) | X1_k | -0.0007 | 0.9993 |
| jenis kelamin: Male dibanding kategori acuan | X2Male | 0.1130 | 1.1196 |
| pendidikan: High school dibanding kategori acuan | X3High school | -0.1130 | 0.8931 |
| pendidikan: Others dibanding kategori acuan | X3Others | -1.1625 | 0.3127 |
| pendidikan: University dibanding kategori acuan | X3University | -0.0845 | 0.9190 |
| status perkawinan: Others dibanding kategori acuan | X4Others | -0.1932 | 0.8243 |
| status perkawinan: Single dibanding kategori acuan | X4Single | -0.1878 | 0.8288 |
| umur nasabah | X5 | 0.0056 | 1.0057 |
| status pembayaran September 2005 | X6 | 0.5775 | 1.7815 |
| status pembayaran Agustus 2005 | X7 | 0.0811 | 1.0845 |
| status pembayaran Juli 2005 | X8 | 0.0711 | 1.0737 |
| status pembayaran Juni 2005 | X9 | 0.0229 | 1.0232 |
| status pembayaran Mei 2005 | X10 | 0.0342 | 1.0348 |
| status pembayaran April 2005 | X11 | 0.0072 | 1.0072 |
| tagihan September 2005 (per 1.000 NT dollar) | X12_k | -0.0055 | 0.9945 |
| tagihan Agustus 2005 (per 1.000 NT dollar) | X13_k | 0.0024 | 1.0024 |
| tagihan Juli 2005 (per 1.000 NT dollar) | X14_k | 0.0014 | 1.0014 |
| tagihan Juni 2005 (per 1.000 NT dollar) | X15_k | -0.0002 | 0.9998 |
| tagihan Mei 2005 (per 1.000 NT dollar) | X16_k | 0.0008 | 1.0008 |
| tagihan April 2005 (per 1.000 NT dollar) | X17_k | 0.0002 | 1.0002 |
| pembayaran September 2005 (per 1.000 NT dollar) | X18_k | -0.0137 | 0.9864 |
| pembayaran Agustus 2005 (per 1.000 NT dollar) | X19_k | -0.0095 | 0.9905 |
| pembayaran Juli 2005 (per 1.000 NT dollar) | X20_k | -0.0026 | 0.9974 |
| pembayaran Juni 2005 (per 1.000 NT dollar) | X21_k | -0.0041 | 0.9959 |
| pembayaran Mei 2005 (per 1.000 NT dollar) | X22_k | -0.0031 | 0.9969 |
| pembayaran April 2005 (per 1.000 NT dollar) | X23_k | -0.0021 | 0.9979 |
tabel_biner <- broom::tidy(model_biner) %>%
dplyr::mutate(
Odds_Ratio = exp(estimate),
Variabel_Mudah = purrr::map_chr(term, label_biner),
Keputusan_5persen = ifelse(p.value < 0.05, "Signifikan", "Tidak signifikan")
) %>%
dplyr::arrange(p.value)
knitr::kable(
tabel_biner %>% dplyr::select(Variabel_Mudah, term, estimate, std.error, statistic, p.value, Odds_Ratio, Keputusan_5persen) %>% head(25),
digits = 4,
caption = "Koefisien dan Odds Ratio Regresi Logistik Biner"
)| Variabel_Mudah | term | estimate | std.error | statistic | p.value | Odds_Ratio | Keputusan_5persen |
|---|---|---|---|---|---|---|---|
| status pembayaran September 2005 | X6 | 0.5775 | 0.0177 | 32.6097 | 0.0000 | 1.7815 | Signifikan |
| (Intercept) | (Intercept) | -1.1074 | 0.0822 | -13.4733 | 0.0000 | 0.3304 | Signifikan |
| pendidikan: Others dibanding kategori acuan | X3Others | -1.1625 | 0.1884 | -6.1688 | 0.0000 | 0.3127 | Signifikan |
| pembayaran September 2005 (per 1.000 NT dollar) | X18_k | -0.0137 | 0.0023 | -5.9279 | 0.0000 | 0.9864 | Signifikan |
| status perkawinan: Single dibanding kategori acuan | X4Single | -0.1878 | 0.0346 | -5.4219 | 0.0000 | 0.8288 | Signifikan |
| tagihan September 2005 (per 1.000 NT dollar) | X12_k | -0.0055 | 0.0011 | -4.8314 | 0.0000 | 0.9945 | Signifikan |
| pembayaran Agustus 2005 (per 1.000 NT dollar) | X19_k | -0.0095 | 0.0021 | -4.5633 | 0.0000 | 0.9905 | Signifikan |
| jumlah limit kredit (per 1.000 NT dollar) | X1_k | -0.0007 | 0.0002 | -4.5224 | 0.0000 | 0.9993 | Signifikan |
| status pembayaran Agustus 2005 | X7 | 0.0811 | 0.0202 | 4.0167 | 0.0001 | 1.0845 | Signifikan |
| jenis kelamin: Male dibanding kategori acuan | X2Male | 0.1130 | 0.0307 | 3.6767 | 0.0002 | 1.1196 | Signifikan |
| status pembayaran Juli 2005 | X8 | 0.0711 | 0.0226 | 3.1435 | 0.0017 | 1.0737 | Signifikan |
| umur nasabah | X5 | 0.0056 | 0.0019 | 3.0305 | 0.0024 | 1.0057 | Signifikan |
| pendidikan: University dibanding kategori acuan | X3University | -0.0845 | 0.0356 | -2.3759 | 0.0175 | 0.9190 | Signifikan |
| pendidikan: High school dibanding kategori acuan | X3High school | -0.1130 | 0.0476 | -2.3749 | 0.0176 | 0.8931 | Signifikan |
| pembayaran Juni 2005 (per 1.000 NT dollar) | X21_k | -0.0041 | 0.0018 | -2.2775 | 0.0228 | 0.9959 | Signifikan |
| pembayaran Mei 2005 (per 1.000 NT dollar) | X22_k | -0.0031 | 0.0018 | -1.7664 | 0.0773 | 0.9969 | Tidak signifikan |
| pembayaran April 2005 (per 1.000 NT dollar) | X23_k | -0.0021 | 0.0013 | -1.5958 | 0.1105 | 0.9979 | Tidak signifikan |
| tagihan Agustus 2005 (per 1.000 NT dollar) | X13_k | 0.0024 | 0.0015 | 1.5907 | 0.1117 | 1.0024 | Tidak signifikan |
| pembayaran Juli 2005 (per 1.000 NT dollar) | X20_k | -0.0026 | 0.0017 | -1.5254 | 0.1272 | 0.9974 | Tidak signifikan |
| status perkawinan: Others dibanding kategori acuan | X4Others | -0.1932 | 0.1319 | -1.4643 | 0.1431 | 0.8243 | Tidak signifikan |
| status pembayaran Mei 2005 | X10 | 0.0342 | 0.0269 | 1.2711 | 0.2037 | 1.0348 | Tidak signifikan |
| tagihan Juli 2005 (per 1.000 NT dollar) | X14_k | 0.0014 | 0.0013 | 1.0544 | 0.2917 | 1.0014 | Tidak signifikan |
| status pembayaran Juni 2005 | X9 | 0.0229 | 0.0250 | 0.9155 | 0.3599 | 1.0232 | Tidak signifikan |
| tagihan Mei 2005 (per 1.000 NT dollar) | X16_k | 0.0008 | 0.0015 | 0.5068 | 0.6123 | 1.0008 | Tidak signifikan |
| status pembayaran April 2005 | X11 | 0.0072 | 0.0222 | 0.3241 | 0.7459 | 1.0072 | Tidak signifikan |
data_biner$prob_default <- predict(model_biner, type = "response")
data_biner$pred_default <- ifelse(data_biner$prob_default >= 0.5, 1, 0)
tabel_klasifikasi_biner <- table(
Prediksi = factor(data_biner$pred_default, levels = c(0, 1), labels = c("Tidak gagal bayar", "Gagal bayar")),
Aktual = data_biner$Y_label
)
tabel_klasifikasi_biner## Aktual
## Prediksi Tidak gagal bayar Gagal bayar
## Tidak gagal bayar 22729 5034
## Gagal bayar 635 1602
## [1] 0.8110333
## [1] 27894.21
Visualisasi ini digunakan untuk melihat sebaran probabilitas gagal bayar yang dihasilkan oleh model. Probabilitas yang lebih tinggi menunjukkan nasabah yang diprediksi memiliki risiko gagal bayar lebih besar.
ggplot(data_biner, aes(x = prob_default)) +
geom_histogram(bins = 40) +
labs(
title = "Distribusi Probabilitas Prediksi Gagal Bayar",
x = "Probabilitas prediksi gagal bayar",
y = "Jumlah nasabah"
) +
theme_minimal()ggplot(data_biner, aes(x = Y_label, y = prob_default)) +
geom_boxplot() +
labs(
title = "Probabilitas Prediksi Gagal Bayar menurut Status Aktual",
x = "Status aktual",
y = "Probabilitas prediksi gagal bayar"
) +
theme_minimal()Grafik pertama menunjukkan sebaran probabilitas gagal bayar hasil model. Grafik kedua membandingkan probabilitas prediksi antara nasabah yang benar-benar gagal bayar dan tidak gagal bayar. Jika model cukup membedakan risiko, maka kelompok yang aktual gagal bayar seharusnya memiliki probabilitas prediksi yang lebih tinggi.
ROC Curve digunakan untuk melihat kemampuan model membedakan nasabah gagal bayar dan tidak gagal bayar pada berbagai threshold. AUC mendekati 1 menunjukkan kemampuan pemisahan yang lebih baik, sedangkan AUC mendekati 0,5 menunjukkan kemampuan model mendekati tebakan acak.
roc_biner <- pROC::roc(
response = data_biner$Y_num,
predictor = data_biner$prob_default,
quiet = TRUE
)
auc_biner <- pROC::auc(roc_biner)
auc_biner## Area under the curve: 0.7259
AUC menunjukkan kemampuan model membedakan nasabah yang gagal bayar dan tidak gagal bayar. Semakin besar AUC, semakin baik kemampuan diskriminasi model. Namun AUC tidak menjelaskan arah pengaruh variabel; arah pengaruh tetap dibaca melalui koefisien dan odds ratio.
Regresi logistik biner digunakan karena variabel respon hanya memiliki dua kategori, yaitu gagal bayar dan tidak gagal bayar. Model ini mengasumsikan bahwa observasi bersifat independen, tidak terdapat multikolinearitas berat antar prediktor, tidak terjadi perfect separation, dan prediktor numerik memiliki hubungan yang cukup linear terhadap log-odds gagal bayar.
Pada analisis credit risk, jumlah nasabah gagal bayar sering kali lebih kecil daripada nasabah tidak gagal bayar. Oleh karena itu, akurasi tidak boleh menjadi satu-satunya ukuran evaluasi. Confusion matrix, probabilitas prediksi, dan AUC perlu dibaca bersama dengan interpretasi odds ratio.
sig_biner <- tabel_biner %>%
dplyr::filter(term != "(Intercept)", p.value < 0.05) %>%
dplyr::arrange(p.value)
cat("Pada taraf signifikansi 5%, model biner menemukan ", nrow(sig_biner),
" prediktor yang berhubungan signifikan dengan peluang gagal bayar.\n\n", sep = "")Pada taraf signifikansi 5%, model biner menemukan 14 prediktor yang berhubungan signifikan dengan peluang gagal bayar.
if (nrow(sig_biner) > 0) {
cat("Prediktor paling penting berdasarkan p-value terkecil adalah:\n\n")
top_biner <- head(sig_biner, 8)
for (i in seq_len(nrow(top_biner))) {
row <- top_biner[i, ]
arah <- ifelse(row$Odds_Ratio > 1,
"meningkatkan odds gagal bayar",
"menurunkan odds gagal bayar")
cat("- **", row$Variabel_Mudah, "** memiliki OR = ", fmt_num(row$Odds_Ratio, 3),
" dan p-value = ", fmt_p(row$p.value), ", sehingga variabel ini ", arah,
", dengan asumsi variabel lain tetap.\n", sep = "")
}
cat("\n")
}Prediktor paling penting berdasarkan p-value terkecil adalah:
cat("Akurasi klasifikasi model biner adalah **", scales::percent(akurasi_biner),
"**. AIC model adalah **", fmt_num(AIC_biner, 2), "**.\n\n", sep = "")Akurasi klasifikasi model biner adalah 81%. AIC model adalah 27,894.21.
if (any(sig_biner$term %in% paste0("X", 6:11))) {
cat("**Kesimpulan substantif:** riwayat pembayaran sebelumnya menjadi faktor penting dalam menjelaskan gagal bayar. Dalam konteks risiko kredit, nasabah yang memiliki riwayat keterlambatan pembayaran cenderung lebih berisiko mengalami gagal bayar pada periode berikutnya.\n")
} else {
cat("**Kesimpulan substantif:** model menunjukkan bahwa risiko gagal bayar dapat dijelaskan oleh kombinasi limit kredit, karakteristik demografi, tagihan, dan pembayaran sebelumnya. Variabel signifikan pada tabel di atas menjadi faktor utama yang perlu diperhatikan dalam penilaian risiko kartu kredit.\n")
}Kesimpulan substantif: riwayat pembayaran sebelumnya menjadi faktor penting dalam menjelaskan gagal bayar. Dalam konteks risiko kredit, nasabah yang memiliki riwayat keterlambatan pembayaran cenderung lebih berisiko mengalami gagal bayar pada periode berikutnya.
Tujuan analisis ini adalah mengetahui faktor-faktor yang berhubungan
dengan tingkat risiko pinjaman pada data Lending Club.
Tingkat risiko diwakili oleh grade, dari A sampai G.
Variabel respon adalah grade dengan urutan:
\[ A < B < C < D < E < F < G \]
Dalam bahasa sederhana, A adalah risiko lebih rendah dan G adalah risiko lebih tinggi.
| Variabel | Peran | Alasan_dipakai |
|---|---|---|
| grade | Respon | Mewakili tingkat risiko pinjaman dari A sampai G |
| annual_income | Prediktor | Menggambarkan kemampuan pendapatan peminjam |
| debt_to_income | Prediktor | Mengukur beban utang dibanding pendapatan |
| delinq_2y | Prediktor | Riwayat keterlambatan kredit 2 tahun terakhir |
| inquiries_last_12m | Prediktor | Banyaknya pemeriksaan kredit terbaru |
| total_credit_lines | Prediktor | Menggambarkan pengalaman kredit peminjam |
| open_credit_lines | Prediktor | Menggambarkan kredit aktif |
| total_credit_limit | Prediktor | Menggambarkan total fasilitas kredit |
| total_credit_utilized | Prediktor | Menggambarkan total kredit yang sedang digunakan |
| num_historical_failed_to_pay | Prediktor | Riwayat gagal bayar sebelumnya |
| public_record_bankrupt | Prediktor | Riwayat kebangkrutan |
| loan_amount | Prediktor | Besar pinjaman yang diterima |
| term | Prediktor | Tenor atau lama pinjaman |
| homeownership | Prediktor | Status tempat tinggal peminjam |
| verified_income | Prediktor | Status verifikasi pendapatan |
| loan_purpose | Prediktor | Tujuan penggunaan pinjaman |
| application_type | Prediktor | Aplikasi individu atau joint |
Variabel sub_grade, interest_rate,
loan_status, balance, paid_total,
paid_principal, paid_interest, dan
paid_late_fees tidak digunakan. Alasannya,
variabel-variabel tersebut terlalu dekat dengan hasil penilaian grade
atau muncul setelah pinjaman berjalan. Jika dipakai, model berisiko
mengalami data leakage.
prediktor_ordinal <- c(
"annual_income", "debt_to_income", "delinq_2y", "inquiries_last_12m",
"total_credit_lines", "open_credit_lines", "total_credit_limit", "total_credit_utilized",
"num_historical_failed_to_pay", "public_record_bankrupt", "loan_amount", "term",
"homeownership", "verified_income", "loan_purpose", "application_type"
)
data_ordinal <- data_ordinal_raw %>%
dplyr::select(grade, dplyr::all_of(prediktor_ordinal)) %>%
tidyr::drop_na() %>%
dplyr::mutate(
grade = ordered(grade, levels = c("A", "B", "C", "D", "E", "F", "G")),
homeownership = factor(homeownership),
verified_income = factor(verified_income),
loan_purpose = factor(loan_purpose),
application_type = factor(application_type),
term = factor(term),
annual_income_k = annual_income / 1000,
total_credit_limit_k = total_credit_limit / 1000,
total_credit_utilized_k = total_credit_utilized / 1000,
loan_amount_k = loan_amount / 1000
)
knitr::kable(head(data_ordinal, 6), caption = "Cuplikan Data Ordinal Setelah Cleaning")| grade | annual_income | debt_to_income | delinq_2y | inquiries_last_12m | total_credit_lines | open_credit_lines | total_credit_limit | total_credit_utilized | num_historical_failed_to_pay | public_record_bankrupt | loan_amount | term | homeownership | verified_income | loan_purpose | application_type | annual_income_k | total_credit_limit_k | total_credit_utilized_k | loan_amount_k |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| C | 90000 | 18.01 | 0 | 6 | 28 | 10 | 70795 | 38767 | 0 | 0 | 28000 | 60 | MORTGAGE | Verified | moving | individual | 90 | 70.795 | 38.767 | 28.0 |
| C | 40000 | 5.04 | 0 | 1 | 30 | 14 | 28800 | 4321 | 1 | 1 | 5000 | 36 | RENT | Not Verified | debt_consolidation | individual | 40 | 28.800 | 4.321 | 5.0 |
| D | 40000 | 21.15 | 0 | 4 | 31 | 10 | 24193 | 16000 | 0 | 0 | 2000 | 36 | RENT | Source Verified | other | individual | 40 | 24.193 | 16.000 | 2.0 |
| A | 30000 | 10.16 | 0 | 0 | 4 | 4 | 25400 | 4997 | 1 | 0 | 21600 | 36 | RENT | Not Verified | debt_consolidation | individual | 30 | 25.400 | 4.997 | 21.6 |
| C | 35000 | 57.96 | 0 | 7 | 22 | 16 | 69839 | 52722 | 0 | 0 | 23000 | 36 | RENT | Verified | credit_card | joint | 35 | 69.839 | 52.722 | 23.0 |
| A | 34000 | 6.46 | 1 | 6 | 32 | 12 | 42100 | 3898 | 0 | 0 | 5000 | 36 | OWN | Not Verified | other | individual | 34 | 42.100 | 3.898 | 5.0 |
dist_ordinal <- data_ordinal %>%
dplyr::count(grade) %>%
dplyr::mutate(Persen = scales::percent(n / sum(n)))
knitr::kable(dist_ordinal, caption = "Distribusi Grade Pinjaman")| grade | n | Persen |
|---|---|---|
| A | 2454 | 24.60% |
| B | 3032 | 30.39% |
| C | 2649 | 26.55% |
| D | 1438 | 14.41% |
| E | 334 | 3.35% |
| F | 57 | 0.57% |
| G | 12 | 0.12% |
ringkasan_ordinal <- data_ordinal %>%
dplyr::summarise(
Rata_rata_income_k = mean(annual_income_k),
Median_income_k = median(annual_income_k),
Rata_rata_dti = mean(debt_to_income),
Median_dti = median(debt_to_income),
Rata_rata_loan_amount_k = mean(loan_amount_k)
)
knitr::kable(ringkasan_ordinal, caption = "Ringkasan Prediktor Utama Data Ordinal")| Rata_rata_income_k | Median_income_k | Rata_rata_dti | Median_dti | Rata_rata_loan_amount_k |
|---|---|---|---|---|
| 79.41274 | 65 | 19.30819 | 17.57 | 16.35753 |
ggplot(data_ordinal, aes(x = grade)) +
geom_bar() +
labs(
title = "Distribusi Grade Pinjaman Lending Club",
x = "Grade",
y = "Jumlah pinjaman"
) +
theme_minimal()Model ordinal dibentuk untuk menjelaskan faktor-faktor yang
berhubungan dengan tingkat grade pinjaman. Model ini menggunakan
spesifikasi MASS::polr() sebagai berikut:
\[ \log\left(\frac{P(Y \leq j)}{P(Y > j)}\right) = \alpha_j - x\beta \]
Dalam penelitian ini, variabel respon adalah grade,
dengan urutan:
\[ A < B < C < D < E < F < G \]
Sehingga bentuk modelnya dapat ditulis sebagai:
\[ \log\left(\frac{P(Y \leq j)}{P(Y > j)}\right) = \alpha_j - \left( \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3 + \cdots + \beta_p X_p \right) \]
Karena model menggunakan bentuk \(\alpha_j - x\beta\), maka koefisien positif menunjukkan penurunan peluang kumulatif berada pada kategori rendah. Dengan kata lain, koefisien positif menunjukkan peningkatan kecenderungan pinjaman masuk ke grade yang lebih tinggi atau risiko yang lebih buruk.
model_ordinal <- MASS::polr(
grade ~ annual_income_k + debt_to_income + delinq_2y + inquiries_last_12m +
total_credit_lines + open_credit_lines + total_credit_limit_k + total_credit_utilized_k +
num_historical_failed_to_pay + public_record_bankrupt + loan_amount_k + term +
homeownership + verified_income + loan_purpose + application_type,
data = data_ordinal,
Hess = TRUE
)
summary(model_ordinal)## Call:
## MASS::polr(formula = grade ~ annual_income_k + debt_to_income +
## delinq_2y + inquiries_last_12m + total_credit_lines + open_credit_lines +
## total_credit_limit_k + total_credit_utilized_k + num_historical_failed_to_pay +
## public_record_bankrupt + loan_amount_k + term + homeownership +
## verified_income + loan_purpose + application_type, data = data_ordinal,
## Hess = TRUE)
##
## Coefficients:
## Value Std. Error t value
## annual_income_k -0.0004366 0.0004111 -1.0622
## debt_to_income 0.0189670 0.0018607 10.1936
## delinq_2y 0.3863916 0.0280135 13.7930
## inquiries_last_12m 0.1206014 0.0080931 14.9018
## total_credit_lines -0.0210112 0.0025525 -8.2315
## open_credit_lines 0.0082993 0.0049402 1.6800
## total_credit_limit_k -0.0024280 0.0001605 -15.1249
## total_credit_utilized_k 0.0045864 0.0004819 9.5181
## num_historical_failed_to_pay 0.0836537 0.0280557 2.9817
## public_record_bankrupt 0.1050426 0.0611649 1.7174
## loan_amount_k -0.0141142 0.0022054 -6.3999
## term60 1.7053905 0.0457152 37.3046
## homeownershipOWN 0.0399999 0.0596143 0.6710
## homeownershipRENT 0.1695171 0.0485386 3.4924
## verified_incomeSource Verified 0.5204831 0.0434310 11.9841
## verified_incomeVerified 1.1085540 0.0531020 20.8759
## loan_purposecredit_card -0.2174709 0.1237707 -1.7570
## loan_purposedebt_consolidation 0.2336611 0.1206111 1.9373
## loan_purposehome_improvement -0.1360832 0.1372344 -0.9916
## loan_purposehouse -0.5827169 0.1899838 -3.0672
## loan_purposemajor_purchase -0.0925206 0.1567966 -0.5901
## loan_purposemedical 0.0837639 0.1837933 0.4558
## loan_purposemoving -0.0292612 0.2470419 -0.1184
## loan_purposeother 0.0487276 0.1315205 0.3705
## loan_purposerenewable_energy 0.3465701 0.2819415 1.2292
## loan_purposesmall_business 0.3061349 0.1983514 1.5434
## loan_purposevacation 0.7064138 0.2559893 2.7595
## application_typejoint -0.1742241 0.0584236 -2.9821
##
## Intercepts:
## Value Std. Error t value
## A|B -0.4266 0.1338 -3.1890
## B|C 1.2191 0.1342 9.0844
## C|D 2.7940 0.1367 20.4317
## D|E 4.6826 0.1451 32.2696
## E|F 6.5509 0.1823 35.9443
## F|G 8.3210 0.3196 26.0362
##
## Residual Deviance: 26566.23
## AIC: 26634.23
Chunk model-ordinal di atas sudah membangun
model regresi logistik ordinal menggunakan
MASS::polr(). Bentuk hasil estimasinya adalah:
\[ \log\left(\frac{\widehat{P}(grade_i \leq j)}{\widehat{P}(grade_i > j)}\right) = \hat{\alpha}_j - \widehat{\eta_i} \]
Dengan:
\[ \widehat{\eta_i} = \hat{\beta}_1X_{1i} + \hat{\beta}_2X_{2i} + \cdots + \hat{\beta}_pX_{pi} \]
Karena MASS::polr() memakai bentuk
alpha_j - x beta, maka exp(beta) dibaca
sebagai odds menuju grade yang lebih tinggi. Dalam
laporan ini grade lebih tinggi berarti risiko lebih buruk.
\[ \widehat{\eta_i} = - 0.0004\,X_{income} + 0.019\,X_{dti} + 0.3864\,X_{delinq} + 0.1206\,X_{inq} - 0.021\,X_{tcl} + 0.0083\,X_{ocl} - 0.0024\,X_{limit} + 0.0046\,X_{utilized} + 0.0837\,X_{failed} + 0.105\,X_{bankrupt} - 0.0141\,X_{loan} + 1.7054\,X_{term60} + 0.04\,X_{homeownershipOWN} + 0.1695\,X_{homeownershipRENT} + 0.5205\,X_{verifiedincomeSourceVerified} + 1.1086\,X_{verifiedincomeVerified} - 0.2175\,X_{loanpurposecreditcard} + 0.2337\,X_{loanpurposedebtconsolidation} - 0.1361\,X_{loanpurposehomeimprovement} - 0.5827\,X_{loanpurposehouse} - 0.0925\,X_{loanpurposemajorpurchase} + 0.0838\,X_{loanpurposemedical} - 0.0293\,X_{loanpurposemoving} + 0.0487\,X_{loanpurposeother} + 0.3466\,X_{loanpurposerenewableenergy} + 0.3061\,X_{loanpurposesmallbusiness} + 0.7064\,X_{loanpurposevacation} - 0.1742\,X_{applicationtypejoint} \]
Dengan spesifikasi MASS::polr(), persamaan untuk setiap
batas kumulatif adalah:
\[ \log\left(\frac{\widehat{P}(Y_i \leq A\mid B)}{\widehat{P}(Y_i > A\mid B)}\right) = -0.4266 - \widehat{\eta_i} \]
\[ \log\left(\frac{\widehat{P}(Y_i \leq B\mid C)}{\widehat{P}(Y_i > B\mid C)}\right) = 1.2191 - \widehat{\eta_i} \]
\[ \log\left(\frac{\widehat{P}(Y_i \leq C\mid D)}{\widehat{P}(Y_i > C\mid D)}\right) = 2.794 - \widehat{\eta_i} \]
\[ \log\left(\frac{\widehat{P}(Y_i \leq D\mid E)}{\widehat{P}(Y_i > D\mid E)}\right) = 4.6826 - \widehat{\eta_i} \]
\[ \log\left(\frac{\widehat{P}(Y_i \leq E\mid F)}{\widehat{P}(Y_i > E\mid F)}\right) = 6.5509 - \widehat{\eta_i} \]
\[ \log\left(\frac{\widehat{P}(Y_i \leq F\mid G)}{\widehat{P}(Y_i > F\mid G)}\right) = 8.321 - \widehat{\eta_i} \]
Pada tabel berikut,
Odds_Ratio_Higher_Grade = exp(estimate) dibaca sebagai odds
untuk berada pada kategori grade yang lebih tinggi. Ini sesuai dengan
parameterisasi MASS::polr() yang berbentuk:
\[ \operatorname{logit}\{P(Y \leq j)\} = \alpha_j - x\beta \]
Jika ingin membaca odds kumulatif untuk berada pada kategori rendah
atau sama dengan batas tertentu, gunakan
Odds_Ratio_Lower_Cumulative = exp(-estimate).
coef_ordinal <- coef(summary(model_ordinal)) %>%
as.data.frame()
coef_ordinal$term <- rownames(coef_ordinal)
names(coef_ordinal)[1:3] <- c("estimate", "std_error", "t_value")
coef_ordinal <- coef_ordinal %>%
dplyr::mutate(
p_value = 2 * pnorm(abs(t_value), lower.tail = FALSE),
Odds_Ratio_Higher_Grade = exp(estimate),
Odds_Ratio_Lower_Cumulative = exp(-estimate),
Jenis = ifelse(stringr::str_detect(term, "\\|"), "Cutpoint", "Prediktor"),
Variabel_Mudah = purrr::map_chr(term, label_ordinal),
Keputusan_5persen = ifelse(p_value < 0.05, "Signifikan", "Tidak signifikan")
) %>%
dplyr::relocate(term, Jenis)
knitr::kable(
coef_ordinal %>% dplyr::filter(Jenis == "Prediktor") %>% dplyr::arrange(p_value) %>%
dplyr::select(Variabel_Mudah, term, estimate, std_error, t_value, p_value, Odds_Ratio_Higher_Grade, Odds_Ratio_Lower_Cumulative, Keputusan_5persen) %>% head(25),
digits = 4,
caption = "Koefisien dan Odds Ratio Regresi Ordinal MASS::polr"
)| Variabel_Mudah | term | estimate | std_error | t_value | p_value | Odds_Ratio_Higher_Grade | Odds_Ratio_Lower_Cumulative | Keputusan_5persen | |
|---|---|---|---|---|---|---|---|---|---|
| term60 | tenor pinjaman: 60 dibanding kategori acuan | term60 | 1.7054 | 0.0457 | 37.3046 | 0.0000 | 5.5035 | 0.1817 | Signifikan |
| verified_incomeVerified | verifikasi pendapatan: Verified dibanding kategori acuan | verified_incomeVerified | 1.1086 | 0.0531 | 20.8759 | 0.0000 | 3.0300 | 0.3300 | Signifikan |
| total_credit_limit_k | total limit kredit (per 1.000 dollar) | total_credit_limit_k | -0.0024 | 0.0002 | -15.1249 | 0.0000 | 0.9976 | 1.0024 | Signifikan |
| inquiries_last_12m | jumlah pemeriksaan kredit 12 bulan terakhir | inquiries_last_12m | 0.1206 | 0.0081 | 14.9018 | 0.0000 | 1.1282 | 0.8864 | Signifikan |
| delinq_2y | jumlah keterlambatan 2 tahun terakhir | delinq_2y | 0.3864 | 0.0280 | 13.7930 | 0.0000 | 1.4717 | 0.6795 | Signifikan |
| verified_incomeSource Verified | verifikasi pendapatan: Source Verified dibanding kategori acuan | verified_incomeSource Verified | 0.5205 | 0.0434 | 11.9841 | 0.0000 | 1.6828 | 0.5942 | Signifikan |
| debt_to_income | rasio utang terhadap pendapatan | debt_to_income | 0.0190 | 0.0019 | 10.1936 | 0.0000 | 1.0191 | 0.9812 | Signifikan |
| total_credit_utilized_k | total kredit yang digunakan (per 1.000 dollar) | total_credit_utilized_k | 0.0046 | 0.0005 | 9.5181 | 0.0000 | 1.0046 | 0.9954 | Signifikan |
| total_credit_lines | total riwayat fasilitas kredit | total_credit_lines | -0.0210 | 0.0026 | -8.2315 | 0.0000 | 0.9792 | 1.0212 | Signifikan |
| loan_amount_k | jumlah pinjaman (per 1.000 dollar) | loan_amount_k | -0.0141 | 0.0022 | -6.3999 | 0.0000 | 0.9860 | 1.0142 | Signifikan |
| homeownershipRENT | kepemilikan rumah: RENT dibanding kategori acuan | homeownershipRENT | 0.1695 | 0.0485 | 3.4924 | 0.0005 | 1.1847 | 0.8441 | Signifikan |
| loan_purposehouse | tujuan pinjaman: house dibanding kategori acuan | loan_purposehouse | -0.5827 | 0.1900 | -3.0672 | 0.0022 | 0.5584 | 1.7909 | Signifikan |
| application_typejoint | jenis aplikasi: joint dibanding kategori acuan | application_typejoint | -0.1742 | 0.0584 | -2.9821 | 0.0029 | 0.8401 | 1.1903 | Signifikan |
| num_historical_failed_to_pay | riwayat gagal bayar sebelumnya | num_historical_failed_to_pay | 0.0837 | 0.0281 | 2.9817 | 0.0029 | 1.0873 | 0.9197 | Signifikan |
| loan_purposevacation | tujuan pinjaman: vacation dibanding kategori acuan | loan_purposevacation | 0.7064 | 0.2560 | 2.7595 | 0.0058 | 2.0267 | 0.4934 | Signifikan |
| loan_purposedebt_consolidation | tujuan pinjaman: debt_consolidation dibanding kategori acuan | loan_purposedebt_consolidation | 0.2337 | 0.1206 | 1.9373 | 0.0527 | 1.2632 | 0.7916 | Tidak signifikan |
| loan_purposecredit_card | tujuan pinjaman: credit_card dibanding kategori acuan | loan_purposecredit_card | -0.2175 | 0.1238 | -1.7570 | 0.0789 | 0.8046 | 1.2429 | Tidak signifikan |
| public_record_bankrupt | catatan kebangkrutan publik | public_record_bankrupt | 0.1050 | 0.0612 | 1.7174 | 0.0859 | 1.1108 | 0.9003 | Tidak signifikan |
| open_credit_lines | jumlah fasilitas kredit yang masih terbuka | open_credit_lines | 0.0083 | 0.0049 | 1.6800 | 0.0930 | 1.0083 | 0.9917 | Tidak signifikan |
| loan_purposesmall_business | tujuan pinjaman: small_business dibanding kategori acuan | loan_purposesmall_business | 0.3061 | 0.1984 | 1.5434 | 0.1227 | 1.3582 | 0.7363 | Tidak signifikan |
| loan_purposerenewable_energy | tujuan pinjaman: renewable_energy dibanding kategori acuan | loan_purposerenewable_energy | 0.3466 | 0.2819 | 1.2292 | 0.2190 | 1.4142 | 0.7071 | Tidak signifikan |
| annual_income_k | pendapatan tahunan (per 1.000 dollar) | annual_income_k | -0.0004 | 0.0004 | -1.0622 | 0.2881 | 0.9996 | 1.0004 | Tidak signifikan |
| loan_purposehome_improvement | tujuan pinjaman: home_improvement dibanding kategori acuan | loan_purposehome_improvement | -0.1361 | 0.1372 | -0.9916 | 0.3214 | 0.8728 | 1.1458 | Tidak signifikan |
| homeownershipOWN | kepemilikan rumah: OWN dibanding kategori acuan | homeownershipOWN | 0.0400 | 0.0596 | 0.6710 | 0.5022 | 1.0408 | 0.9608 | Tidak signifikan |
| loan_purposemajor_purchase | tujuan pinjaman: major_purchase dibanding kategori acuan | loan_purposemajor_purchase | -0.0925 | 0.1568 | -0.5901 | 0.5551 | 0.9116 | 1.0969 | Tidak signifikan |
Pada model ordinal dengan MASS::polr(), nilai
Odds_Ratio_Higher_Grade = exp(\beta) digunakan untuk
membaca kecenderungan menuju grade yang lebih tinggi. Karena grade
diurutkan sebagai:
\[ A < B < C < D < E < F < G \]
maka grade yang lebih tinggi berarti risiko lebih buruk.
Sementara itu, Odds_Ratio_Lower_Cumulative = exp(-\beta)
membaca odds kumulatif untuk berada pada kategori rendah atau sama
dengan batas tertentu, yaitu:
\[ P(Y \leq j) \]
Dalam laporan ini, interpretasi substantif difokuskan pada
Odds_Ratio_Higher_Grade.
pred_ordinal <- predict(model_ordinal, newdata = data_ordinal, type = "class")
grade_levels <- levels(data_ordinal$grade)
pred_ordinal_f <- factor(as.character(pred_ordinal), levels = grade_levels, ordered = TRUE)
aktual_ordinal_f <- factor(as.character(data_ordinal$grade), levels = grade_levels, ordered = TRUE)
conf_ordinal <- table(Prediksi = pred_ordinal_f, Aktual = aktual_ordinal_f)
conf_ordinal## Aktual
## Prediksi A B C D E F G
## A 1167 631 243 82 9 1 0
## B 1118 1485 1120 458 63 4 1
## C 164 805 1024 587 148 27 8
## D 4 107 258 306 111 24 3
## E 1 2 3 5 3 1 0
## F 0 0 1 0 0 0 0
## G 0 2 0 0 0 0 0
akurasi_ordinal <- mean(as.character(pred_ordinal_f) == as.character(aktual_ordinal_f), na.rm = TRUE)
akurasi_ordinal## [1] 0.3994587
## [1] 26634.23
prob_ordinal <- predict(model_ordinal, type = "probs")
knitr::kable(head(prob_ordinal, 6), digits = 4, caption = "Cuplikan Prediksi Probabilitas untuk Model Ordinal")| A | B | C | D | E | F | G |
|---|---|---|---|---|---|---|
| 0.0341 | 0.1207 | 0.3147 | 0.3845 | 0.1203 | 0.0212 | 0.0045 |
| 0.3584 | 0.3849 | 0.1900 | 0.0560 | 0.0090 | 0.0014 | 0.0003 |
| 0.1901 | 0.3588 | 0.3057 | 0.1203 | 0.0211 | 0.0033 | 0.0007 |
| 0.3321 | 0.3884 | 0.2051 | 0.0623 | 0.0101 | 0.0016 | 0.0003 |
| 0.0654 | 0.2008 | 0.3705 | 0.2838 | 0.0663 | 0.0109 | 0.0023 |
| 0.2679 | 0.3869 | 0.2468 | 0.0822 | 0.0137 | 0.0021 | 0.0004 |
Visualisasi ini digunakan untuk melihat bagaimana peluang
masing-masing grade berubah ketika debt_to_income
meningkat. Variabel lain ditahan pada nilai median atau kategori paling
umum agar hubungan lebih mudah dibaca.
grid_ordinal <- data.frame(
annual_income_k = median(data_ordinal$annual_income_k, na.rm = TRUE),
debt_to_income = seq(
quantile(data_ordinal$debt_to_income, 0.05, na.rm = TRUE),
quantile(data_ordinal$debt_to_income, 0.95, na.rm = TRUE),
length.out = 120
),
delinq_2y = median(data_ordinal$delinq_2y, na.rm = TRUE),
inquiries_last_12m = median(data_ordinal$inquiries_last_12m, na.rm = TRUE),
total_credit_lines = median(data_ordinal$total_credit_lines, na.rm = TRUE),
open_credit_lines = median(data_ordinal$open_credit_lines, na.rm = TRUE),
total_credit_limit_k = median(data_ordinal$total_credit_limit_k, na.rm = TRUE),
total_credit_utilized_k = median(data_ordinal$total_credit_utilized_k, na.rm = TRUE),
num_historical_failed_to_pay = median(data_ordinal$num_historical_failed_to_pay, na.rm = TRUE),
public_record_bankrupt = median(data_ordinal$public_record_bankrupt, na.rm = TRUE),
loan_amount_k = median(data_ordinal$loan_amount_k, na.rm = TRUE),
term = factor(modus(data_ordinal$term), levels = levels(data_ordinal$term)),
homeownership = factor(modus(data_ordinal$homeownership), levels = levels(data_ordinal$homeownership)),
verified_income = factor(modus(data_ordinal$verified_income), levels = levels(data_ordinal$verified_income)),
loan_purpose = factor(modus(data_ordinal$loan_purpose), levels = levels(data_ordinal$loan_purpose)),
application_type = factor(modus(data_ordinal$application_type), levels = levels(data_ordinal$application_type))
)
prob_grid_ordinal <- predict(
model_ordinal,
newdata = grid_ordinal,
type = "probs"
)
plot_prob_ordinal <- grid_ordinal %>%
dplyr::bind_cols(as.data.frame(prob_grid_ordinal)) %>%
tidyr::pivot_longer(
cols = levels(data_ordinal$grade),
names_to = "grade",
values_to = "Probabilitas"
)
ggplot(
plot_prob_ordinal,
aes(x = debt_to_income, y = Probabilitas, color = grade)
) +
geom_line(linewidth = 1.1) +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Prediksi Probabilitas Grade Berdasarkan Debt-to-Income Ratio",
subtitle = "Variabel lain ditahan pada median atau kategori paling umum",
x = "Debt-to-Income Ratio",
y = "Probabilitas prediksi",
color = "Grade"
) +
theme_minimal()Grafik ini membantu melihat perubahan peluang grade ketika rasio
utang terhadap pendapatan meningkat. Jika probabilitas grade tinggi
seperti D, E, F, atau G meningkat ketika debt_to_income
naik, maka model menunjukkan bahwa beban utang yang lebih tinggi
berkaitan dengan risiko kredit yang lebih buruk.
Asumsi utama regresi logistik ordinal adalah proportional odds atau parallel lines. Artinya, pengaruh prediktor diasumsikan sama pada setiap batas kumulatif grade.
Dalam analisis ini, pemeriksaan dilakukan menggunakan fungsi
clm() dan nominal_test() dari paket
ordinal.
cek_proportional_odds <- tryCatch({
model_ordinal_clm_simple <- ordinal::clm(
grade ~ annual_income_k + debt_to_income + delinq_2y +
inquiries_last_12m + loan_amount_k + term,
data = data_ordinal,
link = "logit"
)
print(summary(model_ordinal_clm_simple))
ordinal::nominal_test(model_ordinal_clm_simple)
}, error = function(e) {
cat("Pemeriksaan proportional odds dengan nominal_test() tidak berhasil dijalankan.\n")
cat("Pesan error:", e$message, "\n")
NULL
})## formula:
## grade ~ annual_income_k + debt_to_income + delinq_2y + inquiries_last_12m + loan_amount_k + term
## data: data_ordinal
##
## link threshold nobs logLik AIC niter max.grad cond.H
## logit flexible 9976 -13884.82 27793.64 7(0) 2.65e-11 2.5e+06
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## annual_income_k -0.0039610 0.0004048 -9.784 < 0.0000000000000002 ***
## debt_to_income 0.0157440 0.0015465 10.180 < 0.0000000000000002 ***
## delinq_2y 0.3232870 0.0268864 12.024 < 0.0000000000000002 ***
## inquiries_last_12m 0.1057767 0.0077237 13.695 < 0.0000000000000002 ***
## loan_amount_k -0.0084878 0.0021147 -4.014 0.0000598 ***
## term60 1.5669873 0.0446407 35.102 < 0.0000000000000002 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Threshold coefficients:
## Estimate Std. Error z value
## A|B -0.66176 0.05296 -12.50
## B|C 0.85255 0.05310 16.06
## C|D 2.30485 0.05776 39.90
## D|E 4.09772 0.07433 55.13
## E|F 5.93822 0.13290 44.68
## F|G 7.70270 0.29416 26.18
if (is.null(cek_proportional_odds)) {
cat("Pemeriksaan proportional odds dengan `nominal_test()` tidak berhasil dijalankan secara stabil. Oleh karena itu, pada laporan ini asumsi proportional odds dicatat sebagai keterbatasan analisis. Model ordinal tetap digunakan sebagai model utama karena tujuan analisis adalah memahami hubungan antara karakteristik pinjaman dan tingkat grade risiko.\n")
} else {
hasil_po <- as.data.frame(cek_proportional_odds)
hasil_po$Variabel <- rownames(hasil_po)
kolom_p <- grep("Pr", names(hasil_po), value = TRUE)[1]
if (is.na(kolom_p)) {
cat("Hasil `nominal_test()` berhasil diperoleh, tetapi kolom p-value tidak terdeteksi secara otomatis. Oleh karena itu, interpretasi dilakukan secara deskriptif melalui tabel output uji.\n")
} else {
hasil_po <- hasil_po %>%
dplyr::filter(!is.na(.data[[kolom_p]]))
signif_po <- hasil_po %>%
dplyr::filter(.data[[kolom_p]] < 0.05)
tidak_signif_po <- hasil_po %>%
dplyr::filter(.data[[kolom_p]] >= 0.05)
cat("Pemeriksaan proportional odds dilakukan menggunakan `ordinal::nominal_test()` pada model ordinal sederhana. ")
if (nrow(signif_po) == 0) {
cat("Berdasarkan hasil uji, tidak terdapat prediktor dengan p-value di bawah 0,05. Artinya, tidak ditemukan indikasi kuat bahwa asumsi proportional odds dilanggar pada model pemeriksaan ini. Dengan demikian, penggunaan model ordinal cumulative logit masih dapat diterima sebagai model awal.\n")
} else {
cat("Berdasarkan hasil uji, terdapat ", nrow(signif_po), " prediktor dengan p-value di bawah 0,05, yaitu: ",
paste(signif_po$Variabel, collapse = ", "),
". Hal ini menunjukkan adanya indikasi bahwa efek prediktor tersebut tidak sepenuhnya konstan pada seluruh batas kumulatif grade. Dengan kata lain, asumsi proportional odds berpotensi tidak terpenuhi untuk prediktor tersebut.\n\n", sep = "")
cat("Secara substantif, hasil ini berarti pengaruh beberapa karakteristik peminjam terhadap perpindahan dari grade rendah ke grade tinggi tidak selalu sama pada setiap batas grade. Misalnya, pengaruh suatu prediktor dalam membedakan grade A-B dengan grade C-G dapat berbeda dari pengaruhnya dalam membedakan grade A-D dengan grade E-G.\n")
}
}
}Pemeriksaan proportional odds dilakukan menggunakan
ordinal::nominal_test() pada model ordinal sederhana.
Berdasarkan hasil uji, terdapat 4 prediktor dengan p-value di bawah
0,05, yaitu: delinq_2y, inquiries_last_12m, loan_amount_k, term. Hal ini
menunjukkan adanya indikasi bahwa efek prediktor tersebut tidak
sepenuhnya konstan pada seluruh batas kumulatif grade. Dengan kata lain,
asumsi proportional odds berpotensi tidak terpenuhi untuk prediktor
tersebut.
Secara substantif, hasil ini berarti pengaruh beberapa karakteristik peminjam terhadap perpindahan dari grade rendah ke grade tinggi tidak selalu sama pada setiap batas grade. Misalnya, pengaruh suatu prediktor dalam membedakan grade A-B dengan grade C-G dapat berbeda dari pengaruhnya dalam membedakan grade A-D dengan grade E-G.
if (is.null(cek_proportional_odds)) {
cat("Karena uji proportional odds tidak berhasil dijalankan secara stabil, hasil model ordinal perlu dibaca dengan hati-hati. Keterbatasan ini tidak membatalkan model, tetapi menunjukkan bahwa pemeriksaan asumsi belum dapat disimpulkan secara kuat dari output uji.\n")
} else {
hasil_po <- as.data.frame(cek_proportional_odds)
hasil_po$Variabel <- rownames(hasil_po)
kolom_p <- grep("Pr", names(hasil_po), value = TRUE)[1]
if (!is.na(kolom_p)) {
signif_po <- hasil_po %>%
dplyr::filter(!is.na(.data[[kolom_p]]), .data[[kolom_p]] < 0.05)
if (nrow(signif_po) == 0) {
cat("Kesimpulan pemeriksaan asumsi: tidak ada bukti kuat pelanggaran proportional odds pada taraf 5%. Oleh karena itu, model ordinal `MASS::polr()` tetap layak digunakan sebagai model utama untuk menjelaskan tingkat risiko pinjaman berdasarkan grade.\n")
} else {
cat("Kesimpulan pemeriksaan asumsi: terdapat indikasi pelanggaran proportional odds pada sebagian prediktor. Oleh karena itu, hasil model ordinal tetap dapat digunakan sebagai model awal, tetapi interpretasinya perlu dilakukan dengan hati-hati. Jika analisis ingin dikembangkan lebih lanjut, alternatif yang dapat dipertimbangkan adalah partial proportional odds model, generalized ordered logit model, atau regresi multinomial sebagai pembanding non-ordinal.\n")
}
} else {
cat("Kesimpulan pemeriksaan asumsi belum dapat dibuat secara otomatis karena kolom p-value tidak terdeteksi. Output `nominal_test()` tetap perlu diperiksa secara manual.\n")
}
}Kesimpulan pemeriksaan asumsi: terdapat indikasi pelanggaran proportional odds pada sebagian prediktor. Oleh karena itu, hasil model ordinal tetap dapat digunakan sebagai model awal, tetapi interpretasinya perlu dilakukan dengan hati-hati. Jika analisis ingin dikembangkan lebih lanjut, alternatif yang dapat dipertimbangkan adalah partial proportional odds model, generalized ordered logit model, atau regresi multinomial sebagai pembanding non-ordinal.
sig_ordinal <- coef_ordinal %>%
dplyr::filter(Jenis == "Prediktor", p_value < 0.05) %>%
dplyr::arrange(p_value)
cat("Pada taraf signifikansi 5%, model ordinal menemukan ", nrow(sig_ordinal),
" prediktor yang berhubungan signifikan dengan grade risiko pinjaman.\n\n", sep = "")Pada taraf signifikansi 5%, model ordinal menemukan 15 prediktor yang berhubungan signifikan dengan grade risiko pinjaman.
if (nrow(sig_ordinal) > 0) {
cat("Prediktor paling penting berdasarkan p-value terkecil adalah:\n\n")
top_ordinal <- head(sig_ordinal, 8)
for (i in seq_len(nrow(top_ordinal))) {
row <- top_ordinal[i, ]
arah <- ifelse(row$Odds_Ratio_Higher_Grade > 1,
"meningkatkan kecenderungan pinjaman masuk ke grade risiko yang lebih tinggi, yaitu mendekati G",
"menurunkan kecenderungan pinjaman masuk ke grade risiko yang lebih tinggi")
cat("- **", row$Variabel_Mudah, "** memiliki OR kategori lebih tinggi = ", fmt_num(row$Odds_Ratio_Higher_Grade, 3),
" dan p-value = ", fmt_p(row$p_value), ", sehingga variabel ini ", arah,
", dengan asumsi variabel lain tetap. Dalam parameterisasi `polr`, ini berasal dari model `logit(P(Y <= j)) = alpha_j - x beta`.\n", sep = "")
}
cat("\n")
}Prediktor paling penting berdasarkan p-value terkecil adalah:
polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini
berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini
berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.polr, ini berasal dari model
logit(P(Y <= j)) = alpha_j - x beta.cat("Akurasi klasifikasi model ordinal adalah **", scales::percent(akurasi_ordinal),
"**. AIC model adalah **", fmt_num(AIC_ordinal, 2), "**.\n\n", sep = "")Akurasi klasifikasi model ordinal adalah 40%. AIC model adalah 26,634.23.
cat("**Kesimpulan substantif:** model ordinal menunjukkan faktor-faktor yang membedakan pinjaman berisiko rendah dan tinggi. Karena model menggunakan `MASS::polr` dengan bentuk `logit(P(Y <= j)) = alpha_j - x beta`, maka `exp(beta)` dibaca sebagai odds untuk berada pada kategori grade yang lebih tinggi. Dengan urutan A sampai G, OR kategori lebih tinggi di atas 1 berarti variabel tersebut berkaitan dengan grade risiko lebih buruk, sedangkan OR di bawah 1 berarti berkaitan dengan grade risiko lebih rendah.\n")Kesimpulan substantif: model ordinal menunjukkan
faktor-faktor yang membedakan pinjaman berisiko rendah dan tinggi.
Karena model menggunakan MASS::polr dengan bentuk
logit(P(Y <= j)) = alpha_j - x beta, maka
exp(beta) dibaca sebagai odds untuk berada pada kategori
grade yang lebih tinggi. Dengan urutan A sampai G, OR kategori lebih
tinggi di atas 1 berarti variabel tersebut berkaitan dengan grade risiko
lebih buruk, sedangkan OR di bawah 1 berarti berkaitan dengan grade
risiko lebih rendah.
Tujuan analisis ini adalah mengetahui faktor-faktor yang berhubungan
dengan status pinjaman Prosper. Status pinjaman tidak
diperlakukan sebagai urutan, karena Current,
Completed, Chargedoff, Defaulted,
dan PastDue adalah jenis kondisi pinjaman yang berbeda.
Variabel respon adalah LoanStatus, yang kemudian
dirapikan menjadi LoanStatus_recode.
| Kategori baru | Arti sederhana |
|---|---|
| Completed | Pinjaman sudah selesai dibayar |
| Current | Pinjaman masih berjalan |
| Chargedoff | Pinjaman sudah dianggap macet/rugi |
| Defaulted | Pinjaman gagal bayar |
| PastDue | Pinjaman sedang terlambat bayar |
| Variabel | Peran | Alasan_dipakai |
|---|---|---|
| LoanStatus_recode | Respon | Mewakili status pinjaman Prosper |
| BorrowerAPR | Prediktor | Menggambarkan biaya pinjaman tahunan |
| LoanOriginalAmount | Prediktor | Menggambarkan besar pinjaman awal |
| Term | Prediktor | Menggambarkan tenor pinjaman |
| EmploymentStatus | Prediktor | Menggambarkan kondisi pekerjaan peminjam |
| IncomeRange | Prediktor | Menggambarkan rentang pendapatan peminjam |
| DebtToIncomeRatio | Prediktor | Mengukur beban utang terhadap pendapatan |
| CreditScoreRangeLower | Prediktor | Menggambarkan skor kredit peminjam |
| ListingCategory (numeric) | Prediktor | Menggambarkan kategori tujuan pinjaman |
| StatedMonthlyIncome | Prediktor | Menggambarkan pendapatan bulanan yang dilaporkan |
Variabel seperti LoanCurrentDaysDelinquent,
LoanFirstDefaultedCycleNumber, dan variabel
LP_... tidak digunakan karena muncul setelah pinjaman
berjalan dan terlalu dekat dengan status pinjaman. Variabel seperti ini
dapat menyebabkan data leakage.
data_multinom <- data_multinom_raw %>%
dplyr::rename(
ProsperRating_Alpha = `ProsperRating (Alpha)`,
ListingCategory_numeric = `ListingCategory (numeric)`
) %>%
dplyr::mutate(
LoanStatus_recode = dplyr::case_when(
stringr::str_detect(LoanStatus, "Past Due") ~ "PastDue",
LoanStatus %in% c("Completed", "Current", "Chargedoff", "Defaulted") ~ LoanStatus,
TRUE ~ "Other"
)
) %>%
dplyr::filter(LoanStatus_recode %in% c("Completed", "Current", "Chargedoff", "Defaulted", "PastDue")) %>%
dplyr::mutate(
LoanStatus_recode = relevel(factor(LoanStatus_recode), ref = "Completed"),
Term = factor(Term),
EmploymentStatus = forcats::fct_lump_n(factor(EmploymentStatus), n = 6, other_level = "Other"),
IncomeRange = factor(IncomeRange),
ListingCategory_numeric = factor(ListingCategory_numeric),
LoanOriginalAmount_k = LoanOriginalAmount / 1000,
StatedMonthlyIncome_k = StatedMonthlyIncome / 1000
) %>%
dplyr::select(
LoanStatus_recode, BorrowerAPR, LoanOriginalAmount_k, Term,
EmploymentStatus, IncomeRange, DebtToIncomeRatio, CreditScoreRangeLower,
ListingCategory_numeric, StatedMonthlyIncome_k
) %>%
tidyr::drop_na()
knitr::kable(head(data_multinom, 6), caption = "Cuplikan Data Multinomial Setelah Cleaning")| LoanStatus_recode | BorrowerAPR | LoanOriginalAmount_k | Term | EmploymentStatus | IncomeRange | DebtToIncomeRatio | CreditScoreRangeLower | ListingCategory_numeric | StatedMonthlyIncome_k |
|---|---|---|---|---|---|---|---|---|---|
| Completed | 0.16516 | 9.425 | 36 | Self-employed | $25,000-49,999 | 0.17 | 640 | 0 | 3.083333 |
| Current | 0.12016 | 10.000 | 36 | Employed | $50,000-74,999 | 0.18 | 680 | 2 | 6.125000 |
| Completed | 0.28269 | 3.001 | 36 | Not available | Not displayed | 0.06 | 480 | 0 | 2.083333 |
| Current | 0.12528 | 10.000 | 36 | Employed | $25,000-49,999 | 0.15 | 800 | 16 | 2.875000 |
| Current | 0.24614 | 15.000 | 36 | Employed | $100,000+ | 0.26 | 680 | 2 | 9.583333 |
| Current | 0.15425 | 15.000 | 60 | Employed | $100,000+ | 0.36 | 740 | 1 | 8.333333 |
Completed digunakan sebagai kategori acuan. Jadi hasil
model akan membaca status lain dibanding pinjaman yang sudah selesai
dibayar.
dist_multinom <- data_multinom %>%
dplyr::count(LoanStatus_recode) %>%
dplyr::mutate(Persen = scales::percent(n / sum(n)))
knitr::kable(dist_multinom, caption = "Distribusi Loan Status Setelah Recode")| LoanStatus_recode | n | Persen |
|---|---|---|
| Completed | 33917 | 32.9% |
| Chargedoff | 10463 | 10.2% |
| Current | 52478 | 51.0% |
| Defaulted | 4249 | 4.1% |
| PastDue | 1857 | 1.8% |
ringkasan_multinom <- data_multinom %>%
dplyr::summarise(
Rata_rata_APR = mean(BorrowerAPR),
Median_APR = median(BorrowerAPR),
Rata_rata_loan_amount_k = mean(LoanOriginalAmount_k),
Median_loan_amount_k = median(LoanOriginalAmount_k),
Rata_rata_DTI = mean(DebtToIncomeRatio)
)
knitr::kable(ringkasan_multinom, caption = "Ringkasan Prediktor Utama Data Multinomial")| Rata_rata_APR | Median_APR | Rata_rata_loan_amount_k | Median_loan_amount_k | Rata_rata_DTI |
|---|---|---|---|---|
| 0.2166657 | 0.2073 | 8.527668 | 6.6 | 0.2779702 |
ggplot(data_multinom, aes(x = LoanStatus_recode)) +
geom_bar() +
labs(
title = "Distribusi Status Pinjaman Prosper",
x = "Loan Status",
y = "Jumlah pinjaman"
) +
theme_minimal()Model multinomial membandingkan setiap kategori status pinjaman
terhadap kategori acuan Completed. Karena kategori selain
Completed adalah Current,
Chargedoff, Defaulted, dan
PastDue, model membangun empat persamaan logit
sekaligus.
Untuk setiap kategori status \(k\)
selain Completed, bentuk modelnya adalah:
\[ \log\left( \frac{P(Y_i = k)}{P(Y_i = Completed)} \right) = \beta_{0k} + \beta_{1k}X_{1i} + \cdots + \beta_{pk}X_{pi} \]
Artinya, setiap koefisien selalu dibaca relatif terhadap kategori
acuan Completed.
model_multinom <- nnet::multinom(
LoanStatus_recode ~ BorrowerAPR + LoanOriginalAmount_k + Term + EmploymentStatus +
IncomeRange + DebtToIncomeRatio + CreditScoreRangeLower +
ListingCategory_numeric + StatedMonthlyIncome_k,
data = data_multinom,
trace = FALSE,
maxit = 200,
MaxNWts = 10000
)
summary(model_multinom)## Call:
## nnet::multinom(formula = LoanStatus_recode ~ BorrowerAPR + LoanOriginalAmount_k +
## Term + EmploymentStatus + IncomeRange + DebtToIncomeRatio +
## CreditScoreRangeLower + ListingCategory_numeric + StatedMonthlyIncome_k,
## data = data_multinom, trace = FALSE, maxit = 200, MaxNWts = 10000)
##
## Coefficients:
## (Intercept) BorrowerAPR LoanOriginalAmount_k Term36 Term60
## Chargedoff -0.6295027 6.684549 0.06960958 1.543688 1.928403
## Current -9.0123432 -6.171438 0.07133498 4.251528 5.047080
## Defaulted -2.0802445 5.890494 0.08078609 2.288127 2.373327
## PastDue -12.3376523 4.685553 0.08554448 2.849515 3.675825
## EmploymentStatusFull-time EmploymentStatusNot available
## Chargedoff 0.03631025 0.01860717
## Current -3.59344482 19.58240081
## Defaulted 0.67753261 1.04107783
## PastDue -2.82464528 -3.40871471
## EmploymentStatusPart-time EmploymentStatusSelf-employed
## Chargedoff -0.2877912 0.4939120
## Current -4.4946527 -3.2763642
## Defaulted 0.1666370 0.9999379
## PastDue -1.9619289 -27.2650565
## EmploymentStatusOther IncomeRange$1-24,999 IncomeRange$100,000+
## Chargedoff 0.4989151 0.3378266 -0.3613065
## Current 0.3201893 8.8117782 8.6567855
## Defaulted 0.7929610 -0.3501685 -0.1367631
## PastDue 0.1793325 7.0312452 6.7596505
## IncomeRange$25,000-49,999 IncomeRange$50,000-74,999
## Chargedoff 0.2086400 -0.05227022
## Current 8.8280347 8.82613270
## Defaulted -0.1517018 -0.21522729
## PastDue 6.9924241 6.86682065
## IncomeRange$75,000-99,999 IncomeRangeNot displayed
## Chargedoff -0.1699349 -0.3250956
## Current 8.7365207 -23.4326132
## Defaulted -0.2175515 -0.1434447
## PastDue 6.7891067 -2.7346498
## IncomeRangeNot employed DebtToIncomeRatio CreditScoreRangeLower
## Chargedoff -0.2673620 0.04322748 -0.005686828
## Current -29.4389818 0.32910003 -0.010713248
## Defaulted -0.8653875 0.07493480 -0.005769732
## PastDue -44.0422496 0.27404756 -0.008016763
## ListingCategory_numeric1 ListingCategory_numeric2
## Chargedoff -0.5708640 -0.4102319
## Current 5.5951129 5.3244649
## Defaulted -0.6890061 -0.8126204
## PastDue 4.1759018 4.4049329
## ListingCategory_numeric3 ListingCategory_numeric4
## Chargedoff -0.1091526 -0.09164516
## Current 4.9849066 -19.31941238
## Defaulted -0.4161347 -0.32889454
## PastDue 4.2382908 -145.72917520
## ListingCategory_numeric5 ListingCategory_numeric6
## Chargedoff -0.5295448 -0.7036627
## Current -27.2799821 4.9521401
## Defaulted -0.8701874 -1.0376967
## PastDue -26.1512089 3.8806954
## ListingCategory_numeric7 ListingCategory_numeric8
## Chargedoff -0.5496470 0.1609483
## Current 4.9726225 6.0041333
## Defaulted -0.8979768 -19.8076383
## PastDue 3.8253652 4.7507223
## ListingCategory_numeric9 ListingCategory_numeric10
## Chargedoff -1.148400 -0.368280
## Current 4.984668 5.251689
## Defaulted -14.410266 -1.004847
## PastDue 3.949680 4.303154
## ListingCategory_numeric11 ListingCategory_numeric12
## Chargedoff -1.793221 0.4877906
## Current 5.413090 5.4237962
## Defaulted -21.741148 0.1127084
## PastDue 4.359630 4.8957947
## ListingCategory_numeric13 ListingCategory_numeric14
## Chargedoff 0.1619101 -0.3259399
## Current 5.9994923 5.8951513
## Defaulted -0.6488704 -0.8857277
## PastDue 4.8947403 5.1462304
## ListingCategory_numeric15 ListingCategory_numeric16
## Chargedoff 0.03404026 -2.787390
## Current 6.07860353 5.341409
## Defaulted -0.71102302 -1.981023
## PastDue 5.31452702 4.129824
## ListingCategory_numeric17 ListingCategory_numeric18
## Chargedoff -16.8872324 -0.3701332
## Current 4.9597574 6.0569545
## Defaulted -0.7242184 -1.1094231
## PastDue 3.3796574 4.8894867
## ListingCategory_numeric19 ListingCategory_numeric20
## Chargedoff -0.2054259 -0.5058006
## Current 6.0258047 5.8110789
## Defaulted -0.9403849 -1.0029376
## PastDue 4.7436539 4.3776057
## StatedMonthlyIncome_k
## Chargedoff -0.007556906
## Current -0.002472433
## Defaulted -0.062486512
## PastDue -0.013091727
##
## Std. Errors:
## (Intercept) BorrowerAPR LoanOriginalAmount_k Term36 Term60
## Chargedoff 0.045536970 0.037083609 0.002590117 0.03231556 0.03709095
## Current 0.042940975 0.050384682 0.002148251 0.02868112 0.02991584
## Defaulted 0.025610152 0.017306644 0.003441570 0.04344827 0.04479088
## PastDue 0.004453529 0.004306967 0.004991918 0.02952604 0.02885220
## EmploymentStatusFull-time EmploymentStatusNot available
## Chargedoff 0.026669563 0.02018490998192
## Current 0.032502948 0.00000010584371
## Defaulted 0.040883021 0.02267829817536
## PastDue 0.006324081 0.00000000312831
## EmploymentStatusPart-time EmploymentStatusSelf-employed
## Chargedoff 0.073529020 0.06388159859828143605
## Current 0.002106384 0.00387143576458124196
## Defaulted 0.016589231 0.02788475866400276504
## PastDue 0.001314815 0.00000000000001235172
## EmploymentStatusOther IncomeRange$1-24,999 IncomeRange$100,000+
## Chargedoff 0.05829488 0.03983956 0.04657958
## Current 0.04134132 0.03579038 0.02876603
## Defaulted 0.02005086 0.06382447 0.06673275
## PastDue 0.02078589 0.03965622 0.04205807
## IncomeRange$25,000-49,999 IncomeRange$50,000-74,999
## Chargedoff 0.02522149 0.02543147
## Current 0.02005919 0.01989183
## Defaulted 0.04027661 0.03782352
## PastDue 0.04931018 0.04641457
## IncomeRange$75,000-99,999 IncomeRangeNot displayed
## Chargedoff 0.03377200 0.020756548914746
## Current 0.02424256 0.000000105843708
## Defaulted 0.05014490 0.022853289120219
## PastDue 0.05373256 0.000000004784348
## IncomeRangeNot employed DebtToIncomeRatio
## Chargedoff 0.0036259403988203055789474316128 0.01663586
## Current 0.0000000000000000085881086399226 0.03016698
## Defaulted 0.0015947819525250392889981210232 0.01896800
## PastDue 0.0000000000000000000000001404215 0.05639278
## CreditScoreRangeLower ListingCategory_numeric1
## Chargedoff 0.0001471156 0.02873817
## Current 0.0001393542 0.02356747
## Defaulted 0.0001432285 0.04045566
## PastDue 0.0001145706 0.04461606
## ListingCategory_numeric2 ListingCategory_numeric3
## Chargedoff 0.05006704 0.04684950
## Current 0.03561136 0.04099614
## Defaulted 0.06018821 0.06931139
## PastDue 0.06930417 0.06522677
## ListingCategory_numeric4
## Chargedoff 0.05616956550329447322988940527466183993965387344360351562500000000000000000
## Current 0.00000000000106822452679283688714313022005697462191164959222078323364257812
## Defaulted 0.07526216027288142040863050397092592902481555938720703125000000000000000000
## PastDue 0.00000000000000000000000000000000000000000000000000000000000000000001973953
## ListingCategory_numeric5 ListingCategory_numeric6
## Chargedoff 0.02588308410529137348899 0.071878564
## Current 0.00000000000000005055312 0.052408358
## Defaulted 0.00594903836636222552170 0.009998349
## PastDue 0.00000000000000007009299 0.010097548
## ListingCategory_numeric7 ListingCategory_numeric8
## Chargedoff 0.04065510 0.001102603846008551
## Current 0.03185993 0.002186677187282552
## Defaulted 0.06607299 0.000000000000712633
## PastDue 0.07005652 0.000546422384865483
## ListingCategory_numeric9 ListingCategory_numeric10
## Chargedoff 0.0002448132412289 0.0006498580
## Current 0.0012111145759105 0.0012244402
## Defaulted 0.0000000001615604 0.0001227801
## PastDue 0.0002086859400089 0.0002965393
## ListingCategory_numeric11 ListingCategory_numeric12
## Chargedoff 0.0002922166267297219 0.0004505171
## Current 0.0028446576926797317 0.0006599993
## Defaulted 0.0000000000001831248 0.0001282290
## PastDue 0.0006493307834530542 0.0001941926
## ListingCategory_numeric13 ListingCategory_numeric14
## Chargedoff 0.056033285 0.016831564
## Current 0.051702952 0.076020967
## Defaulted 0.004037303 0.001839924
## PastDue 0.026698277 0.018723003
## ListingCategory_numeric15 ListingCategory_numeric16
## Chargedoff 0.021330744 0.0001996018
## Current 0.055934511 0.0056386055
## Defaulted 0.001958656 0.0001317935
## PastDue 0.016634871 0.0009508215
## ListingCategory_numeric17 ListingCategory_numeric18
## Chargedoff 0.00000000003706055 0.019576242
## Current 0.00065983728541946 0.079580967
## Defaulted 0.00013859277502570 0.001717409
## PastDue 0.00011865885701263 0.014504357
## ListingCategory_numeric19 ListingCategory_numeric20
## Chargedoff 0.023230141 0.020786823
## Current 0.078774850 0.081056264
## Defaulted 0.001881095 0.002258808
## PastDue 0.010945065 0.011165208
## StatedMonthlyIncome_k
## Chargedoff 0.004694496
## Current 0.002150989
## Defaulted 0.009234341
## PastDue 0.008540678
##
## Residual Deviance: 158451.7
## AIC: 158763.7
Untuk kategori Chargedoff dibanding
Completed:
\[ \log\left(\frac{\widehat{P}(Y_i=\mathrm{Chargedoff})}{\widehat{P}(Y_i=\mathrm{Completed})}\right) = -0.6295 + 6.6845\,\mathrm{BorrowerAPR} + 0.0696\,\mathrm{LoanAmount_k} + 1.5437\,\mathrm{Term36} + 1.9284\,\mathrm{Term60} + 0.0363\,\mathrm{EmploymentStatusFulltime} + 0.0186\,\mathrm{EmploymentStatusNotavailable} - 0.2878\,\mathrm{EmploymentStatusParttime} + 0.4939\,\mathrm{EmploymentStatusSelfemployed} + 0.4989\,\mathrm{EmploymentStatusOther} + 0.3378\,\mathrm{IncomeRange124999} - 0.3613\,\mathrm{IncomeRange100000} + 0.2086\,\mathrm{IncomeRange2500049999} - 0.0523\,\mathrm{IncomeRange5000074999} - 0.1699\,\mathrm{IncomeRange7500099999} - 0.3251\,\mathrm{IncomeRangeNotdisplayed} - 0.2674\,\mathrm{IncomeRangeNotemployed} + 0.0432\,\mathrm{DTI} - 0.0057\,\mathrm{CreditScore} - 0.5709\,\mathrm{ListingCategory_numeric1} - 0.4102\,\mathrm{ListingCategory_numeric2} - 0.1092\,\mathrm{ListingCategory_numeric3} - 0.0916\,\mathrm{ListingCategory_numeric4} - 0.5295\,\mathrm{ListingCategory_numeric5} - 0.7037\,\mathrm{ListingCategory_numeric6} - 0.5496\,\mathrm{ListingCategory_numeric7} + 0.1609\,\mathrm{ListingCategory_numeric8} - 1.1484\,\mathrm{ListingCategory_numeric9} - 0.3683\,\mathrm{ListingCategory_numeric10} - 1.7932\,\mathrm{ListingCategory_numeric11} + 0.4878\,\mathrm{ListingCategory_numeric12} + 0.1619\,\mathrm{ListingCategory_numeric13} - 0.3259\,\mathrm{ListingCategory_numeric14} + 0.034\,\mathrm{ListingCategory_numeric15} - 2.7874\,\mathrm{ListingCategory_numeric16} - 16.8872\,\mathrm{ListingCategory_numeric17} - 0.3701\,\mathrm{ListingCategory_numeric18} - 0.2054\,\mathrm{ListingCategory_numeric19} - 0.5058\,\mathrm{ListingCategory_numeric20} - 0.0076\,\mathrm{Income_k} \]
Untuk kategori Current dibanding
Completed:
\[ \log\left(\frac{\widehat{P}(Y_i=\mathrm{Current})}{\widehat{P}(Y_i=\mathrm{Completed})}\right) = -9.0123 - 6.1714\,\mathrm{BorrowerAPR} + 0.0713\,\mathrm{LoanAmount_k} + 4.2515\,\mathrm{Term36} + 5.0471\,\mathrm{Term60} - 3.5934\,\mathrm{EmploymentStatusFulltime} + 19.5824\,\mathrm{EmploymentStatusNotavailable} - 4.4947\,\mathrm{EmploymentStatusParttime} - 3.2764\,\mathrm{EmploymentStatusSelfemployed} + 0.3202\,\mathrm{EmploymentStatusOther} + 8.8118\,\mathrm{IncomeRange124999} + 8.6568\,\mathrm{IncomeRange100000} + 8.828\,\mathrm{IncomeRange2500049999} + 8.8261\,\mathrm{IncomeRange5000074999} + 8.7365\,\mathrm{IncomeRange7500099999} - 23.4326\,\mathrm{IncomeRangeNotdisplayed} - 29.439\,\mathrm{IncomeRangeNotemployed} + 0.3291\,\mathrm{DTI} - 0.0107\,\mathrm{CreditScore} + 5.5951\,\mathrm{ListingCategory_numeric1} + 5.3245\,\mathrm{ListingCategory_numeric2} + 4.9849\,\mathrm{ListingCategory_numeric3} - 19.3194\,\mathrm{ListingCategory_numeric4} - 27.28\,\mathrm{ListingCategory_numeric5} + 4.9521\,\mathrm{ListingCategory_numeric6} + 4.9726\,\mathrm{ListingCategory_numeric7} + 6.0041\,\mathrm{ListingCategory_numeric8} + 4.9847\,\mathrm{ListingCategory_numeric9} + 5.2517\,\mathrm{ListingCategory_numeric10} + 5.4131\,\mathrm{ListingCategory_numeric11} + 5.4238\,\mathrm{ListingCategory_numeric12} + 5.9995\,\mathrm{ListingCategory_numeric13} + 5.8952\,\mathrm{ListingCategory_numeric14} + 6.0786\,\mathrm{ListingCategory_numeric15} + 5.3414\,\mathrm{ListingCategory_numeric16} + 4.9598\,\mathrm{ListingCategory_numeric17} + 6.057\,\mathrm{ListingCategory_numeric18} + 6.0258\,\mathrm{ListingCategory_numeric19} + 5.8111\,\mathrm{ListingCategory_numeric20} - 0.0025\,\mathrm{Income_k} \]
Untuk kategori Defaulted dibanding
Completed:
\[ \log\left(\frac{\widehat{P}(Y_i=\mathrm{Defaulted})}{\widehat{P}(Y_i=\mathrm{Completed})}\right) = -2.0802 + 5.8905\,\mathrm{BorrowerAPR} + 0.0808\,\mathrm{LoanAmount_k} + 2.2881\,\mathrm{Term36} + 2.3733\,\mathrm{Term60} + 0.6775\,\mathrm{EmploymentStatusFulltime} + 1.0411\,\mathrm{EmploymentStatusNotavailable} + 0.1666\,\mathrm{EmploymentStatusParttime} + 0.9999\,\mathrm{EmploymentStatusSelfemployed} + 0.793\,\mathrm{EmploymentStatusOther} - 0.3502\,\mathrm{IncomeRange124999} - 0.1368\,\mathrm{IncomeRange100000} - 0.1517\,\mathrm{IncomeRange2500049999} - 0.2152\,\mathrm{IncomeRange5000074999} - 0.2176\,\mathrm{IncomeRange7500099999} - 0.1434\,\mathrm{IncomeRangeNotdisplayed} - 0.8654\,\mathrm{IncomeRangeNotemployed} + 0.0749\,\mathrm{DTI} - 0.0058\,\mathrm{CreditScore} - 0.689\,\mathrm{ListingCategory_numeric1} - 0.8126\,\mathrm{ListingCategory_numeric2} - 0.4161\,\mathrm{ListingCategory_numeric3} - 0.3289\,\mathrm{ListingCategory_numeric4} - 0.8702\,\mathrm{ListingCategory_numeric5} - 1.0377\,\mathrm{ListingCategory_numeric6} - 0.898\,\mathrm{ListingCategory_numeric7} - 19.8076\,\mathrm{ListingCategory_numeric8} - 14.4103\,\mathrm{ListingCategory_numeric9} - 1.0048\,\mathrm{ListingCategory_numeric10} - 21.7411\,\mathrm{ListingCategory_numeric11} + 0.1127\,\mathrm{ListingCategory_numeric12} - 0.6489\,\mathrm{ListingCategory_numeric13} - 0.8857\,\mathrm{ListingCategory_numeric14} - 0.711\,\mathrm{ListingCategory_numeric15} - 1.981\,\mathrm{ListingCategory_numeric16} - 0.7242\,\mathrm{ListingCategory_numeric17} - 1.1094\,\mathrm{ListingCategory_numeric18} - 0.9404\,\mathrm{ListingCategory_numeric19} - 1.0029\,\mathrm{ListingCategory_numeric20} - 0.0625\,\mathrm{Income_k} \]
Untuk kategori PastDue dibanding
Completed:
\[ \log\left(\frac{\widehat{P}(Y_i=\mathrm{PastDue})}{\widehat{P}(Y_i=\mathrm{Completed})}\right) = -12.3377 + 4.6856\,\mathrm{BorrowerAPR} + 0.0855\,\mathrm{LoanAmount_k} + 2.8495\,\mathrm{Term36} + 3.6758\,\mathrm{Term60} - 2.8246\,\mathrm{EmploymentStatusFulltime} - 3.4087\,\mathrm{EmploymentStatusNotavailable} - 1.9619\,\mathrm{EmploymentStatusParttime} - 27.2651\,\mathrm{EmploymentStatusSelfemployed} + 0.1793\,\mathrm{EmploymentStatusOther} + 7.0312\,\mathrm{IncomeRange124999} + 6.7597\,\mathrm{IncomeRange100000} + 6.9924\,\mathrm{IncomeRange2500049999} + 6.8668\,\mathrm{IncomeRange5000074999} + 6.7891\,\mathrm{IncomeRange7500099999} - 2.7346\,\mathrm{IncomeRangeNotdisplayed} - 44.0422\,\mathrm{IncomeRangeNotemployed} + 0.274\,\mathrm{DTI} - 0.008\,\mathrm{CreditScore} + 4.1759\,\mathrm{ListingCategory_numeric1} + 4.4049\,\mathrm{ListingCategory_numeric2} + 4.2383\,\mathrm{ListingCategory_numeric3} - 145.7292\,\mathrm{ListingCategory_numeric4} - 26.1512\,\mathrm{ListingCategory_numeric5} + 3.8807\,\mathrm{ListingCategory_numeric6} + 3.8254\,\mathrm{ListingCategory_numeric7} + 4.7507\,\mathrm{ListingCategory_numeric8} + 3.9497\,\mathrm{ListingCategory_numeric9} + 4.3032\,\mathrm{ListingCategory_numeric10} + 4.3596\,\mathrm{ListingCategory_numeric11} + 4.8958\,\mathrm{ListingCategory_numeric12} + 4.8947\,\mathrm{ListingCategory_numeric13} + 5.1462\,\mathrm{ListingCategory_numeric14} + 5.3145\,\mathrm{ListingCategory_numeric15} + 4.1298\,\mathrm{ListingCategory_numeric16} + 3.3797\,\mathrm{ListingCategory_numeric17} + 4.8895\,\mathrm{ListingCategory_numeric18} + 4.7437\,\mathrm{ListingCategory_numeric19} + 4.3776\,\mathrm{ListingCategory_numeric20} - 0.0131\,\mathrm{Income_k} \]
Chunk model-multinomial di atas sudah membangun
model regresi logistik multinomial menggunakan
nnet::multinom(). Persamaan logit yang dibentuk adalah
sebagai berikut.
Untuk kategori Chargedoff dibanding
Completed:
\[ \log\left(\frac{P(Y=\mathrm{Chargedoff})}{P(Y=\mathrm{Completed})}\right) = \beta_{0,\mathrm{Chargedoff}} + \beta_{1,\mathrm{Chargedoff}}\mathrm{BorrowerAPR} + \cdots + \beta_{p,\mathrm{Chargedoff}}X_p \]
Untuk kategori Current dibanding
Completed:
\[ \log\left(\frac{P(Y=\mathrm{Current})}{P(Y=\mathrm{Completed})}\right) = \beta_{0,\mathrm{Current}} + \beta_{1,\mathrm{Current}}\mathrm{BorrowerAPR} + \cdots + \beta_{p,\mathrm{Current}}X_p \]
Untuk kategori Defaulted dibanding
Completed:
\[ \log\left(\frac{P(Y=\mathrm{Defaulted})}{P(Y=\mathrm{Completed})}\right) = \beta_{0,\mathrm{Defaulted}} + \beta_{1,\mathrm{Defaulted}}\mathrm{BorrowerAPR} + \cdots + \beta_{p,\mathrm{Defaulted}}X_p \]
Untuk kategori PastDue dibanding
Completed:
\[ \log\left(\frac{P(Y=\mathrm{PastDue})}{P(Y=\mathrm{Completed})}\right) = \beta_{0,\mathrm{PastDue}} + \beta_{1,\mathrm{PastDue}}\mathrm{BorrowerAPR} + \cdots + \beta_{p,\mathrm{PastDue}}X_p \]
summary_multinom <- summary(model_multinom)
coef_multinom <- summary_multinom$coefficients
se_multinom <- summary_multinom$standard.errors
multinom_table <- purrr::map_dfr(rownames(coef_multinom), function(kelas) {
tibble::tibble(
Kategori = kelas,
term = colnames(coef_multinom),
estimate = as.numeric(coef_multinom[kelas, ]),
std_error = as.numeric(se_multinom[kelas, ])
)
}) %>%
dplyr::mutate(
z_value = estimate / std_error,
p_value = 2 * pnorm(abs(z_value), lower.tail = FALSE),
Relative_Risk_Ratio = exp(estimate),
Variabel_Mudah = purrr::map_chr(term, label_multinom),
Keputusan_5persen = ifelse(p_value < 0.05, "Signifikan", "Tidak signifikan")
) %>%
dplyr::arrange(Kategori, p_value)
knitr::kable(
multinom_table %>% dplyr::select(Kategori, Variabel_Mudah, term, estimate, std_error, z_value, p_value, Relative_Risk_Ratio, Keputusan_5persen) %>% head(35),
digits = 4,
caption = "Koefisien dan Relative Risk Ratio Regresi Multinomial"
)| Kategori | Variabel_Mudah | term | estimate | std_error | z_value | p_value | Relative_Risk_Ratio | Keputusan_5persen |
|---|---|---|---|---|---|---|---|---|
| Chargedoff | APR/biaya pinjaman tahunan | BorrowerAPR | 6.6845 | 0.0371 | 180.2562 | 0.0000 | 799.9501 | Signifikan |
| Chargedoff | tenor pinjaman: 36 bulan dibanding kategori acuan | Term36 | 1.5437 | 0.0323 | 47.7692 | 0.0000 | 4.6818 | Signifikan |
| Chargedoff | tenor pinjaman: 60 bulan dibanding kategori acuan | Term60 | 1.9284 | 0.0371 | 51.9912 | 0.0000 | 6.8785 | Signifikan |
| Chargedoff | rentang pendapatan: Not employed dibanding kategori acuan | IncomeRangeNot employed | -0.2674 | 0.0036 | -73.7359 | 0.0000 | 0.7654 | Signifikan |
| Chargedoff | batas bawah skor kredit | CreditScoreRangeLower | -0.0057 | 0.0001 | -38.6555 | 0.0000 | 0.9943 | Signifikan |
| Chargedoff | kategori tujuan listing: 8 dibanding kategori acuan | ListingCategory_numeric8 | 0.1609 | 0.0011 | 145.9711 | 0.0000 | 1.1746 | Signifikan |
| Chargedoff | kategori tujuan listing: 9 dibanding kategori acuan | ListingCategory_numeric9 | -1.1484 | 0.0002 | -4690.9212 | 0.0000 | 0.3171 | Signifikan |
| Chargedoff | kategori tujuan listing: 10 dibanding kategori acuan | ListingCategory_numeric10 | -0.3683 | 0.0006 | -566.7084 | 0.0000 | 0.6919 | Signifikan |
| Chargedoff | kategori tujuan listing: 11 dibanding kategori acuan | ListingCategory_numeric11 | -1.7932 | 0.0003 | -6136.6152 | 0.0000 | 0.1664 | Signifikan |
| Chargedoff | kategori tujuan listing: 12 dibanding kategori acuan | ListingCategory_numeric12 | 0.4878 | 0.0005 | 1082.7348 | 0.0000 | 1.6287 | Signifikan |
| Chargedoff | kategori tujuan listing: 16 dibanding kategori acuan | ListingCategory_numeric16 | -2.7874 | 0.0002 | -13964.7523 | 0.0000 | 0.0616 | Signifikan |
| Chargedoff | kategori tujuan listing: 17 dibanding kategori acuan | ListingCategory_numeric17 | -16.8872 | 0.0000 | -455665951831.1931 | 0.0000 | 0.0000 | Signifikan |
| Chargedoff | jumlah pinjaman awal (per 1.000 dollar) | LoanOriginalAmount_k | 0.0696 | 0.0026 | 26.8751 | 0.0000 | 1.0721 | Signifikan |
| Chargedoff | kategori tujuan listing: 20 dibanding kategori acuan | ListingCategory_numeric20 | -0.5058 | 0.0208 | -24.3327 | 0.0000 | 0.6030 | Signifikan |
| Chargedoff | kategori tujuan listing: 5 dibanding kategori acuan | ListingCategory_numeric5 | -0.5295 | 0.0259 | -20.4591 | 0.0000 | 0.5889 | Signifikan |
| Chargedoff | kategori tujuan listing: 1 dibanding kategori acuan | ListingCategory_numeric1 | -0.5709 | 0.0287 | -19.8643 | 0.0000 | 0.5650 | Signifikan |
| Chargedoff | kategori tujuan listing: 14 dibanding kategori acuan | ListingCategory_numeric14 | -0.3259 | 0.0168 | -19.3648 | 0.0000 | 0.7218 | Signifikan |
| Chargedoff | kategori tujuan listing: 18 dibanding kategori acuan | ListingCategory_numeric18 | -0.3701 | 0.0196 | -18.9073 | 0.0000 | 0.6906 | Signifikan |
| Chargedoff | rentang pendapatan: Not displayed dibanding kategori acuan | IncomeRangeNot displayed | -0.3251 | 0.0208 | -15.6623 | 0.0000 | 0.7225 | Signifikan |
| Chargedoff | (Intercept) | (Intercept) | -0.6295 | 0.0455 | -13.8240 | 0.0000 | 0.5329 | Signifikan |
| Chargedoff | kategori tujuan listing: 7 dibanding kategori acuan | ListingCategory_numeric7 | -0.5496 | 0.0407 | -13.5198 | 0.0000 | 0.5772 | Signifikan |
| Chargedoff | kategori tujuan listing: 6 dibanding kategori acuan | ListingCategory_numeric6 | -0.7037 | 0.0719 | -9.7896 | 0.0000 | 0.4948 | Signifikan |
| Chargedoff | kategori tujuan listing: 19 dibanding kategori acuan | ListingCategory_numeric19 | -0.2054 | 0.0232 | -8.8431 | 0.0000 | 0.8143 | Signifikan |
| Chargedoff | status pekerjaan: Other dibanding kategori acuan | EmploymentStatusOther | 0.4989 | 0.0583 | 8.5585 | 0.0000 | 1.6469 | Signifikan |
| Chargedoff | rentang pendapatan: $1-24,999 dibanding kategori acuan | IncomeRange$1-24,999 | 0.3378 | 0.0398 | 8.4797 | 0.0000 | 1.4019 | Signifikan |
| Chargedoff | rentang pendapatan: $25,000-49,999 dibanding kategori acuan | IncomeRange$25,000-49,999 | 0.2086 | 0.0252 | 8.2723 | 0.0000 | 1.2320 | Signifikan |
| Chargedoff | kategori tujuan listing: 2 dibanding kategori acuan | ListingCategory_numeric2 | -0.4102 | 0.0501 | -8.1937 | 0.0000 | 0.6635 | Signifikan |
| Chargedoff | rentang pendapatan: $100,000+ dibanding kategori acuan | IncomeRange$100,000+ | -0.3613 | 0.0466 | -7.7568 | 0.0000 | 0.6968 | Signifikan |
| Chargedoff | status pekerjaan: Self-employed dibanding kategori acuan | EmploymentStatusSelf-employed | 0.4939 | 0.0639 | 7.7317 | 0.0000 | 1.6387 | Signifikan |
| Chargedoff | rentang pendapatan: $75,000-99,999 dibanding kategori acuan | IncomeRange$75,000-99,999 | -0.1699 | 0.0338 | -5.0318 | 0.0000 | 0.8437 | Signifikan |
| Chargedoff | status pekerjaan: Part-time dibanding kategori acuan | EmploymentStatusPart-time | -0.2878 | 0.0735 | -3.9140 | 0.0001 | 0.7499 | Signifikan |
| Chargedoff | kategori tujuan listing: 13 dibanding kategori acuan | ListingCategory_numeric13 | 0.1619 | 0.0560 | 2.8895 | 0.0039 | 1.1758 | Signifikan |
| Chargedoff | rasio utang terhadap pendapatan | DebtToIncomeRatio | 0.0432 | 0.0166 | 2.5985 | 0.0094 | 1.0442 | Signifikan |
| Chargedoff | kategori tujuan listing: 3 dibanding kategori acuan | ListingCategory_numeric3 | -0.1092 | 0.0468 | -2.3299 | 0.0198 | 0.8966 | Signifikan |
| Chargedoff | rentang pendapatan: $50,000-74,999 dibanding kategori acuan | IncomeRange$50,000-74,999 | -0.0523 | 0.0254 | -2.0553 | 0.0398 | 0.9491 | Signifikan |
pred_multinom <- predict(model_multinom, type = "class")
conf_multinom <- table(Prediksi = pred_multinom, Aktual = data_multinom$LoanStatus_recode)
conf_multinom## Aktual
## Prediksi Completed Chargedoff Current Defaulted PastDue
## Completed 22573 6120 2196 3016 151
## Chargedoff 851 986 51 396 9
## Current 10371 3214 50231 586 1697
## Defaulted 122 143 0 251 0
## PastDue 0 0 0 0 0
akurasi_multinom <- mean(as.character(pred_multinom) == as.character(data_multinom$LoanStatus_recode))
akurasi_multinom## [1] 0.719096
## [1] 158763.7
prob_multinom <- predict(model_multinom, type = "probs")
knitr::kable(head(prob_multinom, 6), digits = 4, caption = "Cuplikan Prediksi Probabilitas untuk Model Multinomial")| Completed | Chargedoff | Current | Defaulted | PastDue |
|---|---|---|---|---|
| 0.4768 | 0.3608 | 0.0008 | 0.1616 | 0.0000 |
| 0.1041 | 0.0147 | 0.8677 | 0.0029 | 0.0106 |
| 0.3237 | 0.3121 | 0.0000 | 0.3642 | 0.0000 |
| 0.3010 | 0.0027 | 0.6838 | 0.0017 | 0.0107 |
| 0.1572 | 0.0525 | 0.7393 | 0.0119 | 0.0390 |
| 0.0689 | 0.0112 | 0.9040 | 0.0029 | 0.0131 |
Visualisasi probabilitas prediksi digunakan untuk melihat bagaimana
peluang masing-masing status pinjaman berubah ketika salah satu
prediktor berubah. Dalam analisis ini, prediktor yang digunakan adalah
BorrowerAPR, yaitu biaya pinjaman tahunan. Variabel lain
ditahan pada nilai yang umum atau nilai terbanyak agar perubahan grafik
lebih mudah dibaca.
grid_multinom <- data.frame(
BorrowerAPR = seq(
quantile(data_multinom$BorrowerAPR, 0.05, na.rm = TRUE),
quantile(data_multinom$BorrowerAPR, 0.95, na.rm = TRUE),
length.out = 100
),
LoanOriginalAmount_k = median(data_multinom$LoanOriginalAmount_k, na.rm = TRUE),
Term = factor(modus(data_multinom$Term), levels = levels(data_multinom$Term)),
EmploymentStatus = factor(
modus(data_multinom$EmploymentStatus),
levels = levels(data_multinom$EmploymentStatus)
),
IncomeRange = factor(
modus(data_multinom$IncomeRange),
levels = levels(data_multinom$IncomeRange)
),
DebtToIncomeRatio = median(data_multinom$DebtToIncomeRatio, na.rm = TRUE),
CreditScoreRangeLower = median(data_multinom$CreditScoreRangeLower, na.rm = TRUE),
ListingCategory_numeric = factor(
modus(data_multinom$ListingCategory_numeric),
levels = levels(data_multinom$ListingCategory_numeric)
),
StatedMonthlyIncome_k = median(data_multinom$StatedMonthlyIncome_k, na.rm = TRUE)
)
prob_grid_multinom <- predict(
model_multinom,
newdata = grid_multinom,
type = "probs"
)
plot_prob_multinom <- grid_multinom %>%
dplyr::bind_cols(as.data.frame(prob_grid_multinom)) %>%
tidyr::pivot_longer(
cols = levels(data_multinom$LoanStatus_recode),
names_to = "LoanStatus_recode",
values_to = "Probabilitas"
)
ggplot(
plot_prob_multinom,
aes(x = BorrowerAPR, y = Probabilitas, color = LoanStatus_recode)
) +
geom_line(linewidth = 1.1) +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Prediksi Probabilitas Status Pinjaman Berdasarkan BorrowerAPR",
subtitle = "Variabel lain ditahan pada median atau kategori paling umum",
x = "BorrowerAPR",
y = "Probabilitas prediksi",
color = "Status pinjaman"
) +
theme_minimal()Grafik ini membantu membaca hasil regresi multinomial secara lebih
substantif. Jika probabilitas Chargedoff,
Defaulted, atau PastDue meningkat ketika
BorrowerAPR naik, maka model menunjukkan bahwa pinjaman
dengan biaya pinjaman lebih tinggi cenderung memiliki peluang lebih
besar masuk ke status bermasalah. Sebaliknya, jika probabilitas
Completed menurun ketika BorrowerAPR naik,
maka pinjaman dengan APR lebih tinggi cenderung lebih kecil peluangnya
untuk selesai dibayar.
Pada analisis ini, uji goodness-of-fit devians \(G^2\) tidak digunakan sebagai evaluasi
utama karena data Prosper berbentuk data individu, yaitu satu baris
untuk satu pinjaman, serta memiliki beberapa prediktor kontinu seperti
BorrowerAPR, DebtToIncomeRatio,
LoanOriginalAmount_k, dan
CreditScoreRangeLower. Uji \(G^2\) lebih cocok digunakan pada data
berbentuk grouped data atau tabel frekuensi, yaitu ketika satu baris
mewakili satu kelompok dan respons ditampilkan sebagai jumlah atau
frekuensi kategori.
Oleh karena itu, evaluasi model multinomial dalam laporan ini difokuskan pada koefisien model, relative risk ratio, AIC, prediksi probabilitas, dan confusion matrix.
Regresi logistik multinomial memiliki asumsi Independence of
Irrelevant Alternatives atau IIA. Secara sederhana, asumsi ini
menyatakan bahwa perbandingan peluang antara dua kategori status
pinjaman tidak berubah secara drastis hanya karena kategori lain
ditambahkan atau dihapus. Dalam konteks Prosper, asumsi ini perlu
dicatat sebagai keterbatasan karena beberapa kategori seperti
Chargedoff, Defaulted, dan
PastDue sama-sama menggambarkan kondisi pinjaman yang
kurang baik. Untuk tugas ini, asumsi IIA dicatat sebagai keterbatasan,
bukan diuji secara mendalam.
sig_multi <- multinom_table %>%
dplyr::filter(term != "(Intercept)", p_value < 0.05) %>%
dplyr::arrange(Kategori, p_value)
cat("Pada taraf signifikansi 5%, model multinomial menemukan ", nrow(sig_multi),
" kombinasi prediktor-kategori yang signifikan. Semua interpretasi dibandingkan terhadap kategori acuan `Completed`.\n\n", sep = "")Pada taraf signifikansi 5%, model multinomial menemukan 149 kombinasi
prediktor-kategori yang signifikan. Semua interpretasi dibandingkan
terhadap kategori acuan Completed.
if (nrow(sig_multi) > 0) {
for (kelas in unique(sig_multi$Kategori)) {
cat("**Status ", kelas, " dibanding Completed**\n\n", sep = "")
top_kelas <- sig_multi %>% dplyr::filter(Kategori == kelas) %>% head(5)
for (i in seq_len(nrow(top_kelas))) {
row <- top_kelas[i, ]
arah <- ifelse(row$Relative_Risk_Ratio > 1,
paste0("meningkatkan kecenderungan status ", kelas, " dibanding Completed"),
paste0("menurunkan kecenderungan status ", kelas, " dibanding Completed"))
cat("- **", row$Variabel_Mudah, "** memiliki RRR = ", fmt_num(row$Relative_Risk_Ratio, 3),
" dan p-value = ", fmt_p(row$p_value), ", sehingga variabel ini ", arah,
", dengan asumsi variabel lain tetap.\n", sep = "")
}
cat("\n")
}
}Status Chargedoff dibanding Completed
Status Current dibanding Completed
Status Defaulted dibanding Completed
Status PastDue dibanding Completed
cat("Akurasi klasifikasi model multinomial adalah **", scales::percent(akurasi_multinom),
"**. AIC model adalah **", fmt_num(AIC_multinom, 2), "**.\n\n", sep = "")Akurasi klasifikasi model multinomial adalah 72%. AIC model adalah 158,763.70.
cat("**Kesimpulan substantif:** model multinomial menunjukkan karakteristik pinjaman dan peminjam yang membedakan status pinjaman yang sudah selesai dibayar (`Completed`) dengan status lain seperti masih berjalan, macet, gagal bayar, atau terlambat. Faktor signifikan dengan RRR lebih dari 1 meningkatkan kecenderungan suatu status dibanding `Completed`, sedangkan RRR kurang dari 1 menurunkannya.\n")Kesimpulan substantif: model multinomial menunjukkan
karakteristik pinjaman dan peminjam yang membedakan status pinjaman yang
sudah selesai dibayar (Completed) dengan status lain
seperti masih berjalan, macet, gagal bayar, atau terlambat. Faktor
signifikan dengan RRR lebih dari 1 meningkatkan kecenderungan suatu
status dibanding Completed, sedangkan RRR kurang dari 1
menurunkannya.
Tujuan analisis ini adalah mengetahui faktor-faktor yang berhubungan
dengan jumlah pinjaman SBA 7(a) yang bermasalah. Dalam
data SBA, pinjaman bermasalah diwakili oleh status CHGOFF,
yaitu pinjaman yang sudah dianggap macet atau rugi oleh pemberi
pinjaman.
Data awal SBA berbentuk satu baris per pinjaman. Untuk regresi Poisson, data diubah menjadi satu baris per kelompok pinjaman. Respon akhirnya adalah jumlah pinjaman bermasalah dalam setiap kelompok.
| Variabel | Peran | Alasan_dipakai |
|---|---|---|
| LoanStatus | Dasar pembentukan respon | Dipakai untuk menandai pinjaman PIF atau CHGOFF |
| ChargedOff | Variabel baru | Bernilai 1 jika CHGOFF dan 0 jika PIF |
| ApprovalFY | Prediktor kelompok | Risiko bisa berbeda antar tahun persetujuan pinjaman |
| BorrState | Prediktor kelompok | Risiko bisa berbeda antar lokasi peminjam |
| Sector | Prediktor kelompok | Risiko bisa berbeda antar sektor industri |
| Loan_Size_Band | Prediktor kelompok | Risiko bisa berbeda menurut ukuran pinjaman |
| Term_Band | Prediktor kelompok | Risiko bisa berbeda menurut tenor pinjaman |
| BusinessType | Prediktor kelompok | Risiko bisa berbeda menurut bentuk usaha |
| CollateralInd | Prediktor kelompok | Agunan dapat berkaitan dengan risiko kredit |
| Total_Loan | Offset/exposure | Jumlah pinjaman dalam kelompok, digunakan agar model membaca rate bukan jumlah mentah |
| Jumlah_ChargedOff | Respon Poisson | Jumlah pinjaman CHGOFF dalam setiap kelompok |
| Variabel | Alasan_sederhana |
|---|---|
| BorrName, BorrStreet, BorrZip | Identitas dan alamat peminjam terlalu detail, sulit diinterpretasikan, dan bukan fokus model risiko |
| BankName, BankStreet, BankZip | Identitas bank terlalu detail untuk model awal |
| LocationID, BankFDICNumber, BankNCUANumber | Hanya kode teknis atau nomor identitas |
| PaidInFullDate, ChargeOffDate | Terlalu dekat dengan hasil akhir pinjaman sehingga bisa menyebabkan data leakage |
| GrossChargeOffAmount | Jumlah kerugian baru diketahui setelah pinjaman bermasalah |
| JobsSupported | Bukan fokus utama risiko kredit dan bersifat laporan estimasi dari lender |
| BusinessAge | Secara konsep relevan, tetapi banyak kosong untuk tahun 2010-2017 sehingga tidak dipakai pada model awal |
data_poisson_clean <- data_poisson_raw %>%
dplyr::filter(loanstatus %in% c("P I F", "CHGOFF")) %>%
dplyr::mutate(
ChargedOff = ifelse(loanstatus == "CHGOFF", 1L, 0L),
Sector = stringr::str_sub(as.character(naicscode), 1, 2),
Loan_Size_Band = dplyr::case_when(
grossapproval <= 50000 ~ "Small",
grossapproval <= 350000 ~ "Medium",
grossapproval > 350000 ~ "Large",
TRUE ~ NA_character_
),
Term_Band = dplyr::case_when(
terminmonths <= 60 ~ "Short",
terminmonths <= 120 ~ "Medium",
terminmonths > 120 ~ "Long",
TRUE ~ NA_character_
),
CollateralInd_clean = dplyr::case_when(
tolower(as.character(collateralind)) %in% c("true", "1", "yes", "y") ~ "Collateral",
tolower(as.character(collateralind)) %in% c("false", "0", "no", "n") ~ "No_Collateral",
TRUE ~ NA_character_
),
ApprovalFY = factor(approvalfy),
BorrState = factor(borrstate),
Sector = factor(Sector),
Loan_Size_Band = factor(Loan_Size_Band, levels = c("Small", "Medium", "Large")),
Term_Band = factor(Term_Band, levels = c("Short", "Medium", "Long")),
BusinessType = factor(businesstype),
CollateralInd = factor(CollateralInd_clean)
) %>%
tidyr::drop_na(
ApprovalFY, BorrState, Sector, Loan_Size_Band, Term_Band,
BusinessType, CollateralInd, ChargedOff
)
data_poisson_agg <- data_poisson_clean %>%
dplyr::group_by(
ApprovalFY, BorrState, Sector, Loan_Size_Band,
Term_Band, BusinessType, CollateralInd
) %>%
dplyr::summarise(
Total_Loan = dplyr::n(),
Jumlah_ChargedOff = sum(ChargedOff),
.groups = "drop"
) %>%
dplyr::filter(Total_Loan > 0)
knitr::kable(head(data_poisson_agg, 10), caption = "Cuplikan Data Agregat untuk Regresi Poisson")| ApprovalFY | BorrState | Sector | Loan_Size_Band | Term_Band | BusinessType | CollateralInd | Total_Loan | Jumlah_ChargedOff |
|---|---|---|---|---|---|---|---|---|
| 2010 | AK | 11 | Small | Medium | CORPORATION | No_Collateral | 1 | 0 |
| 2010 | AK | 11 | Small | Long | CORPORATION | Collateral | 1 | 0 |
| 2010 | AK | 11 | Medium | Long | INDIVIDUAL | Collateral | 1 | 0 |
| 2010 | AK | 11 | Large | Short | CORPORATION | No_Collateral | 1 | 1 |
| 2010 | AK | 11 | Large | Medium | CORPORATION | Collateral | 1 | 0 |
| 2010 | AK | 23 | Small | Short | INDIVIDUAL | Collateral | 1 | 0 |
| 2010 | AK | 23 | Small | Medium | CORPORATION | No_Collateral | 2 | 0 |
| 2010 | AK | 23 | Medium | Short | CORPORATION | Collateral | 1 | 0 |
| 2010 | AK | 23 | Medium | Short | INDIVIDUAL | Collateral | 1 | 0 |
| 2010 | AK | 23 | Medium | Medium | INDIVIDUAL | Collateral | 1 | 0 |
ringkasan_poisson <- data_poisson_agg %>%
dplyr::summarise(
Jumlah_kelompok = dplyr::n(),
Total_pinjaman = sum(Total_Loan),
Total_pinjaman_bermasalah = sum(Jumlah_ChargedOff),
Rata_rata_bermasalah_per_kelompok = mean(Jumlah_ChargedOff),
Median_bermasalah_per_kelompok = median(Jumlah_ChargedOff)
)
knitr::kable(ringkasan_poisson, caption = "Ringkasan Data Agregat Poisson")| Jumlah_kelompok | Total_pinjaman | Total_pinjaman_bermasalah | Rata_rata_bermasalah_per_kelompok | Median_bermasalah_per_kelompok |
|---|---|---|---|---|
| 98766 | 422523 | 30838 | 0.312233 | 0 |
knitr::kable(
data_poisson_clean %>%
dplyr::count(loanstatus) %>%
dplyr::mutate(Persen = scales::percent(n / sum(n))),
caption = "Distribusi Status Pinjaman yang Digunakan"
)| loanstatus | n | Persen |
|---|---|---|
| CHGOFF | 30838 | 7% |
| P I F | 391685 | 93% |
plot_poisson_data <- data_poisson_agg %>%
dplyr::filter(Jumlah_ChargedOff <= quantile(Jumlah_ChargedOff, 0.99))
ggplot(plot_poisson_data, aes(x = Jumlah_ChargedOff)) +
geom_histogram(binwidth = 1) +
labs(
title = "Distribusi Jumlah Pinjaman Bermasalah per Kelompok",
x = "Jumlah pinjaman bermasalah",
y = "Jumlah kelompok"
) +
theme_minimal()Rate pinjaman bermasalah dihitung sebagai:
\[ Rate = \frac{Jumlah\_ChargedOff}{Total\_Loan} \]
Rate ini membantu membandingkan risiko antar kelompok, karena jumlah pinjaman setiap kelompok tidak sama.
rate_by_size_term <- data_poisson_agg %>%
dplyr::group_by(Loan_Size_Band, Term_Band) %>%
dplyr::summarise(
Total_Loan = sum(Total_Loan),
Jumlah_ChargedOff = sum(Jumlah_ChargedOff),
Rate_ChargedOff = Jumlah_ChargedOff / Total_Loan,
.groups = "drop"
) %>%
dplyr::arrange(desc(Rate_ChargedOff))
knitr::kable(
rate_by_size_term %>%
dplyr::mutate(Rate_ChargedOff = scales::percent(Rate_ChargedOff, accuracy = 0.01)),
caption = "Rate Pinjaman Bermasalah berdasarkan Ukuran Pinjaman dan Tenor"
)| Loan_Size_Band | Term_Band | Total_Loan | Jumlah_ChargedOff | Rate_ChargedOff |
|---|---|---|---|---|
| Large | Short | 5558 | 1354 | 24.36% |
| Medium | Short | 35390 | 6594 | 18.63% |
| Small | Short | 49785 | 8775 | 17.63% |
| Large | Medium | 36146 | 2231 | 6.17% |
| Medium | Medium | 115298 | 6529 | 5.66% |
| Small | Long | 1867 | 70 | 3.75% |
| Small | Medium | 102612 | 3570 | 3.48% |
| Large | Long | 53893 | 1248 | 2.32% |
| Medium | Long | 21974 | 467 | 2.13% |
Model Poisson yang digunakan:
\[ \log(\mu_i) = \beta_0 + \beta_1 X_{1i} + \beta_2 X_{2i} + \cdots + \beta_p X_{pi} + \log(Total\_Loan_i) \]
Dalam model ini, \(X_{1i}, X_{2i}, \ldots,
X_{pi}\) mewakili ApprovalFY,
BorrState, Sector,
Loan_Size_Band, Term_Band,
BusinessType, dan CollateralInd. Komponen
\(\log(Total\_Loan_i)\) adalah
offset.
Bagian offset(log(Total_Loan)) membuat model
membandingkan rate pinjaman bermasalah. Artinya,
kelompok dengan jumlah pinjaman lebih banyak tidak otomatis dianggap
lebih berisiko hanya karena jumlah kasusnya lebih besar.
model_poisson <- glm(
Jumlah_ChargedOff ~ ApprovalFY + BorrState + Sector +
Loan_Size_Band + Term_Band + BusinessType + CollateralInd +
offset(log(Total_Loan)),
data = data_poisson_agg,
family = poisson(link = "log")
)
summary(model_poisson)##
## Call:
## glm(formula = Jumlah_ChargedOff ~ ApprovalFY + BorrState + Sector +
## Loan_Size_Band + Term_Band + BusinessType + CollateralInd +
## offset(log(Total_Loan)), family = poisson(link = "log"),
## data = data_poisson_agg)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.46947 0.15788 -15.641 < 0.0000000000000002
## ApprovalFY2011 -0.24209 0.02716 -8.913 < 0.0000000000000002
## ApprovalFY2012 -0.29396 0.02893 -10.161 < 0.0000000000000002
## ApprovalFY2013 -0.29279 0.02878 -10.173 < 0.0000000000000002
## ApprovalFY2014 -0.19727 0.02697 -7.316 0.000000000000256404
## ApprovalFY2015 -0.06903 0.02523 -2.736 0.006228
## ApprovalFY2016 0.05423 0.02471 2.194 0.028215
## ApprovalFY2017 0.18465 0.02443 7.559 0.000000000000040696
## ApprovalFY2018 0.27549 0.02453 11.230 < 0.0000000000000002
## ApprovalFY2019 0.24332 0.02663 9.135 < 0.0000000000000002
## BorrStateAL 0.41684 0.15676 2.659 0.007834
## BorrStateAR 0.27004 0.16264 1.660 0.096847
## BorrStateAZ 0.32399 0.15000 2.160 0.030780
## BorrStateCA 0.22843 0.14533 1.572 0.116011
## BorrStateCO 0.06094 0.14983 0.407 0.684210
## BorrStateCT -0.09801 0.15511 -0.632 0.527483
## BorrStateDC 0.08759 0.19524 0.449 0.653695
## BorrStateDE 0.08016 0.17878 0.448 0.653890
## BorrStateFL 0.61101 0.14595 4.187 0.000028328546656523
## BorrStateFM -7.43694 104.72036 -0.071 0.943384
## BorrStateGA 0.53549 0.14827 3.612 0.000304
## BorrStateGU -0.99354 0.28882 -3.440 0.000582
## BorrStateHI -0.56223 0.16309 -3.447 0.000566
## BorrStateIA -0.01058 0.15769 -0.067 0.946492
## BorrStateID -0.36327 0.16500 -2.202 0.027686
## BorrStateIL 0.34962 0.14724 2.374 0.017575
## BorrStateIN -0.31480 0.15020 -2.096 0.036094
## BorrStateKS -0.12426 0.15879 -0.783 0.433920
## BorrStateKY -0.09080 0.15634 -0.581 0.561375
## BorrStateLA 0.38275 0.15597 2.454 0.014126
## BorrStateMA -0.46103 0.14809 -3.113 0.001851
## BorrStateMD 0.06567 0.15143 0.434 0.664516
## BorrStateME -0.55411 0.17128 -3.235 0.001216
## BorrStateMH -8.48450 104.72036 -0.081 0.935426
## BorrStateMI -0.52699 0.14846 -3.550 0.000386
## BorrStateMN -0.28438 0.14962 -1.901 0.057339
## BorrStateMO 0.21966 0.14962 1.468 0.142056
## BorrStateMP 0.31445 1.01052 0.311 0.755668
## BorrStateMS 0.09516 0.15712 0.606 0.544723
## BorrStateMT -0.88110 0.18354 -4.801 0.000001582041871745
## BorrStateNC 0.25033 0.14989 1.670 0.094902
## BorrStateND -1.01273 0.20124 -5.032 0.000000484197663264
## BorrStateNE -0.19367 0.16285 -1.189 0.234340
## BorrStateNH -0.53755 0.15946 -3.371 0.000749
## BorrStateNJ 0.35466 0.14757 2.403 0.016246
## BorrStateNM -0.01682 0.17025 -0.099 0.921283
## BorrStateNV 0.36220 0.15671 2.311 0.020820
## BorrStateNY 0.09597 0.14586 0.658 0.510574
## BorrStateOH -0.44622 0.14682 -3.039 0.002372
## BorrStateOK 0.03046 0.15604 0.195 0.845224
## BorrStateOR -0.19393 0.15498 -1.251 0.210807
## BorrStatePA -0.08363 0.14811 -0.565 0.572324
## BorrStatePR -0.29434 0.15772 -1.866 0.062008
## BorrStateRI -0.23438 0.16553 -1.416 0.156798
## BorrStateSC 0.53736 0.15500 3.467 0.000527
## BorrStateSD -0.45081 0.20117 -2.241 0.025028
## BorrStateTN 0.29929 0.15551 1.925 0.054276
## BorrStateTX 0.52534 0.14546 3.611 0.000304
## BorrStateUT -0.09849 0.15165 -0.649 0.516067
## BorrStateVA 0.17141 0.15051 1.139 0.254740
## BorrStateVI 0.26294 0.40464 0.650 0.515806
## BorrStateVT -0.73539 0.18223 -4.036 0.000054462509707384
## BorrStateWA -0.19821 0.15068 -1.315 0.188375
## BorrStateWI -0.20688 0.15048 -1.375 0.169189
## BorrStateWV -0.35734 0.19164 -1.865 0.062232
## BorrStateWY -0.28210 0.19934 -1.415 0.157008
## Sector21 0.16780 0.12352 1.359 0.174285
## Sector22 0.09301 0.23178 0.401 0.688201
## Sector23 0.53213 0.06314 8.428 < 0.0000000000000002
## Sector31 0.52780 0.07341 7.190 0.000000000000650111
## Sector32 0.40767 0.07561 5.392 0.000000069725213239
## Sector33 0.31752 0.06862 4.627 0.000003708985025159
## Sector42 0.48216 0.06533 7.380 0.000000000000158234
## Sector44 0.69365 0.06332 10.955 < 0.0000000000000002
## Sector45 0.76351 0.06613 11.546 < 0.0000000000000002
## Sector48 0.37120 0.06512 5.700 0.000000011947801913
## Sector49 0.52290 0.10912 4.792 0.000001649625681084
## Sector51 0.48543 0.07999 6.069 0.000000001288851830
## Sector52 0.12758 0.08236 1.549 0.121379
## Sector53 0.36788 0.07617 4.830 0.000001367504057940
## Sector54 0.40733 0.06396 6.369 0.000000000190651353
## Sector55 -0.24403 0.38296 -0.637 0.523985
## Sector56 0.47257 0.06620 7.139 0.000000000000939939
## Sector61 0.65300 0.07674 8.510 < 0.0000000000000002
## Sector62 0.26157 0.06531 4.005 0.000061925924576628
## Sector71 0.85793 0.06758 12.696 < 0.0000000000000002
## Sector72 0.79440 0.06278 12.654 < 0.0000000000000002
## Sector81 0.62187 0.06372 9.759 < 0.0000000000000002
## Sector92 0.51861 0.41284 1.256 0.209038
## Loan_Size_BandMedium 0.29419 0.01345 21.871 < 0.0000000000000002
## Loan_Size_BandLarge 0.43938 0.02020 21.753 < 0.0000000000000002
## Term_BandMedium -1.55411 0.01235 -125.836 < 0.0000000000000002
## Term_BandLong -2.44891 0.02798 -87.535 < 0.0000000000000002
## BusinessTypeINDIVIDUAL -0.01455 0.01928 -0.755 0.450351
## BusinessTypePARTNERSHIP -0.46048 0.05616 -8.199 0.000000000000000243
## CollateralIndNo_Collateral 0.39095 0.01323 29.546 < 0.0000000000000002
##
## (Intercept) ***
## ApprovalFY2011 ***
## ApprovalFY2012 ***
## ApprovalFY2013 ***
## ApprovalFY2014 ***
## ApprovalFY2015 **
## ApprovalFY2016 *
## ApprovalFY2017 ***
## ApprovalFY2018 ***
## ApprovalFY2019 ***
## BorrStateAL **
## BorrStateAR .
## BorrStateAZ *
## BorrStateCA
## BorrStateCO
## BorrStateCT
## BorrStateDC
## BorrStateDE
## BorrStateFL ***
## BorrStateFM
## BorrStateGA ***
## BorrStateGU ***
## BorrStateHI ***
## BorrStateIA
## BorrStateID *
## BorrStateIL *
## BorrStateIN *
## BorrStateKS
## BorrStateKY
## BorrStateLA *
## BorrStateMA **
## BorrStateMD
## BorrStateME **
## BorrStateMH
## BorrStateMI ***
## BorrStateMN .
## BorrStateMO
## BorrStateMP
## BorrStateMS
## BorrStateMT ***
## BorrStateNC .
## BorrStateND ***
## BorrStateNE
## BorrStateNH ***
## BorrStateNJ *
## BorrStateNM
## BorrStateNV *
## BorrStateNY
## BorrStateOH **
## BorrStateOK
## BorrStateOR
## BorrStatePA
## BorrStatePR .
## BorrStateRI
## BorrStateSC ***
## BorrStateSD *
## BorrStateTN .
## BorrStateTX ***
## BorrStateUT
## BorrStateVA
## BorrStateVI
## BorrStateVT ***
## BorrStateWA
## BorrStateWI
## BorrStateWV .
## BorrStateWY
## Sector21
## Sector22
## Sector23 ***
## Sector31 ***
## Sector32 ***
## Sector33 ***
## Sector42 ***
## Sector44 ***
## Sector45 ***
## Sector48 ***
## Sector49 ***
## Sector51 ***
## Sector52
## Sector53 ***
## Sector54 ***
## Sector55
## Sector56 ***
## Sector61 ***
## Sector62 ***
## Sector71 ***
## Sector72 ***
## Sector81 ***
## Sector92
## Loan_Size_BandMedium ***
## Loan_Size_BandLarge ***
## Term_BandMedium ***
## Term_BandLong ***
## BusinessTypeINDIVIDUAL
## BusinessTypePARTNERSHIP ***
## CollateralIndNo_Collateral ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 83781 on 98765 degrees of freedom
## Residual deviance: 59081 on 98670 degrees of freedom
## AIC: 102778
##
## Number of Fisher Scoring iterations: 8
Chunk model-poisson di atas sudah membangun
model regresi Poisson menggunakan glm() dengan
family = poisson(link = "log"). Bentuk hasil estimasinya
adalah:
\[ \log(\hat{\mu_i}) = \hat{\beta}_0 + \hat{\beta}_1X_{1i} + \cdots + \log(Total\_Loan_i) \]
Karena terdapat offset(log(Total_Loan)), model membaca
rate pinjaman bermasalah, bukan sekadar jumlah mentah.
Koefisien yang dieksponensialkan menjadi
Incidence Rate Ratio atau IRR.
\[ \log(\widehat{\mu_i}) = -2.4695 - 0.2421\,\mathrm{FY2011} - 0.294\,\mathrm{FY2012} - 0.2928\,\mathrm{FY2013} - 0.1973\,\mathrm{FY2014} - 0.069\,\mathrm{FY2015} + 0.0542\,\mathrm{FY2016} + 0.1847\,\mathrm{FY2017} + 0.2755\,\mathrm{FY2018} + 0.2433\,\mathrm{FY2019} + 0.4168\,\mathrm{StateAL} + 0.27\,\mathrm{StateAR} + 0.324\,\mathrm{StateAZ} + 0.2284\,\mathrm{StateCA} + 0.0609\,\mathrm{StateCO} - 0.098\,\mathrm{StateCT} + 0.0876\,\mathrm{StateDC} + 0.0802\,\mathrm{StateDE} + 0.611\,\mathrm{StateFL} - 7.4369\,\mathrm{StateFM} + 0.5355\,\mathrm{StateGA} - 0.9935\,\mathrm{StateGU} - 0.5622\,\mathrm{StateHI} - 0.0106\,\mathrm{StateIA} - 0.3633\,\mathrm{StateID} + 0.3496\,\mathrm{StateIL} - 0.3148\,\mathrm{StateIN} - 0.1243\,\mathrm{StateKS} - 0.0908\,\mathrm{StateKY} + 0.3828\,\mathrm{StateLA} - 0.461\,\mathrm{StateMA} + 0.0657\,\mathrm{StateMD} - 0.5541\,\mathrm{StateME} - 8.4845\,\mathrm{StateMH} - 0.527\,\mathrm{StateMI} - 0.2844\,\mathrm{StateMN} + 0.2197\,\mathrm{StateMO} + 0.3144\,\mathrm{StateMP} + 0.0952\,\mathrm{StateMS} - 0.8811\,\mathrm{StateMT} + 0.2503\,\mathrm{StateNC} - 1.0127\,\mathrm{StateND} - 0.1937\,\mathrm{StateNE} - 0.5376\,\mathrm{StateNH} + 0.3547\,\mathrm{StateNJ} - 0.0168\,\mathrm{StateNM} + 0.3622\,\mathrm{StateNV} + 0.096\,\mathrm{StateNY} - 0.4462\,\mathrm{StateOH} + 0.0305\,\mathrm{StateOK} - 0.1939\,\mathrm{StateOR} - 0.0836\,\mathrm{StatePA} - 0.2943\,\mathrm{StatePR} - 0.2344\,\mathrm{StateRI} + 0.5374\,\mathrm{StateSC} - 0.4508\,\mathrm{StateSD} + 0.2993\,\mathrm{StateTN} + 0.5253\,\mathrm{StateTX} - 0.0985\,\mathrm{StateUT} + 0.1714\,\mathrm{StateVA} + 0.2629\,\mathrm{StateVI} - 0.7354\,\mathrm{StateVT} - 0.1982\,\mathrm{StateWA} - 0.2069\,\mathrm{StateWI} - 0.3573\,\mathrm{StateWV} - 0.2821\,\mathrm{StateWY} + 0.1678\,\mathrm{Sector21} + 0.093\,\mathrm{Sector22} + 0.5321\,\mathrm{Sector23} + 0.5278\,\mathrm{Sector31} + 0.4077\,\mathrm{Sector32} + 0.3175\,\mathrm{Sector33} + 0.4822\,\mathrm{Sector42} + 0.6936\,\mathrm{Sector44} + 0.7635\,\mathrm{Sector45} + 0.3712\,\mathrm{Sector48} + 0.5229\,\mathrm{Sector49} + 0.4854\,\mathrm{Sector51} + 0.1276\,\mathrm{Sector52} + 0.3679\,\mathrm{Sector53} + 0.4073\,\mathrm{Sector54} - 0.244\,\mathrm{Sector55} + 0.4726\,\mathrm{Sector56} + 0.653\,\mathrm{Sector61} + 0.2616\,\mathrm{Sector62} + 0.8579\,\mathrm{Sector71} + 0.7944\,\mathrm{Sector72} + 0.6219\,\mathrm{Sector81} + 0.5186\,\mathrm{Sector92} + 0.2942\,\mathrm{LoanSizeMedium} + 0.4394\,\mathrm{LoanSizeLarge} - 1.5541\,\mathrm{TermMedium} - 2.4489\,\mathrm{TermLong} - 0.0146\,\mathrm{BusinessTypeINDIVIDUAL} - 0.4605\,\mathrm{BusinessTypePARTNERSHIP} + 0.391\,\mathrm{CollateralNo_Collateral} + \log(Total\_Loan_i) \]
Karena terdapat offset, bentuk rate-nya dapat ditulis sebagai:
\[ \log\left(\frac{\widehat{\mu_i}}{Total\_Loan_i}\right) = -2.4695 - 0.2421\,\mathrm{FY2011} - 0.294\,\mathrm{FY2012} - 0.2928\,\mathrm{FY2013} - 0.1973\,\mathrm{FY2014} - 0.069\,\mathrm{FY2015} + 0.0542\,\mathrm{FY2016} + 0.1847\,\mathrm{FY2017} + 0.2755\,\mathrm{FY2018} + 0.2433\,\mathrm{FY2019} + 0.4168\,\mathrm{StateAL} + 0.27\,\mathrm{StateAR} + 0.324\,\mathrm{StateAZ} + 0.2284\,\mathrm{StateCA} + 0.0609\,\mathrm{StateCO} - 0.098\,\mathrm{StateCT} + 0.0876\,\mathrm{StateDC} + 0.0802\,\mathrm{StateDE} + 0.611\,\mathrm{StateFL} - 7.4369\,\mathrm{StateFM} + 0.5355\,\mathrm{StateGA} - 0.9935\,\mathrm{StateGU} - 0.5622\,\mathrm{StateHI} - 0.0106\,\mathrm{StateIA} - 0.3633\,\mathrm{StateID} + 0.3496\,\mathrm{StateIL} - 0.3148\,\mathrm{StateIN} - 0.1243\,\mathrm{StateKS} - 0.0908\,\mathrm{StateKY} + 0.3828\,\mathrm{StateLA} - 0.461\,\mathrm{StateMA} + 0.0657\,\mathrm{StateMD} - 0.5541\,\mathrm{StateME} - 8.4845\,\mathrm{StateMH} - 0.527\,\mathrm{StateMI} - 0.2844\,\mathrm{StateMN} + 0.2197\,\mathrm{StateMO} + 0.3144\,\mathrm{StateMP} + 0.0952\,\mathrm{StateMS} - 0.8811\,\mathrm{StateMT} + 0.2503\,\mathrm{StateNC} - 1.0127\,\mathrm{StateND} - 0.1937\,\mathrm{StateNE} - 0.5376\,\mathrm{StateNH} + 0.3547\,\mathrm{StateNJ} - 0.0168\,\mathrm{StateNM} + 0.3622\,\mathrm{StateNV} + 0.096\,\mathrm{StateNY} - 0.4462\,\mathrm{StateOH} + 0.0305\,\mathrm{StateOK} - 0.1939\,\mathrm{StateOR} - 0.0836\,\mathrm{StatePA} - 0.2943\,\mathrm{StatePR} - 0.2344\,\mathrm{StateRI} + 0.5374\,\mathrm{StateSC} - 0.4508\,\mathrm{StateSD} + 0.2993\,\mathrm{StateTN} + 0.5253\,\mathrm{StateTX} - 0.0985\,\mathrm{StateUT} + 0.1714\,\mathrm{StateVA} + 0.2629\,\mathrm{StateVI} - 0.7354\,\mathrm{StateVT} - 0.1982\,\mathrm{StateWA} - 0.2069\,\mathrm{StateWI} - 0.3573\,\mathrm{StateWV} - 0.2821\,\mathrm{StateWY} + 0.1678\,\mathrm{Sector21} + 0.093\,\mathrm{Sector22} + 0.5321\,\mathrm{Sector23} + 0.5278\,\mathrm{Sector31} + 0.4077\,\mathrm{Sector32} + 0.3175\,\mathrm{Sector33} + 0.4822\,\mathrm{Sector42} + 0.6936\,\mathrm{Sector44} + 0.7635\,\mathrm{Sector45} + 0.3712\,\mathrm{Sector48} + 0.5229\,\mathrm{Sector49} + 0.4854\,\mathrm{Sector51} + 0.1276\,\mathrm{Sector52} + 0.3679\,\mathrm{Sector53} + 0.4073\,\mathrm{Sector54} - 0.244\,\mathrm{Sector55} + 0.4726\,\mathrm{Sector56} + 0.653\,\mathrm{Sector61} + 0.2616\,\mathrm{Sector62} + 0.8579\,\mathrm{Sector71} + 0.7944\,\mathrm{Sector72} + 0.6219\,\mathrm{Sector81} + 0.5186\,\mathrm{Sector92} + 0.2942\,\mathrm{LoanSizeMedium} + 0.4394\,\mathrm{LoanSizeLarge} - 1.5541\,\mathrm{TermMedium} - 2.4489\,\mathrm{TermLong} - 0.0146\,\mathrm{BusinessTypeINDIVIDUAL} - 0.4605\,\mathrm{BusinessTypePARTNERSHIP} + 0.391\,\mathrm{CollateralNo_Collateral} \]
Pada regresi Poisson, koefisien model berada pada skala log. Agar lebih mudah diinterpretasikan, koefisien diubah menjadi Incidence Rate Ratio atau IRR dengan rumus:
\[ IRR = \exp(\beta) \]
Jika IRR lebih dari 1, maka rate pinjaman bermasalah lebih tinggi dibanding kategori acuan. Jika IRR kurang dari 1, maka rate pinjaman bermasalah lebih rendah dibanding kategori acuan.
tabel_poisson <- broom::tidy(model_poisson) %>%
dplyr::mutate(
Incidence_Rate_Ratio = exp(estimate),
Perubahan_Persen = 100 * (Incidence_Rate_Ratio - 1),
Variabel_Mudah = purrr::map_chr(term, label_poisson),
Keputusan_5persen = ifelse(p.value < 0.05, "Signifikan", "Tidak signifikan")
) %>%
dplyr::arrange(p.value)
knitr::kable(
tabel_poisson %>%
dplyr::select(
Variabel_Mudah,
term,
estimate,
std.error,
statistic,
p.value,
Incidence_Rate_Ratio,
Perubahan_Persen,
Keputusan_5persen
) %>%
head(35),
digits = 4,
caption = "Koefisien dan Incidence Rate Ratio Regresi Poisson"
)| Variabel_Mudah | term | estimate | std.error | statistic | p.value | Incidence_Rate_Ratio | Perubahan_Persen | Keputusan_5persen |
|---|---|---|---|---|---|---|---|---|
| tenor pinjaman: Medium dibanding tenor pendek | Term_BandMedium | -1.5541 | 0.0124 | -125.8356 | 0.0000 | 0.2114 | -78.8622 | Signifikan |
| tenor pinjaman: Long dibanding tenor pendek | Term_BandLong | -2.4489 | 0.0280 | -87.5349 | 0.0000 | 0.0864 | -91.3612 | Signifikan |
| status agunan: No_Collateral dibanding kategori acuan | CollateralIndNo_Collateral | 0.3910 | 0.0132 | 29.5461 | 0.0000 | 1.4784 | 47.8387 | Signifikan |
| ukuran pinjaman: Medium dibanding pinjaman kecil | Loan_Size_BandMedium | 0.2942 | 0.0135 | 21.8709 | 0.0000 | 1.3420 | 34.2034 | Signifikan |
| ukuran pinjaman: Large dibanding pinjaman kecil | Loan_Size_BandLarge | 0.4394 | 0.0202 | 21.7530 | 0.0000 | 1.5517 | 55.1747 | Signifikan |
| (Intercept) | (Intercept) | -2.4695 | 0.1579 | -15.6413 | 0.0000 | 0.0846 | -91.5371 | Signifikan |
| sektor industri: 71 dibanding sektor acuan | Sector71 | 0.8579 | 0.0676 | 12.6959 | 0.0000 | 2.3583 | 135.8283 | Signifikan |
| sektor industri: 72 dibanding sektor acuan | Sector72 | 0.7944 | 0.0628 | 12.6543 | 0.0000 | 2.2131 | 121.3112 | Signifikan |
| sektor industri: 45 dibanding sektor acuan | Sector45 | 0.7635 | 0.0661 | 11.5463 | 0.0000 | 2.1458 | 114.5786 | Signifikan |
| tahun persetujuan: 2018 dibanding tahun acuan | ApprovalFY2018 | 0.2755 | 0.0245 | 11.2297 | 0.0000 | 1.3172 | 31.7181 | Signifikan |
| sektor industri: 44 dibanding sektor acuan | Sector44 | 0.6936 | 0.0633 | 10.9546 | 0.0000 | 2.0010 | 100.1000 | Signifikan |
| tahun persetujuan: 2013 dibanding tahun acuan | ApprovalFY2013 | -0.2928 | 0.0288 | -10.1733 | 0.0000 | 0.7462 | -25.3821 | Signifikan |
| tahun persetujuan: 2012 dibanding tahun acuan | ApprovalFY2012 | -0.2940 | 0.0289 | -10.1612 | 0.0000 | 0.7453 | -25.4695 | Signifikan |
| sektor industri: 81 dibanding sektor acuan | Sector81 | 0.6219 | 0.0637 | 9.7587 | 0.0000 | 1.8624 | 86.2408 | Signifikan |
| tahun persetujuan: 2019 dibanding tahun acuan | ApprovalFY2019 | 0.2433 | 0.0266 | 9.1354 | 0.0000 | 1.2755 | 27.5476 | Signifikan |
| tahun persetujuan: 2011 dibanding tahun acuan | ApprovalFY2011 | -0.2421 | 0.0272 | -8.9128 | 0.0000 | 0.7850 | -21.5015 | Signifikan |
| sektor industri: 61 dibanding sektor acuan | Sector61 | 0.6530 | 0.0767 | 8.5096 | 0.0000 | 1.9213 | 92.1300 | Signifikan |
| sektor industri: 23 dibanding sektor acuan | Sector23 | 0.5321 | 0.0631 | 8.4282 | 0.0000 | 1.7026 | 70.2555 | Signifikan |
| jenis usaha: PARTNERSHIP dibanding kategori acuan | BusinessTypePARTNERSHIP | -0.4605 | 0.0562 | -8.1989 | 0.0000 | 0.6310 | -36.9017 | Signifikan |
| tahun persetujuan: 2017 dibanding tahun acuan | ApprovalFY2017 | 0.1847 | 0.0244 | 7.5588 | 0.0000 | 1.2028 | 20.2801 | Signifikan |
| sektor industri: 42 dibanding sektor acuan | Sector42 | 0.4822 | 0.0653 | 7.3800 | 0.0000 | 1.6196 | 61.9563 | Signifikan |
| tahun persetujuan: 2014 dibanding tahun acuan | ApprovalFY2014 | -0.1973 | 0.0270 | -7.3155 | 0.0000 | 0.8210 | -17.9029 | Signifikan |
| sektor industri: 31 dibanding sektor acuan | Sector31 | 0.5278 | 0.0734 | 7.1895 | 0.0000 | 1.6952 | 69.5205 | Signifikan |
| sektor industri: 56 dibanding sektor acuan | Sector56 | 0.4726 | 0.0662 | 7.1390 | 0.0000 | 1.6041 | 60.4118 | Signifikan |
| sektor industri: 54 dibanding sektor acuan | Sector54 | 0.4073 | 0.0640 | 6.3687 | 0.0000 | 1.5028 | 50.2794 | Signifikan |
| sektor industri: 51 dibanding sektor acuan | Sector51 | 0.4854 | 0.0800 | 6.0688 | 0.0000 | 1.6249 | 62.4878 | Signifikan |
| sektor industri: 48 dibanding sektor acuan | Sector48 | 0.3712 | 0.0651 | 5.7005 | 0.0000 | 1.4495 | 44.9477 | Signifikan |
| sektor industri: 32 dibanding sektor acuan | Sector32 | 0.4077 | 0.0756 | 5.3919 | 0.0000 | 1.5033 | 50.3305 | Signifikan |
| state peminjam: ND dibanding state acuan | BorrStateND | -1.0127 | 0.2012 | -5.0325 | 0.0000 | 0.3632 | -63.6773 | Signifikan |
| sektor industri: 53 dibanding sektor acuan | Sector53 | 0.3679 | 0.0762 | 4.8297 | 0.0000 | 1.4447 | 44.4673 | Signifikan |
| state peminjam: MT dibanding state acuan | BorrStateMT | -0.8811 | 0.1835 | -4.8006 | 0.0000 | 0.4143 | -58.5672 | Signifikan |
| sektor industri: 49 dibanding sektor acuan | Sector49 | 0.5229 | 0.1091 | 4.7922 | 0.0000 | 1.6869 | 68.6918 | Signifikan |
| sektor industri: 33 dibanding sektor acuan | Sector33 | 0.3175 | 0.0686 | 4.6271 | 0.0000 | 1.3737 | 37.3723 | Signifikan |
| state peminjam: FL dibanding state acuan | BorrStateFL | 0.6110 | 0.1459 | 4.1865 | 0.0000 | 1.8423 | 84.2283 | Signifikan |
| state peminjam: VT dibanding state acuan | BorrStateVT | -0.7354 | 0.1822 | -4.0356 | 0.0001 | 0.4793 | -52.0682 | Signifikan |
## [1] 102778.3
## [1] 0.5987723
if (dispersion_poisson > 1.5) {
cat("Terdapat indikasi overdispersion. Inferensi p-value sebaiknya dilihat juga menggunakan quasi-Poisson.\n")
} else {
cat("Tidak ada indikasi overdispersion yang kuat berdasarkan rasio deviance/df residual.\n")
}## Tidak ada indikasi overdispersion yang kuat berdasarkan rasio deviance/df residual.
Selain rasio deviance terhadap derajat bebas residual, overdispersion juga dapat diperiksa menggunakan Pearson dispersion.
\[ \hat{\phi} = \frac{\sum r_{P,i}^2}{df} \]
Jika nilai dispersion jauh lebih besar dari 1, maka terdapat indikasi overdispersion.
pearson_dispersion <- sum(residuals(model_poisson, type = "pearson")^2) /
df.residual(model_poisson)
tibble::tibble(
Ukuran = "Pearson dispersion",
Nilai = pearson_dispersion,
Interpretasi = dplyr::case_when(
pearson_dispersion < 1.5 ~ "Tidak ada indikasi overdispersion berat",
pearson_dispersion < 2.5 ~ "Ada indikasi overdispersion sedang",
TRUE ~ "Ada indikasi overdispersion kuat"
)
) %>%
dplyr::mutate(Nilai = round(Nilai, 3)) %>%
knitr::kable(caption = "Pemeriksaan Overdispersion dengan Pearson Dispersion")| Ukuran | Nilai | Interpretasi |
|---|---|---|
| Pearson dispersion | 1.148 | Tidak ada indikasi overdispersion berat |
Jika nilai Pearson dispersion jauh lebih besar dari 1, maka variasi jumlah pinjaman bermasalah lebih besar daripada yang diasumsikan oleh model Poisson. Dalam kondisi tersebut, hasil signifikansi dari model Poisson standar perlu dibaca hati-hati dan model quasi-Poisson lebih aman digunakan sebagai pembanding.
model_quasipoisson <- glm(
Jumlah_ChargedOff ~ ApprovalFY + BorrState + Sector +
Loan_Size_Band + Term_Band + BusinessType + CollateralInd +
offset(log(Total_Loan)),
data = data_poisson_agg,
family = quasipoisson(link = "log")
)
tabel_quasipoisson <- broom::tidy(model_quasipoisson) %>%
dplyr::mutate(
Incidence_Rate_Ratio = exp(estimate),
Perubahan_Persen = 100 * (Incidence_Rate_Ratio - 1),
Variabel_Mudah = purrr::map_chr(term, label_poisson),
Keputusan_5persen = ifelse(p.value < 0.05, "Signifikan", "Tidak signifikan")
) %>%
dplyr::arrange(p.value)
knitr::kable(
tabel_quasipoisson %>% dplyr::select(Variabel_Mudah, term, estimate, std.error, statistic, p.value, Incidence_Rate_Ratio, Perubahan_Persen, Keputusan_5persen) %>% head(35),
digits = 4,
caption = "Koefisien dan IRR Quasi-Poisson"
)| Variabel_Mudah | term | estimate | std.error | statistic | p.value | Incidence_Rate_Ratio | Perubahan_Persen | Keputusan_5persen |
|---|---|---|---|---|---|---|---|---|
| tenor pinjaman: Medium dibanding tenor pendek | Term_BandMedium | -1.5541 | 0.0132 | -117.4643 | 0.0000 | 0.2114 | -78.8622 | Signifikan |
| tenor pinjaman: Long dibanding tenor pendek | Term_BandLong | -2.4489 | 0.0300 | -81.7116 | 0.0000 | 0.0864 | -91.3612 | Signifikan |
| status agunan: No_Collateral dibanding kategori acuan | CollateralIndNo_Collateral | 0.3910 | 0.0142 | 27.5805 | 0.0000 | 1.4784 | 47.8387 | Signifikan |
| ukuran pinjaman: Medium dibanding pinjaman kecil | Loan_Size_BandMedium | 0.2942 | 0.0144 | 20.4159 | 0.0000 | 1.3420 | 34.2034 | Signifikan |
| ukuran pinjaman: Large dibanding pinjaman kecil | Loan_Size_BandLarge | 0.4394 | 0.0216 | 20.3059 | 0.0000 | 1.5517 | 55.1747 | Signifikan |
| (Intercept) | (Intercept) | -2.4695 | 0.1691 | -14.6008 | 0.0000 | 0.0846 | -91.5371 | Signifikan |
| sektor industri: 71 dibanding sektor acuan | Sector71 | 0.8579 | 0.0724 | 11.8513 | 0.0000 | 2.3583 | 135.8283 | Signifikan |
| sektor industri: 72 dibanding sektor acuan | Sector72 | 0.7944 | 0.0673 | 11.8124 | 0.0000 | 2.2131 | 121.3112 | Signifikan |
| sektor industri: 45 dibanding sektor acuan | Sector45 | 0.7635 | 0.0708 | 10.7781 | 0.0000 | 2.1458 | 114.5786 | Signifikan |
| tahun persetujuan: 2018 dibanding tahun acuan | ApprovalFY2018 | 0.2755 | 0.0263 | 10.4826 | 0.0000 | 1.3172 | 31.7181 | Signifikan |
| sektor industri: 44 dibanding sektor acuan | Sector44 | 0.6936 | 0.0678 | 10.2259 | 0.0000 | 2.0010 | 100.1000 | Signifikan |
| tahun persetujuan: 2013 dibanding tahun acuan | ApprovalFY2013 | -0.2928 | 0.0308 | -9.4965 | 0.0000 | 0.7462 | -25.3821 | Signifikan |
| tahun persetujuan: 2012 dibanding tahun acuan | ApprovalFY2012 | -0.2940 | 0.0310 | -9.4853 | 0.0000 | 0.7453 | -25.4695 | Signifikan |
| sektor industri: 81 dibanding sektor acuan | Sector81 | 0.6219 | 0.0683 | 9.1095 | 0.0000 | 1.8624 | 86.2408 | Signifikan |
| tahun persetujuan: 2019 dibanding tahun acuan | ApprovalFY2019 | 0.2433 | 0.0285 | 8.5276 | 0.0000 | 1.2755 | 27.5476 | Signifikan |
| tahun persetujuan: 2011 dibanding tahun acuan | ApprovalFY2011 | -0.2421 | 0.0291 | -8.3199 | 0.0000 | 0.7850 | -21.5015 | Signifikan |
| sektor industri: 61 dibanding sektor acuan | Sector61 | 0.6530 | 0.0822 | 7.9435 | 0.0000 | 1.9213 | 92.1300 | Signifikan |
| sektor industri: 23 dibanding sektor acuan | Sector23 | 0.5321 | 0.0676 | 7.8675 | 0.0000 | 1.7026 | 70.2555 | Signifikan |
| jenis usaha: PARTNERSHIP dibanding kategori acuan | BusinessTypePARTNERSHIP | -0.4605 | 0.0602 | -7.6535 | 0.0000 | 0.6310 | -36.9017 | Signifikan |
| tahun persetujuan: 2017 dibanding tahun acuan | ApprovalFY2017 | 0.1847 | 0.0262 | 7.0559 | 0.0000 | 1.2028 | 20.2801 | Signifikan |
| sektor industri: 42 dibanding sektor acuan | Sector42 | 0.4822 | 0.0700 | 6.8891 | 0.0000 | 1.6196 | 61.9563 | Signifikan |
| tahun persetujuan: 2014 dibanding tahun acuan | ApprovalFY2014 | -0.1973 | 0.0289 | -6.8288 | 0.0000 | 0.8210 | -17.9029 | Signifikan |
| sektor industri: 31 dibanding sektor acuan | Sector31 | 0.5278 | 0.0786 | 6.7112 | 0.0000 | 1.6952 | 69.5205 | Signifikan |
| sektor industri: 56 dibanding sektor acuan | Sector56 | 0.4726 | 0.0709 | 6.6641 | 0.0000 | 1.6041 | 60.4118 | Signifikan |
| sektor industri: 54 dibanding sektor acuan | Sector54 | 0.4073 | 0.0685 | 5.9450 | 0.0000 | 1.5028 | 50.2794 | Signifikan |
| sektor industri: 51 dibanding sektor acuan | Sector51 | 0.4854 | 0.0857 | 5.6650 | 0.0000 | 1.6249 | 62.4878 | Signifikan |
| sektor industri: 48 dibanding sektor acuan | Sector48 | 0.3712 | 0.0698 | 5.3212 | 0.0000 | 1.4495 | 44.9477 | Signifikan |
| sektor industri: 32 dibanding sektor acuan | Sector32 | 0.4077 | 0.0810 | 5.0332 | 0.0000 | 1.5033 | 50.3305 | Signifikan |
| state peminjam: ND dibanding state acuan | BorrStateND | -1.0127 | 0.2156 | -4.6977 | 0.0000 | 0.3632 | -63.6773 | Signifikan |
| sektor industri: 53 dibanding sektor acuan | Sector53 | 0.3679 | 0.0816 | 4.5084 | 0.0000 | 1.4447 | 44.4673 | Signifikan |
| state peminjam: MT dibanding state acuan | BorrStateMT | -0.8811 | 0.1966 | -4.4812 | 0.0000 | 0.4143 | -58.5672 | Signifikan |
| sektor industri: 49 dibanding sektor acuan | Sector49 | 0.5229 | 0.1169 | 4.4734 | 0.0000 | 1.6869 | 68.6918 | Signifikan |
| sektor industri: 33 dibanding sektor acuan | Sector33 | 0.3175 | 0.0735 | 4.3192 | 0.0000 | 1.3737 | 37.3723 | Signifikan |
| state peminjam: FL dibanding state acuan | BorrStateFL | 0.6110 | 0.1563 | 3.9080 | 0.0001 | 1.8423 | 84.2283 | Signifikan |
| state peminjam: VT dibanding state acuan | BorrStateVT | -0.7354 | 0.1952 | -3.7671 | 0.0002 | 0.4793 | -52.0682 | Signifikan |
data_poisson_agg$fitted_poisson <- fitted(model_poisson)
ggplot(data_poisson_agg, aes(x = fitted_poisson, y = Jumlah_ChargedOff)) +
geom_point(alpha = 0.35) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed") +
labs(
title = "Observed vs Fitted Jumlah Pinjaman Bermasalah",
x = "Nilai fitted model",
y = "Jumlah pinjaman bermasalah aktual"
) +
theme_minimal()Visualisasi ini digunakan untuk melihat prediksi rate pinjaman bermasalah berdasarkan ukuran pinjaman dan tenor. Pada grafik ini, exposure ditetapkan sebesar 1 agar hasil yang ditampilkan dapat dibaca sebagai rate.
grid_poisson <- expand.grid(
ApprovalFY = factor(modus(data_poisson_agg$ApprovalFY), levels = levels(data_poisson_agg$ApprovalFY)),
BorrState = factor(modus(data_poisson_agg$BorrState), levels = levels(data_poisson_agg$BorrState)),
Sector = factor(modus(data_poisson_agg$Sector), levels = levels(data_poisson_agg$Sector)),
Loan_Size_Band = factor(levels(data_poisson_agg$Loan_Size_Band), levels = levels(data_poisson_agg$Loan_Size_Band)),
Term_Band = factor(levels(data_poisson_agg$Term_Band), levels = levels(data_poisson_agg$Term_Band)),
BusinessType = factor(modus(data_poisson_agg$BusinessType), levels = levels(data_poisson_agg$BusinessType)),
CollateralInd = factor(modus(data_poisson_agg$CollateralInd), levels = levels(data_poisson_agg$CollateralInd)),
Total_Loan = 1
)
pred_rate_poisson <- predict(
model_poisson,
newdata = grid_poisson,
type = "link",
se.fit = TRUE
)
grid_poisson_plot <- grid_poisson %>%
dplyr::mutate(
fit_link = pred_rate_poisson$fit,
se_link = pred_rate_poisson$se.fit,
Predicted_Rate = exp(fit_link),
Rate_Lower = exp(fit_link - 1.96 * se_link),
Rate_Upper = exp(fit_link + 1.96 * se_link)
)
ggplot(
grid_poisson_plot,
aes(x = Loan_Size_Band, y = Predicted_Rate, fill = Term_Band)
) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_errorbar(
aes(ymin = Rate_Lower, ymax = Rate_Upper),
position = position_dodge(width = 0.8),
width = 0.2
) +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Prediksi Rate Pinjaman Bermasalah",
subtitle = "Exposure ditetapkan 1; variabel lain ditahan pada kategori paling umum",
x = "Ukuran Pinjaman",
y = "Prediksi rate pinjaman bermasalah",
fill = "Tenor"
) +
theme_minimal()Grafik ini menunjukkan perbedaan prediksi rate pinjaman bermasalah menurut ukuran pinjaman dan tenor, dengan variabel lain ditahan pada kategori paling umum. Jika batang pada kategori tertentu lebih tinggi, maka kelompok tersebut diprediksi memiliki rate pinjaman bermasalah yang lebih tinggi.
if (dispersion_poisson > 1.5) {
tabel_pakai_poisson <- tabel_quasipoisson
metode_pakai <- "quasi-Poisson"
} else {
tabel_pakai_poisson <- tabel_poisson
metode_pakai <- "Poisson"
}
sig_poisson <- tabel_pakai_poisson %>%
dplyr::filter(term != "(Intercept)", p.value < 0.05) %>%
dplyr::arrange(p.value)
cat("Rasio deviance/df residual adalah **", fmt_num(dispersion_poisson, 3), "**. ", sep = "")Rasio deviance/df residual adalah 0.599.
if (dispersion_poisson > 1.5) {
cat("Nilai ini menunjukkan overdispersion, sehingga interpretasi signifikansi lebih aman mengacu pada model quasi-Poisson.\n\n")
} else {
cat("Nilai ini tidak menunjukkan overdispersion yang kuat, sehingga model Poisson standar masih memadai sebagai model awal.\n\n")
}Nilai ini tidak menunjukkan overdispersion yang kuat, sehingga model Poisson standar masih memadai sebagai model awal.
cat("Dengan acuan inferensi ", metode_pakai, ", terdapat ", nrow(sig_poisson),
" prediktor signifikan pada taraf 5%.\n\n", sep = "")Dengan acuan inferensi Poisson, terdapat 56 prediktor signifikan pada taraf 5%.
if (nrow(sig_poisson) > 0) {
cat("Prediktor paling penting berdasarkan p-value terkecil adalah:\n\n")
top_poisson <- head(sig_poisson, 10)
for (i in seq_len(nrow(top_poisson))) {
row <- top_poisson[i, ]
arah <- ifelse(row$Incidence_Rate_Ratio > 1,
"memiliki rate pinjaman bermasalah yang lebih tinggi",
"memiliki rate pinjaman bermasalah yang lebih rendah")
cat("- **", row$Variabel_Mudah, "** memiliki IRR = ", fmt_num(row$Incidence_Rate_Ratio, 3),
" dengan perubahan sekitar ", fmt_num(row$Perubahan_Persen, 2), "%",
" dan p-value = ", fmt_p(row$p.value), ", sehingga kelompok ini ", arah,
", dengan asumsi variabel lain tetap.\n", sep = "")
}
cat("\n")
}Prediktor paling penting berdasarkan p-value terkecil adalah:
AIC model Poisson adalah 102,778.27.
cat("**Kesimpulan substantif:** jumlah pinjaman bermasalah pada data SBA 7(a) tidak hanya dipengaruhi oleh banyaknya pinjaman dalam kelompok, tetapi juga oleh karakteristik kelompok seperti tahun persetujuan, state peminjam, sektor industri, ukuran pinjaman, tenor, jenis usaha, dan status agunan. Penggunaan offset `Total_Loan` membuat kesimpulan berfokus pada rate pinjaman bermasalah, bukan jumlah mentah.\n")Kesimpulan substantif: jumlah pinjaman bermasalah
pada data SBA 7(a) tidak hanya dipengaruhi oleh banyaknya pinjaman dalam
kelompok, tetapi juga oleh karakteristik kelompok seperti tahun
persetujuan, state peminjam, sektor industri, ukuran pinjaman, tenor,
jenis usaha, dan status agunan. Penggunaan offset
Total_Loan membuat kesimpulan berfokus pada rate pinjaman
bermasalah, bukan jumlah mentah.
| Model | Respon | Fungsi link | Ukuran interpretasi | Evaluasi utama |
|---|---|---|---|---|
| Logistik biner | Gagal bayar 0/1 | Logit | Odds ratio | Confusion matrix, AIC, ROC/AUC |
| Ordinal | Grade A-G | Cumulative logit dengan spesifikasi MASS::polr:
logit(P(Y <= j)) = alpha_j - x beta |
exp(beta) sebagai odds ratio menuju grade lebih
tinggi |
Confusion matrix, AIC, proportional odds check |
| Multinomial | Status pinjaman | Baseline-category logit | Relative risk ratio | Confusion matrix, AIC, prediksi probabilitas, catatan IIA |
| Poisson | Jumlah pinjaman bermasalah | Log | Incidence rate ratio dan perubahan persen | AIC, deviance dispersion, Pearson dispersion, overdispersion |
cat("Berdasarkan empat analisis yang dilakukan, setiap model menjawab bagian risiko kredit yang berbeda.\n\n")Berdasarkan empat analisis yang dilakukan, setiap model menjawab bagian risiko kredit yang berbeda.
cat("- **Model biner** menjelaskan peluang nasabah kartu kredit mengalami gagal bayar. Model ini cocok karena respon hanya terdiri dari dua kategori, yaitu gagal bayar dan tidak gagal bayar.\n")cat("- **Model ordinal** menjelaskan tingkat risiko pinjaman Lending Club berdasarkan grade A sampai G. Model ini cocok karena grade memiliki urutan risiko.\n")cat("- **Model multinomial** menjelaskan status pinjaman Prosper. Model ini cocok karena status pinjaman memiliki beberapa kategori yang tidak diperlakukan sebagai urutan.\n")cat("- **Model Poisson** menjelaskan jumlah pinjaman SBA 7(a) yang bermasalah pada setiap kelompok pinjaman. Model ini cocok karena respon berupa hitungan kejadian.\n\n")cat("Secara keseluruhan, analisis ini menunjukkan bahwa regresi untuk data kategori dan data hitungan dapat digunakan dalam konteks risk management. Model biner berguna untuk peluang gagal bayar, model ordinal untuk tingkat risiko, model multinomial untuk status pinjaman, dan model Poisson untuk jumlah kejadian pinjaman bermasalah.\n")Secara keseluruhan, analisis ini menunjukkan bahwa regresi untuk data kategori dan data hitungan dapat digunakan dalam konteks risk management. Model biner berguna untuk peluang gagal bayar, model ordinal untuk tingkat risiko, model multinomial untuk status pinjaman, dan model Poisson untuk jumlah kejadian pinjaman bermasalah.