DSEB

NHÓM 7

  1. Nguyễn Thị Kim Anh 11210617

  2. Nguyễn Thị Kim Anh 11216984

  3. Lê Thị Thu Hà 11211884

  4. Phạm Thị Thu Hương 11216994

  5. Trần Thị Phương Nguyên 11214476

options(repos = "https://cloud.r-project.org/")
# Load some packages for data manipulation: 
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.2
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(readr)
## Warning: package 'readr' was built under R version 4.3.3
library(Amelia)
## Warning: package 'Amelia' was built under R version 4.3.3
## Loading required package: Rcpp
## ## 
## ## Amelia II: Multiple Imputation
## ## (Version 1.8.1, built: 2022-11-18)
## ## Copyright (C) 2005-2024 James Honaker, Gary King and Matthew Blackwell
## ## Refer to http://gking.harvard.edu/amelia/ for more information
## ##
library(plyr)
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
library(tables)
## Warning: package 'tables' was built under R version 4.3.3
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.3.3
## Warning: package 'ggplot2' was built under R version 4.3.2
## Warning: package 'forcats' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ plyr::arrange()   masks dplyr::arrange()
## ✖ purrr::compact()  masks plyr::compact()
## ✖ plyr::count()     masks dplyr::count()
## ✖ plyr::desc()      masks dplyr::desc()
## ✖ plyr::failwith()  masks dplyr::failwith()
## ✖ dplyr::filter()   masks stats::filter()
## ✖ plyr::id()        masks dplyr::id()
## ✖ dplyr::lag()      masks stats::lag()
## ✖ plyr::mutate()    masks dplyr::mutate()
## ✖ plyr::rename()    masks dplyr::rename()
## ✖ plyr::summarise() masks dplyr::summarise()
## ✖ plyr::summarize() masks dplyr::summarize()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(Amelia)
library(car)
## Warning: package 'car' was built under R version 4.3.2
## Loading required package: carData
## 
## Attaching package: 'car'
## 
## The following object is masked from 'package:purrr':
## 
##     some
## 
## The following object is masked from 'package:dplyr':
## 
##     recode
library(psych)
## Warning: package 'psych' was built under R version 4.3.2
## 
## Attaching package: 'psych'
## 
## The following object is masked from 'package:car':
## 
##     logit
## 
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.92 loaded
library(nnet)
library(caTools)
library(ROCR)
## Warning: package 'ROCR' was built under R version 4.3.3
library(ggplot2)
library(ggthemes)
## Warning: package 'ggthemes' was built under R version 4.3.3
library(ggmosaic)
## Warning: package 'ggmosaic' was built under R version 4.3.3

I. TỔNG QUAN DỮ LIỆU

  1. Giới thiệu chung

    Sử dụng tập dữ liệu ” HMEQ” bao gồm 13 biến, với 5960 quan sát

    Nguồn: Dữ liệu được lấy trên trang Kaggle

    Các biến sử dụng trong tập dữ liệu

    BAD

    Tình trạng khách hàng

    0= Khách hàng trả được nợ( không nợ xấu)

    1= Khách hàng nợ xấu

    LOAN Số tiền khách hàng yêu cầu vay
    MORTDUE Số tiền phải trả cho khoản thế chấp hiện tại
    VALUE Giá trị hiện tại của tài sản( ngôi nhà)
    REASON

    Lý do yêu cầu vay

    Homelmp= sửa nhà

    DebtCon= gộp nợ

    JOB Nghề nghiệp
    YOJ Thời gian làm việc của khách hàng( đơn vị: năm)
    DEROG Số lượng ghi chép vào lịch sử tín dụng xấu
    DELINQ Số lượng khoản vay quá hạn
    CLAGE Thời gian của hạn mức tín dụng cũ nhất( đơn vị: tháng)
    NINQ Sô lượng tra cứu tín dụng gần đây
    CLNO Số lượng hạn mức tín dụng hiện tại
    DEBTINC Tỷ lệ nợ trên thu nhập
  2. Thống kê dữ liệu

# Import data: 
library(readr)
data <- read_csv("C:/Users/pc/Downloads/hmeq.csv")
## Rows: 5960 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (2): REASON, JOB
## dbl (11): BAD, LOAN, MORTDUE, VALUE, YOJ, DEROG, DELINQ, CLAGE, NINQ, CLNO, ...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
### Descriptive statistic
summary(data)
##       BAD              LOAN          MORTDUE           VALUE       
##  Min.   :0.0000   Min.   : 1100   Min.   :  2063   Min.   :  8000  
##  1st Qu.:0.0000   1st Qu.:11100   1st Qu.: 46276   1st Qu.: 66076  
##  Median :0.0000   Median :16300   Median : 65019   Median : 89236  
##  Mean   :0.1995   Mean   :18608   Mean   : 73761   Mean   :101776  
##  3rd Qu.:0.0000   3rd Qu.:23300   3rd Qu.: 91488   3rd Qu.:119824  
##  Max.   :1.0000   Max.   :89900   Max.   :399550   Max.   :855909  
##                                   NA's   :518      NA's   :112     
##     REASON              JOB                 YOJ             DEROG        
##  Length:5960        Length:5960        Min.   : 0.000   Min.   : 0.0000  
##  Class :character   Class :character   1st Qu.: 3.000   1st Qu.: 0.0000  
##  Mode  :character   Mode  :character   Median : 7.000   Median : 0.0000  
##                                        Mean   : 8.922   Mean   : 0.2546  
##                                        3rd Qu.:13.000   3rd Qu.: 0.0000  
##                                        Max.   :41.000   Max.   :10.0000  
##                                        NA's   :515      NA's   :708      
##      DELINQ            CLAGE             NINQ             CLNO     
##  Min.   : 0.0000   Min.   :   0.0   Min.   : 0.000   Min.   : 0.0  
##  1st Qu.: 0.0000   1st Qu.: 115.1   1st Qu.: 0.000   1st Qu.:15.0  
##  Median : 0.0000   Median : 173.5   Median : 1.000   Median :20.0  
##  Mean   : 0.4494   Mean   : 179.8   Mean   : 1.186   Mean   :21.3  
##  3rd Qu.: 0.0000   3rd Qu.: 231.6   3rd Qu.: 2.000   3rd Qu.:26.0  
##  Max.   :15.0000   Max.   :1168.2   Max.   :17.000   Max.   :71.0  
##  NA's   :580       NA's   :308      NA's   :510      NA's   :222   
##     DEBTINC        
##  Min.   :  0.5245  
##  1st Qu.: 29.1400  
##  Median : 34.8183  
##  Mean   : 33.7799  
##  3rd Qu.: 39.0031  
##  Max.   :203.3121  
##  NA's   :1267
head(data)
## # A tibble: 6 × 13
##     BAD  LOAN MORTDUE  VALUE REASON  JOB      YOJ DEROG DELINQ CLAGE  NINQ  CLNO
##   <dbl> <dbl>   <dbl>  <dbl> <chr>   <chr>  <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1     1  1100   25860  39025 HomeImp Other   10.5     0      0  94.4     1     9
## 2     1  1300   70053  68400 HomeImp Other    7       0      2 122.      0    14
## 3     1  1500   13500  16700 HomeImp Other    4       0      0 149.      1    10
## 4     1  1500      NA     NA <NA>    <NA>    NA      NA     NA  NA      NA    NA
## 5     0  1700   97800 112000 HomeImp Office   3       0      0  93.3     0    14
## 6     1  1700   30548  40320 HomeImp Other    9       0      0 101.      1     8
## # ℹ 1 more variable: DEBTINC <dbl>
str(data)
## spc_tbl_ [5,960 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ BAD    : num [1:5960] 1 1 1 1 0 1 1 1 1 1 ...
##  $ LOAN   : num [1:5960] 1100 1300 1500 1500 1700 1700 1800 1800 2000 2000 ...
##  $ MORTDUE: num [1:5960] 25860 70053 13500 NA 97800 ...
##  $ VALUE  : num [1:5960] 39025 68400 16700 NA 112000 ...
##  $ REASON : chr [1:5960] "HomeImp" "HomeImp" "HomeImp" NA ...
##  $ JOB    : chr [1:5960] "Other" "Other" "Other" NA ...
##  $ YOJ    : num [1:5960] 10.5 7 4 NA 3 9 5 11 3 16 ...
##  $ DEROG  : num [1:5960] 0 0 0 NA 0 0 3 0 0 0 ...
##  $ DELINQ : num [1:5960] 0 2 0 NA 0 0 2 0 2 0 ...
##  $ CLAGE  : num [1:5960] 94.4 121.8 149.5 NA 93.3 ...
##  $ NINQ   : num [1:5960] 1 0 1 NA 0 1 1 0 1 0 ...
##  $ CLNO   : num [1:5960] 9 14 10 NA 14 8 17 8 12 13 ...
##  $ DEBTINC: num [1:5960] NA NA NA NA NA ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   BAD = col_double(),
##   ..   LOAN = col_double(),
##   ..   MORTDUE = col_double(),
##   ..   VALUE = col_double(),
##   ..   REASON = col_character(),
##   ..   JOB = col_character(),
##   ..   YOJ = col_double(),
##   ..   DEROG = col_double(),
##   ..   DELINQ = col_double(),
##   ..   CLAGE = col_double(),
##   ..   NINQ = col_double(),
##   ..   CLNO = col_double(),
##   ..   DEBTINC = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
table(data$JOB)
## 
##     Mgr  Office   Other ProfExe   Sales    Self 
##     767     948    2388    1276     109     193

Tại tập dữ liệu này, biến ” BAD” là biến mục tiêu sẽ sử dụng trong bài báo cáo, mục đích hướng tới là quan sát thống kê các ảnh hưởng, sử tương quan của các biến khác tới biến mục tiêu. Cụ thể, biến “BAD” bao gồm giá trị 0 và 1

Trong đó:

1- Không có khả năng trả nợ

0- Có khả năng trả nợ

II. XỬ LÝ DỮ LIỆU

  1. Xử lý Missing Data
#sapply(data, function(data) sum(is.na(data)))
colSums(is.na(data))
##     BAD    LOAN MORTDUE   VALUE  REASON     JOB     YOJ   DEROG  DELINQ   CLAGE 
##       0       0     518     112     252     279     515     708     580     308 
##    NINQ    CLNO DEBTINC 
##     510     222    1267
sum(is.na(data))
## [1] 5271
attach(data) 
library(Amelia)
missmap(data, col = c("brown", "pink"), legend = TRUE)
## Warning: Unknown or uninitialised column: `arguments`.
## Unknown or uninitialised column: `arguments`.
## Warning: Unknown or uninitialised column: `imputations`.

Ta thấy số lượng Missing data tương đối nhiều ( điển hình biến debtinc lên tới 1267 giá trị bị thiếu), chiếm phần lớn so với tổng quan sát mà chúng ta sử dụng. Do vậy, chúng ta sẽ không xóa toàn bộ các giá trị thiếu, mà sẽ thay thế các NA thành giá trị như mean, mode và median. Cụ thể thay thế như thế nào, ta sẽ sử dụng đồ thị Histogram để xác định. Dưới đây là histogram cho từng biến

# Vẽ histogram cho biến DEBTINC
hist(data$DEBTINC, main = "Histogram of DEBTINC", xlab = "DEBTINC", ylab = "Frequency", col = "skyblue", border = "black")

# Vẽ histogram cho biến NINQ
hist(data$NINQ, main = "Histogram of NINQ", xlab = "NINQ", ylab = "Frequency", col = "skyblue", border = "black")

#DEROG
hist(data$DEROG, main = "Histogram of DEROG", xlab = "DEROG", ylab = "Frequency", col = "skyblue", border = "black")

#VALUE
hist(data$VALUE, main = "Histogram of VALUE", xlab = "VALUE", ylab = "Frequency", col = "skyblue", border = "black")

#CLNO
hist(data$CLNO, main = "Histogram of CLNO", xlab = "CLNO", ylab = "Frequency", col = "skyblue", border = "black")

#CLAGE
hist(data$CLAGE, main = "Histogram of CLAGE", xlab = "CLAGE", ylab = "Frequency", col = "skyblue", border = "black")

#YOJ
hist(data$YOJ, main = "Histogram of YOJ", xlab = "YOJ", ylab = "Frequency", col = "skyblue", border = "black")

#DELINQ
hist(data$DELINQ, main = "Histogram of DELINQ", xlab = "DELINQ", ylab = "Frequency", col = "skyblue", border = "black")

#LOAN
hist(data$LOAN, main = "Histogram of LOAN", xlab = "LOAN", ylab = "Frequency", col = "skyblue", border = "black")

#MORTDUE
hist(data$MORTDUE, main = "Histogram of MORYDUE", xlab = "MORTDUE", ylab = "Frequency", col = "skyblue", border = "black")

Trong đó biến JOB sẽ thay thế bằng giá trị mode, và các biến còn lại thay thế bằng giá trị median

# Điền vào giá trị null của biến REASON bằng "Other reason"
data$REASON[is.na(data$REASON)] <- "Other reason"

# Điền vào giá trị null của biến JOB bằng giá trị mode
library(dplyr)
mode_job <- data$JOB %>% na.omit() %>%table() %>%     names() %>%   as.character() %>%  
  .[which.max(table(.))]  
data <- data %>%
  mutate(JOB = ifelse(is.na(JOB), mode_job, JOB))
# Thay thế các giá trị NA của biến JOB bằng mode_value
data$JOB[is.na(data$JOB)] <- mode_job

# DEROG
data <- data %>%
  mutate(DEROG = ifelse(is.na(DEROG), median(DEROG, na.rm = TRUE), DEROG))

# DELINQ
data <- data %>%
  mutate(DELINQ = ifelse(is.na(DELINQ), median(DELINQ, na.rm = TRUE), DELINQ))

##
median(data$MORTDUE, na.rm = TRUE)
## [1] 65019
data<- data %>% 
  mutate(MORTDUE = ifelse(is.na(MORTDUE), median(MORTDUE, na.rm = TRUE), MORTDUE))
##YOJ
data <- data %>%
  mutate(YOJ = ifelse(is.na(YOJ), median(YOJ, na.rm = TRUE), YOJ))
## CLNO
data <- data %>%
  mutate(CLNO = ifelse(is.na(CLNO), median(CLNO, na.rm = TRUE), CLNO))
## CLAGE
data <- data %>%
  mutate(CLAGE = ifelse(is.na(CLAGE), median(CLAGE, na.rm = TRUE), CLAGE))
## NINQ
data <- data %>%
  mutate(NINQ = ifelse(is.na(NINQ), median(CLNO, na.rm = TRUE), NINQ))
##DEBTINC
data <- data %>%
  mutate(DEBTINC = ifelse(is.na(DEBTINC), median(DEBTINC, na.rm = TRUE), DEBTINC))
#VALUE
data <- data %>%
  mutate(VALUE = ifelse(is.na(VALUE), median(VALUE, na.rm = TRUE), VALUE))
head(data)
## # A tibble: 6 × 13
##     BAD  LOAN MORTDUE   VALUE REASON  JOB     YOJ DEROG DELINQ CLAGE  NINQ  CLNO
##   <dbl> <dbl>   <dbl>   <dbl> <chr>   <chr> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1     1  1100   25860  39025  HomeImp Other  10.5     0      0  94.4     1     9
## 2     1  1300   70053  68400  HomeImp Other   7       0      2 122.      0    14
## 3     1  1500   13500  16700  HomeImp Other   4       0      0 149.      1    10
## 4     1  1500   65019  89236. Other … Mgr     7       0      0 173.     20    20
## 5     0  1700   97800 112000  HomeImp Offi…   3       0      0  93.3     0    14
## 6     1  1700   30548  40320  HomeImp Other   9       0      0 101.      1     8
## # ℹ 1 more variable: DEBTINC <dbl>
colSums(is.na(data))
##     BAD    LOAN MORTDUE   VALUE  REASON     JOB     YOJ   DEROG  DELINQ   CLAGE 
##       0       0       0       0       0       0       0       0       0       0 
##    NINQ    CLNO DEBTINC 
##       0       0       0
missmap(data, col = c("brown", "pink"), legend = TRUE)
## Warning: Unknown or uninitialised column: `arguments`.
## Unknown or uninitialised column: `arguments`.
## Warning: Unknown or uninitialised column: `imputations`.

Sau khi thay thế các giá trị NA thành giá trị mode và median, kiểm tra lại các giá trị còn thiếu, đây là kết quả sau cùng, chúng ta đã xử lý được các giá trị thiếu.

2. Kiểm tra và xử lý các giá tị ngoại lai Outliers

par(mfrow = c(2,3))
boxplot(data$LOAN, main = "LOAN")
boxplot(data$MORTDUE, main = "MORTDUE")
boxplot(data$VALUE, main = "VALUE")
boxplot(data$YOJ, main = "YOJ")
boxplot(data$DEROG, main = "DEROG")
boxplot(data$DELINQ, main = "DELINQ")

boxplot(data$CLAGE, main = "CLAGE")
boxplot(data$NINQ, main = "NINQ")
boxplot(data$CLNO, main = "CLNO")
boxplot(data$DEBTINC, main = "DEBTINC")

summary(LOAN)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1100   11100   16300   18608   23300   89900
minLOAN=quantile(LOAN,probs=0.25) - 1.5*IQR(LOAN)
maxLOAN=quantile(LOAN,probs=0.75) + 1.5*IQR(LOAN)
LOAN[LOAN> maxLOAN|LOAN<minLOAN]= mean(LOAN)
boxplot(LOAN) 

summary(MORTDUE)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    2063   46276   65019   73761   91488  399550     518
minMORTDUE= quantile(MORTDUE, probs = 0.25, na.rm = TRUE) - 1.5 * IQR(MORTDUE, na.rm = TRUE)
maxMORTDUE= quantile(MORTDUE, probs = 0.75, na.rm = TRUE) + 1.5 * IQR(MORTDUE, na.rm = TRUE)
MORTDUE[MORTDUE> maxMORTDUE|MORTDUE<minLOAN]= mean(MORTDUE)
boxplot(MORTDUE)

summary(VALUE)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    8000   66076   89236  101776  119824  855909     112
minVALUE=quantile(VALUE,probs=0.25, na.rm = TRUE) - 1.5*IQR(VALUE, na.rm = TRUE)
maxVALUE=quantile(VALUE,probs=0.75, na.rm = TRUE) + 1.5*IQR(VALUE, na.rm = TRUE)
VALUE[VALUE> maxVALUE|VALUE<minVALUE]= mean(VALUE)
boxplot(VALUE) 

summary(CLAGE)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0   115.1   173.5   179.8   231.6  1168.2     308
minCLAGE=quantile(CLAGE,probs=0.25, na.rm = TRUE) - 1.5*IQR(CLAGE, na.rm = TRUE)
maxCLAGE=quantile(CLAGE,probs=0.75, na.rm = TRUE) + 1.5*IQR(CLAGE, na.rm = TRUE)
CLAGE[CLAGE> maxCLAGE|CLAGE<minCLAGE]= mean(CLAGE)
boxplot(CLAGE)

summary(DEBTINC)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
##   0.5245  29.1400  34.8183  33.7799  39.0031 203.3121     1267
minDEBTINC=quantile(DEBTINC,probs=0.25, na.rm = TRUE) - 1.5*IQR(DEBTINC, na.rm = TRUE)
maxDEBTINC=quantile(DEBTINC,probs=0.75, na.rm = TRUE) + 1.5*IQR(DEBTINC, na.rm = TRUE)
DEBTINC[DEBTINC>maxDEBTINC|DEBTINC<minDEBTINC]= mean(DEBTINC)
boxplot(DEBTINC) 

##
summary(YOJ)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   0.000   3.000   7.000   8.922  13.000  41.000     515
minYOJ=quantile(YOJ,probs=0.25, na.rm = TRUE) - 1.5*IQR(YOJ, na.rm = TRUE)
maxYOJ=quantile(YOJ,probs=0.75, na.rm = TRUE) + 1.5*IQR(YOJ, na.rm = TRUE)
YOJ[YOJ> maxYOJ|YOJ<minLOAN]= mean(YOJ)
boxplot(YOJ)

summary(DEROG)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##  0.0000  0.0000  0.0000  0.2546  0.0000 10.0000     708
minDEROG=quantile(DEROG,probs=0.25, na.rm = TRUE) - 1.5*IQR(DEROG, na.rm = TRUE)
maxDEROG=quantile(DEROG,probs=0.75, na.rm = TRUE) + 1.5*IQR(DEROG, na.rm = TRUE)
DEROG[DEROG> maxDEROG|DEROG<minDEROG]= mean(DEROG)
boxplot(DEROG)

summary(DELINQ)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##  0.0000  0.0000  0.0000  0.4494  0.0000 15.0000     580
minDELINQ=quantile(DELINQ,probs=0.25, na.rm = TRUE) - 1.5*IQR(DELINQ, na.rm = TRUE)
maxDELINQ=quantile(DELINQ,probs=0.75, na.rm = TRUE) + 1.5*IQR(DELINQ, na.rm = TRUE)
DELINQ[DELINQ> maxDELINQ|DELINQ<minDELINQ]= mean(DELINQ)
boxplot(DELINQ)

summary(NINQ)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   0.000   0.000   1.000   1.186   2.000  17.000     510
minNINQ=quantile(NINQ,probs=0.25, na.rm = TRUE) - 1.5*IQR(NINQ, na.rm = TRUE)
maxNINQ=quantile(NINQ,probs=0.75, na.rm = TRUE) + 1.5*IQR(NINQ, na.rm = TRUE)
NINQ[NINQ> maxNINQ|NINQ<minNINQ]= mean(NINQ)
boxplot(NINQ)

summary(CLNO)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0    15.0    20.0    21.3    26.0    71.0     222
minCLNO=quantile(CLNO,probs=0.25, na.rm = TRUE) - 1.5*IQR(CLNO, na.rm = TRUE)
maxCLNO=quantile(CLNO,probs=0.75, na.rm = TRUE) + 1.5*IQR(CLNO, na.rm = TRUE)
CLNO[CLNO> maxLOAN|CLNO<minCLNO]= mean(CLNO)
boxplot(CLNO)

Tính toán giá trị min của từng biến bằng cách lấy phân vị 25% (Q1) của biến đó và trừ đi 1.5 lần khoảng IQR(khoảng tứ phân vị= Q3-Q1). Đây là giá trị dưới ngưỡng dưới để xác định outliers.

Tương tự tính max của biến bằng cách lấy phân vị 75% (Q3) của biến và cộng thêm 1.5 lần khoảng IQR của LOAN. Đây là giá trị trên ngưỡng trên để xác định outliers.

Sau đó, thay thế các giá trị của biến nằm ngoài khoảng [min, max] bằng giá trị trung bình .

Việc loại bỏ outliers giúp làm sạch dữ liệu và cải thiện chất lượng của các phân tích và mô hình học máy sau này. Bằng cách thay thế các giá trị outliers bằng giá trị trung bình của biến, chúng ta có thể giảm thiểu ảnh hưởng của các giá trị ngoại lệ lên các phân tích thống kê và mô hình dự đoán. Điều này giúp tăng độ chính xác và đáng tin cậy của kết quả cuối cùng.

III. TRỰC QUAN HÓA DỮ LIỆU

####1. Bad rate
# Data Overview
ggplot(data, aes(BAD, fill = BAD)) +
  geom_bar() +
  theme(legend.position = 'none')
## Warning: The following aesthetics were dropped during statistical transformation: fill
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
##   the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
##   variable into a factor?

table(BAD)
## BAD
##    0    1 
## 4771 1189
round(prop.table(table(BAD)),3)
## BAD
##     0     1 
## 0.801 0.199
# xem tỉ lệ bad-good
table(data$Bad)
## Warning: Unknown or uninitialised column: `Bad`.
## < table of extent 0 >
round(prop.table(table(data$Bad)),3)
## Warning: Unknown or uninitialised column: `Bad`.
## numeric(0)

Đây là tỷ lệ giữa giá trị 0 và 1 của biến ” BAD”, có tỷ lệ BAD= 1 chiếm khoảng 19,9%

### xem mối liên hệ với biến bad
plot_dt <- data
plot_dt$BAD <- factor(plot_dt$BAD, labels = c("Paid", "Defaulted"))
#Disable exponential notation in graphs
options(scipen = 999)
  1. Ma trận tương quan giữa các biến
library(ggcorrplot)
## Warning: package 'ggcorrplot' was built under R version 4.3.3
numericVarName <- names(which(sapply(data, is.numeric)))
corr <- cor(data[,numericVarName], use = 'pairwise.complete.obs')
corr
##                  BAD         LOAN      MORTDUE        VALUE         YOJ
## BAD      1.000000000 -0.075098920 -0.046186035 -0.036492382 -0.05395626
## LOAN    -0.075098920  1.000000000  0.216380410  0.331522435  0.09687850
## MORTDUE -0.046186035  0.216380410  1.000000000  0.788735625 -0.07620054
## VALUE   -0.036492382  0.331522435  0.788735625  1.000000000  0.01363839
## YOJ     -0.053956262  0.096878497 -0.076200545  0.013638392  1.00000000
## DEROG    0.269921278  0.006995633 -0.047123015 -0.043807846 -0.05772929
## DELINQ   0.346503256 -0.028869500  0.003580167 -0.008158179  0.05158005
## CLAGE   -0.165614000  0.088237005  0.129798674  0.169535991  0.18620260
## NINQ     0.012298953 -0.051559758 -0.021913110 -0.062052290 -0.09205959
## CLNO    -0.004542564  0.074317173  0.318515335  0.265029453  0.03281478
## DEBTINC  0.154544141  0.068937824  0.134575084  0.113079575 -0.04648154
##                DEROG       DELINQ       CLAGE          NINQ          CLNO
## BAD      0.269921278  0.346503256 -0.16561400  0.0122989530 -0.0045425643
## LOAN     0.006995633 -0.028869500  0.08823700 -0.0515597576  0.0743171733
## MORTDUE -0.047123015  0.003580167  0.12979867 -0.0219131098  0.3185153351
## VALUE   -0.043807846 -0.008158179  0.16953599 -0.0620522898  0.2650294529
## YOJ     -0.057729293  0.051580048  0.18620260 -0.0920595941  0.0328147754
## DEROG    1.000000000  0.171285977 -0.07948222  0.0450988433  0.0520749270
## DELINQ   0.171285977  1.000000000  0.02632362 -0.0437902468  0.1611534330
## CLAGE   -0.079482222  0.026323621  1.00000000 -0.0495990038  0.2338015567
## NINQ     0.045098843 -0.043790247 -0.04959900  1.0000000000  0.0002945141
## CLNO     0.052074927  0.161153433  0.23380156  0.0002945141  1.0000000000
## DEBTINC  0.020541539  0.048307219 -0.04074138 -0.0637962094  0.1598499744
##             DEBTINC
## BAD      0.15454414
## LOAN     0.06893782
## MORTDUE  0.13457508
## VALUE    0.11307958
## YOJ     -0.04648154
## DEROG    0.02054154
## DELINQ   0.04830722
## CLAGE   -0.04074138
## NINQ    -0.06379621
## CLNO     0.15984997
## DEBTINC  1.00000000
ggcorrplot(corr, lab = TRUE)

Trong thống kê mô hình, đa cộng tuyến là hiện tượng tránh để xuất hiện, vì nó có thể làm giảm đáng kể độ chính xác của ước lượng cũng như làm yếu đi ý nghĩa thống kê của mô hình. Bởi vậy cần xem xét sự tương quan giữa các biến có trong tập dữ liệu. Sử dụng biểu đồ nhiệt để quan sát. Ta thấy MORTDUE và VALUE có hệ số tương quan cao.

Xem tương quan giữa VALUe và mortdue

#VALUE vs MORTDUE
library(cowplot)
## Warning: package 'cowplot' was built under R version 4.3.2
## 
## Attaching package: 'cowplot'
## The following object is masked from 'package:ggthemes':
## 
##     theme_map
## The following object is masked from 'package:lubridate':
## 
##     stamp
library(plotly)
## Warning: package 'plotly' was built under R version 4.3.3
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following objects are masked from 'package:plyr':
## 
##     arrange, mutate, rename, summarise
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
fit <- lm(plot_dt$MORTDUE~plot_dt$VALUE)
scatter1 <- ggplot(plot_dt, aes(VALUE, MORTDUE, color = BAD)) +
  geom_count(position = "jitter", alpha = 0.6, size = 1.6, show.legend = F) +
  geom_line(aes(y = predict(fit)), col = "brown", size = 0.9) +
  ylim(c(0, 225000)) +
  scale_x_log10() +
  labs(title = "Property value vs Outstanding mortgage", x = "Property value", y = "Outstanding mortgage", size = "Size", color = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 11), text = element_text(family = "serif"),panel.grid = element_blank()) +
  scale_color_manual(values = c("steelblue", "brown"))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
#NINQ vs CLNO
fit2 <- lm(plot_dt$CLNO~plot_dt$NINQ)
scatter2 <- ggplot(plot_dt, aes(NINQ, CLNO, color = BAD)) +
  geom_count(position = "jitter", alpha = 0.6, size = 1.6) +
  labs(title = "Recent credit inquiries vs Total credit lines", x = "Recent inquiries", y = "Total credit lines", size = "Size", color = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 11), text = element_text(family = "serif"),
        panel.grid = element_blank()) +
  scale_color_manual(values = c("steelblue", "brown"))
#Aggregate plots
plot_grid(scatter1, scatter2)
## Warning: Removed 69 rows containing non-finite values (`stat_sum()`).
## Warning: Removed 18 rows containing missing values (`geom_line()`).

Sử dụng biểu đồ quan sát mối tương quan giữa MORTDUE- VALUE và NINQ- CLNO

Có một mối tương quan dương mạnh mẽ theo cấp số nhân giữa giá trị tài sản hiện tại của khách hàng và các khoản thế chấp chưa thanh toán. Vì vậy, chúng ta không được để cả 2 biến này cùng xuất hiện trong mô hình, cần loại bỏ 1 trong 2 biến để tránh trường hợp đa cộng tuyến và cải thiện hiệu suất của mô hình cũng như phân tích thống kê.

 Mặt khác, có mối tương quan cực kỳ yếu giữa các yêu cầu tín dụng gần đây của khách hàng và tổng hạn mức tín dụng. Điều này có nghĩa là việc bao gồm NINQ và CLNO cùng nhau sẽ không gây nguy hiểm cho độ chính xác của mô hình.

# Xóa bỏ biến " MORTDUE"
plot_dt <- subset(plot_dt, select = -c(MORTDUE))
  1. So sánh các yếu tố theo biến mục tiêu
#BAD vs DELINQ
bar1 <- ggplot(plot_dt, aes(BAD, DELINQ, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Delinquent Credit Lines", x = "", y = "Delinquent Credit Lines", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))
#BAD vs DEBTINC
bar2 <- ggplot(plot_dt, aes(BAD, DEBTINC, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Debt-Income Ratio", x = "", y = "Debt:Income", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown")) 
#BAD vs DEROG
bar3 <- ggplot(plot_dt, aes(BAD, DEROG, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Derogatory Reports", x = "", y = "Derogatory Reports", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))  
#BAD vs CLAGE
bar4 <- ggplot(plot_dt, aes(BAD, CLAGE, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Oldest Credit Line", x = "", y = "Age", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))  
#BAD vs LOAN
bar5 <- ggplot(plot_dt, aes(BAD, LOAN, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Loan Request Amount", x = "", y = "Loan", color = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))
#BAD vs NINQ
bar6 <- ggplot(plot_dt, aes(BAD, NINQ, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Recent Credit Inquiries", x = "", y = "Recent Inquiries", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))
#BAD vs CLNO
bar7 <- ggplot(plot_dt, aes(BAD, CLNO, fill = BAD)) +
  geom_bar(stat = "identity", show.legend = F, width = 0.4) +
  labs(title = "Total Credit Lines", x = "", y = "Credit Lines", fill = "Status") +
  theme_bw() +
  theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 10), text = element_text(family = "serif"),
        aspect.ratio = 2/1, panel.grid = element_blank()) +
  scale_fill_manual(values = c("steelblue", "brown"))
library(cowplot)
library(plotly)
plot_grid(bar1, bar3)

Khi một người có nhiều khoản vay quá hạn(DELINQ) hoặc bị ghi chép vào lịch sử tín dụng xấu(DEROG), họ có thể gặp khó khăn trong việc trả nợ và vay được thêm tiền. Điều này có thể dẫn đến một vòng lặp tiêu cực khi họ không thể trả nợ hiện tại và tiếp tục tích lũy thêm nợ, tạo ra một môi trường không thuận lợi cho việc trả nợ. Do đó, người không có khả năng trả nợ thường có nhiều khoản vay quá hạn hơn và bị ghi chép vào lịch sử tín dụng xấu.

plot_grid(bar4, bar6, bar7, ncol = 3, nrow = 1)

Một cách hiểu đơn giản, những người vay đã trả nợ thường được ngân hàng đánh giá là đáng tin cậy hơn, do đó họ có lịch sử tín dụng lâu hơn(CLAGE càng lớn thì cho thấy lịch sử tín dụng dài và ổn định), thực hiện nhiều lần tra cứu tín dụng gần đây hơn(NINQ) và thường có nhiều tài khoản tín dụng hơn so với khách hàng không trả nợ.

Các biến CLAGE, NINQ và CLNO trong bộ dữ liệu có thể có các ý nghĩa như sau:

1. CLAGE (Age of the oldest credit line in months): đo lường sự ổn định và lịch sử tín dụng của người vay. Một CLAGE lớn hơn có thể cho thấy một lịch sử tín dụng dài hạn và ổn định.

2. NINQ (Number of recent credit inquiries): Biến này đếm số lần kiểm tra tín dụng gần đây. Số lượng kiểm tra tín dụng cao có thể cho thấy người vay đang tìm kiếm vay nợ hoặc mở thêm tài khoản tín dụng mới, có thể tăng nguy cơ về khả năng trả nợ.

3. CLNO (Number of existing credit lines): Biến này đếm số lượng tài khoản tín dụng hiện có của người vay. Nó có thể phản ánh khả năng quản lý tài chính của họ, với số lượng tài khoản lớn có thể gợi ý đến việc họ có kinh nghiệm trong việc quản lý nhiều khoản vay hoặc tăng cường tài chính, trong khi số lượng tài khoản ít có thể cho thấy họ không có kinh nghiệm hoặc có nhiều nguy cơ hơn khi vay nợ.

plot_grid(bar2, bar5)

Những người vay mà không gặp khó khăn về trả nợ thì  có tỉ lệ nợ thu nhập(DEBTINC) và số tiền vay(LOAN) cao hơn đáng kể, vì họ có khả năng tiếp tục vay từ ngân hàng dựa trên lịch sử tín dụng tích cực, với các khoản vay trước đó được trả đúng hạn và không có nợ xấu=> họ trở nên đáng tin cậy hơn trong mắt ngân hàng nên được vay nhiều hơn (mà không cần phải làm đơn vay mới).

1. Người vay có DEBTINC cao hơn có thể có khả năng tài chính tốt hơn, tức là thu nhập của họ đủ để chi trả một lượng nợ lớn hơn mà không làm ảnh hưởng đến tỷ lệ nợ thu nhập.

2. Số tiền vay cao hơn trong biến LOAN có thể phản ánh nhu cầu tài chính lớn hơn từ người vay. Họ có thể muốn vay một số tiền lớn để đầu tư vào dự án lớn, mua nhà mới hoặc thậm chí là trả nợ cho các khoản vay khác.

Tóm lại, các giá trị cao của DEBTINC và LOAN có thể phản ánh sự ổn định tài chính, nhu cầu tài chính lớn và lịch sử tín dụng tích cực của người vay.

### Bivariate Analysis
# Cài đặt thư viện ggplot2 nếu chưa có
# Nhập thư viện ggplot2
library(ggplot2)

# Vẽ biểu đồ boxplot
#LOAN- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = LOAN, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "LOAN") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

# MORTDUE- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = MORTDUE, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "MORTDUE") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()
## Warning: Removed 752 rows containing non-finite values (`stat_boxplot()`).

#VALUE- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = VALUE, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "VALUE") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#YOJ- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = YOJ, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "YOJ") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#DEGROG- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = DEROG, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "DEROG") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#DELINQ-BAD
ggplot(plot_dt, aes(x = factor(BAD), y = DELINQ, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "DELINQ") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#CLAGE-BAD
ggplot(plot_dt, aes(x = factor(BAD), y = MORTDUE, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "MORTDUE") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()
## Warning: Removed 752 rows containing non-finite values (`stat_boxplot()`).

#NINQ- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = NINQ, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "NINQ") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#CLNO- BAD
ggplot(plot_dt, aes(x = factor(BAD), y = CLNO, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "CLNO") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()

#DEBTINC-BAD
ggplot(plot_dt, aes(x = factor(BAD), y = DEBTINC, fill = factor(BAD))) +
  geom_boxplot() +
  labs(x = "BAD", y = "DEBTINC") +
  scale_fill_manual(values = c("blue", "red")) +
  theme_minimal()


## Tương quan biến định tính và BAD
#REASON- BAD
# Vẽ biểu đồ cột chồng
ggplot(plot_dt, aes(x = REASON, fill = factor(BAD))) +
  geom_bar(position = "fill") +
  labs(x = "Reason", y = "Proportion", fill = "BAD") +
  scale_y_continuous(labels = scales::percent) +
  theme_minimal()

#JOB- BAD
ggplot(plot_dt, aes(x = JOB, fill = factor(BAD))) +
  geom_bar(position = "fill") +
  labs(x = "Job", y = "Proportion", fill = "BAD") +
  scale_y_continuous(labels = scales::percent) +
  theme_minimal()

  1. Đánh giá tầm quan trọng của các biến đến biến “BAD”

    4.1. Classification Tree

    Sử dụng mô hình cây phân loại Classification Tree để đánh giá tầm quan trọng của các biến có trong tập dữ liệu đối với biến ” BAD”, tức là xác định yếu tố quan trọng nhất từ khách hàng ảnh hưởng tới xác suất vỡ nợ của họ. Điều này sẽ giúp ngân hàng và các tổ chức tín dụng hiểu rõ hơn về nguyên nhân dẫn đến vỡ nợ, từ đó giúp đưa ra quyết định cho vay cũng như quản lý rủi ro

    Trước tiên tạo biến giả cho các biến định tính bằng one- hot

## Cây quyến định Regression Tree
# One-hot encoding( Tạo biến giải bằng one-hot)
library(caret)
## Loading required package: lattice
## 
## Attaching package: 'caret'
## The following object is masked from 'package:purrr':
## 
##     lift
dummy <- dummyVars(" ~ .", data = plot_dt)
data_new <- data.frame(predict(dummy, newdata = data))
## Warning in model.frame.default(Terms, newdata, na.action = na.action, xlev =
## object$lvls): variable 'BAD' is not a factor
names(data_new)
##  [1] "BAD"                "LOAN"               "VALUE"             
##  [4] "REASONDebtCon"      "REASONHomeImp"      "REASONOther.reason"
##  [7] "JOBMgr"             "JOBOffice"          "JOBOther"          
## [10] "JOBProfExe"         "JOBSales"           "JOBSelf"           
## [13] "YOJ"                "DEROG"              "DELINQ"            
## [16] "CLAGE"              "NINQ"               "CLNO"              
## [19] "DEBTINC"
# Chuyển biến BAD thành hai cấp
data_new$BAD <- as.factor(data_new$BAD)

set.seed(26)

# Huấn luyện mô hình sử dụng phương pháp rpart
model <- train(BAD ~ ., data = data_new, method = "rpart")
model
## CART 
## 
## 5960 samples
##   18 predictor
##    2 classes: '0', '1' 
## 
## No pre-processing
## Resampling: Bootstrapped (25 reps) 
## Summary of sample sizes: 5960, 5960, 5960, 5960, 5960, 5960, ... 
## Resampling results across tuning parameters:
## 
##   cp          Accuracy   Kappa    
##   0.03448276  0.8667946  0.5175924
##   0.04205214  0.8608695  0.4837222
##   0.08326325  0.8319534  0.2920002
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was cp = 0.03448276.
# Đánh giá tầm quan trọng của các biến
rankVars <- varImp(model)
print(rankVars)
## rpart variable importance
## 
##                    Overall
## DEBTINC            100.000
## DELINQ              57.697
## DEROG               55.887
## CLAGE               30.635
## LOAN                19.685
## NINQ                 9.108
## CLNO                 5.099
## VALUE                0.000
## JOBMgr               0.000
## JOBSales             0.000
## JOBOther             0.000
## JOBOffice            0.000
## JOBSelf              0.000
## YOJ                  0.000
## JOBProfExe           0.000
## REASONHomeImp        0.000
## REASONOther.reason   0.000
## REASONDebtCon        0.000
# Vẽ biểu đồ tầm quan trọng của các biến
plot(rankVars, top = 18, main = 'Variable Importance')

Theo mô hình này, mức độ quan trọng của các biến đối với biến “BAD” lần lượt là: DEBTINC, DELINQ, DEROG, CLAGE, LOAN, NINQ, CLNO.

4.2. Random Forest

Mô hình Random Forest là một phương pháp học máy dựa trên việc xây dựng nhiều cây quyết định (decision trees) và kết hợp kết quả từ tất cả các cây để đưa ra kết quả cuối cùng giúp xác định các biến quan trọng. Như vậy trong phần này 2 mô hình đang sử dụng cùng mục đích, tìm hiểu yếu tố nào ảnh hưởng nhiều nhất tới rủi ro của khách hàng.

## Mô hình Random Forest
# Cài đặt và nhập thư viện
install.packages("randomForest")
## Installing package into 'C:/Users/pc/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'randomForest' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\pc\AppData\Local\Temp\RtmpGCDKUA\downloaded_packages
library(randomForest)
## Warning: package 'randomForest' was built under R version 4.3.3
## randomForest 4.7-1.1
## Type rfNews() to see new features/changes/bug fixes.
## 
## Attaching package: 'randomForest'
## The following object is masked from 'package:psych':
## 
##     outlier
## The following object is masked from 'package:ggplot2':
## 
##     margin
## The following object is masked from 'package:dplyr':
## 
##     combine
# Tạo mô hình RandomForest
rf_model <- randomForest(BAD ~ ., data = data_new)

# Tính toán tầm quan trọng của các biến
importance <- importance(rf_model)

# Sắp xếp theo thứ tự giảm dần
sorted_importance <- sort(importance, decreasing = TRUE)
rf<-varImp(rf_model)
print(rf)
##                       Overall
## LOAN               175.170591
## VALUE              188.422743
## REASONDebtCon       20.279171
## REASONHomeImp       19.360510
## REASONOther.reason   9.082943
## JOBMgr              18.282091
## JOBOffice           20.629889
## JOBOther            23.748949
## JOBProfExe          17.719019
## JOBSales            11.409519
## JOBSelf             10.284756
## YOJ                124.115807
## DEROG              106.259406
## DELINQ             186.608274
## CLAGE              203.374751
## NINQ                82.352444
## CLNO               160.910159
## DEBTINC            456.829048
# Vẽ biểu đồ tầm quan trọng của các biến
plot(sorted_importance, main = 'Variable Importance', ylab = "", xlab = "Variable Index")
lines(sorted_importance) 

Theo mô hình này, mức độ quan trọng của các biến đối với biến “BAD” lần lượt là: DEBTINC, CLAGE, VALUE, DELINQ, LOAN, CLNO

Như vậy, từ 2 mô hình trên, ta thấy rằng DEBTINC là biến quan trọng nhất, hay yếu tố Tỷ lệ nợ trên thu nhất có ảnh hưởng lớn nhất đối với xác suất vỡ nợ của khách hàng

IV. TỔNG KẾT

Như vậy, việc thống kê, trực quan hóa dữ liệu là bước làm giúp ích cho quá trình nhận định và đưa ra quyết định của các tổ chức tài chính. Điển hình là các ngân hàng, dựa vào các yếu tố của các cá nhân khách hàng để đánh giá, dự báo về xác suất vỡ nợ của họ, từ đó có cái nhìn tốt hơn đối với rủi ro tín dụng, giúp các ngân hàng đưa ra quyết định cho vay đối với khách hàng nào, giúp giảm thiểu rủi ro cho ngân hàng, tăng doanh thu, lợi nhuận, góp phần vào việc phát triển nền kinh tế