library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.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(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(scales)
## Warning: package 'scales' was built under R version 4.4.3
df <- Loan_default %>%
  select(Default, CreditScore, Income, LoanAmount, LoanTerm, LoanPurpose)
df$Default <- as.factor(df$Default)
df$LoanPurpose <- as.factor(df$LoanPurpose)

#Tổng quan dữ liệu

##Giới thiệu về bộ dữ liệu

Bộ dữ liệu Loan Default Prediction Dataset được cung cấp trên nền tảng Kaggle với mục tiêu hỗ trợ phân tích và dự đoán khả năng khách hàng vỡ nợ khoản vay (loan default) dựa trên các thông tin nhân khẩu học và đặc điểm của khoản vay. Đây là một bộ dữ liệu mô phỏng thực tế trong lĩnh vực tín dụng tiêu dùng, nơi các tổ chức tài chính cần đánh giá rủi ro trước khi đưa ra quyết định cho vay. Bộ dữ liệu có 255.347 quan sát và 18 biến, bao gồm nhiều nhóm thông tin như: đặc điểm cá nhân (tuổi, thu nhập, nghề nghiệp), lịch sử tín dụng (credit score, số lần trễ hạn), thông tin khoản vay (số tiền vay, thời hạn vay, mục đích vay), và biến kết quả (default: có vỡ nợ hay không).

##Cấu trúc bộ dữ liệu

dim(Loan_default)
## [1] 255347     18

Tên bộ dữ liệu: Loan Default Prediction Dataset Nguồn dữ liệu: Nền tảng Kaggle Số lượng quan sát: 255.347 số biến: 18 Dạng dữ liệu: Định tính và định lượng

##Mục tiêu nghiên cứu

Đề tài “Phân tích các yếu tố ảnh hưởng đến khả năng vỡ nợ của khách hàng vay” được thực hiện nhằm nhận diện và đo lường mức độ tác động của các yếu tố tài chính và đặc điểm khoản vay đến xác suất khách hàng rơi vào trạng thái vỡ nợ. Cụ thể, nghiên cứu hướng đến việc phân tích sự khác biệt về hành vi vỡ nợ giữa các nhóm khách hàng khác nhau, đồng thời đánh giá vai trò của các biến quan trọng như điểm tín dụng (CreditScore), thu nhập (Income), số tiền vay (LoanAmount) và thời hạn vay (LoanTerm) trong việc dự đoán khả năng vỡ nợ. Thông qua việc ứng dụng các kỹ thuật thống kê mô tả, kiểm định giả thuyết và mô hình hồi quy logistic bằng ngôn ngữ R, đề tài không chỉ giúp xác định yếu tố nào ảnh hưởng mạnh nhất đến khả năng vỡ nợ của khách hàng vay mà còn cung cấp cơ sở thực tiễn để các tổ chức tài chính tối ưu hóa quy trình thẩm định tín dụng, quản trị rủi ro và ra quyết định cho vay một cách hiệu quả hơn.

##Kiểm tra bộ dữ liệu

# kiểm tra dữ liệu bị thiếu
colSums(is.na(Loan_default))
##         LoanID            Age         Income     LoanAmount    CreditScore 
##              0              0              0              0              0 
## MonthsEmployed NumCreditLines   InterestRate       LoanTerm       DTIRatio 
##              0              0              0              0              0 
##      Education EmploymentType  MaritalStatus    HasMortgage  HasDependents 
##              0              0              0              0              0 
##    LoanPurpose    HasCoSigner        Default 
##              0              0              0
# kiểm tra dữ liệu bị trùng lặp
sum(duplicated(Loan_default))
## [1] 0

Sau quá trình kiểm tra kết quả cho thấy không có dữ liệu bị trùng lặp, không có dữ liệu nào bị thiếu

0.1 Ý nghĩa của các biến

variable_description <- data.frame(
  Variable = c("LoanID", "Age", "Income", "LoanAmount", "CreditScore",
               "MonthsEmployed", "NumCreditLines", "InterestRate", "LoanTerm", "DTIRatio",
               "Education", "EmploymentType", "MaritalStatus", "HasMortgage",
               "HasDependents", "LoanPurpose", "HasCoSigner", "Default"),
  Description = c("Mã khoản vay",
                  "Tuổi khách hàng",
                  "Thu nhập hàng năm",
                  "Số tiền vay",
                  "Điểm tín dụng",
                  "Số tháng đã làm việc",
                  "Số lượng dòng tín dụng hiện tại/trước đây",
                  "Lãi suất vay (%)",
                  "Thời hạn vay",
                  "Tỷ lệ nợ trên thu nhập",
                  "Trình độ học vấn",
                  "Loại hình công việc",
                  "Tình trạng hôn nhân",
                  "Có vay thế chấp hay không",
                  "Có người phụ thuộc hay không",
                  "Mục đích vay",
                  "Có người đồng ký vay hay không",
                  "Khả năng vỡ nợ ")
)

variable_description

1 Mô tả dữ liệu

1.1 Thống kê mô tả

1.1.1 Mô tả dữ liệu biến phụ thuộc Default

table(df$Default)
## 
##      0      1 
## 225694  29653
prop.table(table(df$Default))
## 
##         0         1 
## 0.8838718 0.1161282

Nhận xét: Biến Default đại diện cho khả năng vỡ nợ của khách hàng vay, trong đó 0 = Không vỡ nợ và 1 = Vỡ nợ. Kết quả thống kê cho thấy trong tổng số 255.347 khách hàng, có 225.694 khách hàng không vỡ nợ (chiếm 88,39%) và 29.653 khách hàng vỡ nợ (chiếm 11,61%).

# Biểu đồ thể hiện Default
df %>%
  count(Default) %>%
  mutate(Percent = n / sum(n) * 100,
         Label = paste0(Default, " (", round(Percent, 1), "%)")) %>%
  ggplot(aes(x = "", y = Percent, fill = Default)) +
  geom_col(width = 1, color = "white") +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Label), 
            position = position_stack(vjust = 0.5),
            color = "white", size = 5) +
  labs(title = "Biểu đồ tròn: Tỷ lệ vỡ nợ") +
  scale_fill_manual(values = c("#377eb8", "#e41a1c")) +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

1.1.2 Mô tả biến độc lập

# Thống kê mô tả biến độc lập
summary(df[, c("CreditScore", "Income", "LoanAmount", "LoanTerm")])
##   CreditScore        Income         LoanAmount        LoanTerm    
##  Min.   :300.0   Min.   : 15000   Min.   :  5000   Min.   :12.00  
##  1st Qu.:437.0   1st Qu.: 48826   1st Qu.: 66156   1st Qu.:24.00  
##  Median :574.0   Median : 82466   Median :127556   Median :36.00  
##  Mean   :574.3   Mean   : 82499   Mean   :127579   Mean   :36.03  
##  3rd Qu.:712.0   3rd Qu.:116219   3rd Qu.:188985   3rd Qu.:48.00  
##  Max.   :849.0   Max.   :149999   Max.   :249999   Max.   :60.00

Nhận xét: Kết quả thống kê mô tả cho bốn biến độc lập cho thấy phạm vi và xu hướng phân bố khá hợp lý. CreditScore dao động từ 300 đến 849 với giá trị trung bình khoảng 574, cho thấy phần lớn khách hàng có mức điểm tín dụng trung bình – khá. Income có mức tối thiểu 15.000 và tối đa 149.999, với trung bình khoảng 82.499, phản ánh sự chênh lệch thu nhập khá lớn giữa các khách hàng. LoanAmount (số tiền vay) tăng từ 5.000 đến 249.999, với giá trị trung bình 127.579, cho thấy khách hàng thường vay số tiền tương đối cao. Cuối cùng, LoanTerm (thời hạn vay) trải dài từ 12 đến 60 tháng, với trung bình khoảng 36 tháng, cho thấy đa số khoản vay có thời hạn trung bình 3 năm. Nhìn chung, ba biến CreditScore, Income và LoanAmount có mức độ biến thiên lớn, trong khi LoanTerm phân bố khá ổn định.

# Biểu đồ boxplot của biến LoanAmount
boxplot(df$LoanAmount,
        main = "Boxplot LoanAmount",
        ylab = "LoanAmount",
        col = "lightblue")

Nhận xét: Biểu đồ boxplot của biến LoanAmount (số tiền vay) cho thấy phân bố của dữ liệu khá rộng, với khoảng giá trị dao động từ khoảng 5.000 đến gần 250.000. Đường trung vị nằm gần giữa hộp, cho thấy phân bố khá cân đối giữa hai phía. Đồng thời, khoảng giữa Q1 và Q3 khá lớn, chứng tỏ sự biến động lớn trong số tiền vay của khách hàng. Độ dài của “râu” phía trên và dưới cũng cân đối, cho thấy không có sự lệch nổi bật về một phía. Ngoài ra, biểu đồ không xuất hiện nhiều điểm ngoại lệ rõ rệt, cho thấy dữ liệu khá sạch. Nhìn chung, LoanAmount có sự phân tán lớn nhưng phân bố tương đối đối xứng, và khách hàng vay các khoản tiền từ trung bình đến cao là khá phổ biến.

# Biểu đồ boxplot của biến CreditScore
boxplot(df$CreditScore,
        main = "Boxplot CreditScore",
        ylab = "CreditScore",
        col = "lightgray")

Nhận xét: Biểu đồ boxplot của CreditScore cho thấy điểm tín dụng của khách hàng phân bố chủ yếu trong khoảng từ khoảng 440 (Q1) đến hơn 700 (Q3), với trung vị xấp xỉ 575, phản ánh rằng phần lớn khách hàng có mức điểm tín dụng trung bình khá. Hai “râu” của biểu đồ kéo dài từ khoảng 300 đến hơn 800, cho thấy khoảng biến thiên rộng và tồn tại cả những khách hàng có điểm tín dụng rất thấp lẫn rất cao. Đáng chú ý, trung vị nằm gần giữa hộp, cho thấy phân bố dữ liệu khá cân đối, không lệch mạnh về phía thấp hay cao. Biểu đồ cũng không xuất hiện nhiều điểm ngoại lệ, chứng tỏ dữ liệu khá ổn định. Nhìn chung, CreditScore phân bố đa dạng nhưng tương đối cân bằng, phản ánh sự chênh lệch tự nhiên về mức độ uy tín tài chính của khách hàng.

# Biểu đồ boxplot của biến Income
boxplot(df$Income,
        main = "Boxplot Income",
        ylab = "Income",
        col = "lightgreen")

Nhận xét: Biểu đồ boxplot của Income (thu nhập) cho thấy phân bố dữ liệu khá cân đối và đồng đều. Giá trị thu nhập của khách hàng dao động trong khoảng từ 15.000 đến gần 150.000, với trung vị khoảng 82.000 – nằm gần giữa hộp, thể hiện phân bố tương đối đối xứng. Khoảng giữa hai phân vị Q1 và Q3 (khoảng từ 48.000 đến 116.000) khá rộng, phản ánh sự chênh lệch lớn về mức thu nhập giữa các khách hàng. Hai “râu” của biểu đồ có độ dài tương đối cân bằng, và không xuất hiện ngoại lệ rõ rệt, cho thấy dữ liệu ổn định. Nhìn chung, thu nhập của khách hàng có phân bố trải rộng nhưng không bị lệch mạnh, thể hiện sự đa dạng trong khả năng tài chính của nhóm người vay.

# Biểu đồ boxplot của biến Income
boxplot(df$LoanTerm,
        main = "Boxplot LoanTerm",
        ylab = "LoanTerm (tháng)",
        col = "lightpink")

Nhận xét: Biểu đồ boxplot của LoanTerm (thời hạn vay) cho thấy dữ liệu phân bố khá ổn định và cân đối. Thời hạn vay dao động từ 12 đến 60 tháng, với trung vị nằm đúng ở mức 36 tháng, phản ánh rằng phần lớn khách hàng chọn vay trong khoảng 3 năm. Khoảng giữa Q1 và Q3 (từ khoảng 24 đến 48 tháng) khá hẹp hơn so với các biến khác, cho thấy sự tập trung cao của dữ liệu quanh mức trung bình. Hai “râu” trên và dưới có độ dài tương đối tương đương, cho thấy phân bố không bị lệch mạnh về phía thời hạn vay ngắn hay dài. Đặc biệt, biểu đồ hầu như không xuất hiện ngoại lệ, chứng tỏ dữ liệu LoanTerm rất sạch và ổn định. Nhìn chung, đa số khách hàng vay trung và dài hạn (2–4 năm), và biến LoanTerm không có sự biến động quá lớn so với các biến tài chính khác.

1.2 Phân tích biến phụ thuộc theo các biến độc lập

1.2.1 Phân tích CreditScore theo Default

df %>%
  group_by(Default) %>%
  summarise(
    Mean   = mean(CreditScore, na.rm = TRUE),
    Median = median(CreditScore, na.rm = TRUE),
    SD     = sd(CreditScore, na.rm = TRUE),
    Min    = min(CreditScore, na.rm = TRUE),
    Max    = max(CreditScore, na.rm = TRUE)
  )

Nhận xét”: Kết quả thống kê mô tả cho biến CreditScore theo trạng thái Default cho thấy có sự khác biệt rõ ràng giữa hai nhóm khách hàng. Cụ thể, nhóm không vỡ nợ có điểm tín dụng trung bình là 576,23, trong khi nhóm vỡ nợ chỉ đạt 559,29, cho thấy khách hàng vỡ nợ thường có mức điểm tín dụng thấp hơn. Giá trị trung vị (Median) cũng phản ánh xu hướng tương tự khi nhóm không vỡ nợ đạt 577, cao hơn so với 553 của nhóm vỡ nợ. Mặc dù độ lệch chuẩn của hai nhóm gần như tương đồng (khoảng 158), tức là mức độ biến động trong mỗi nhóm là tương đối giống nhau, nhưng sự chênh lệch về giá trị trung bình và trung vị cho thấy điểm tín dụng có xu hướng cao hơn ở nhóm giữ được khả năng trả nợ. Như vậy, CreditScore có mối liên hệ ngược chiều với khả năng vỡ nợ, tức điểm tín dụng càng cao thì khả năng vỡ nợ càng thấp, phù hợp với logic thực tế trong lĩnh vực tài chính – ngân hàng. Đây là dấu hiệu ban đầu cho thấy CreditScore có thể là một yếu tố quan trọng ảnh hưởng đến khả năng vỡ nợ và cần được kiểm định thêm bằng các phương pháp thống kê suy luận hoặc mô hình hóa.

# Biểu đồ trực quan hóa mối quan hệ giữa CreditScore và Default
df %>%
  group_by(Default) %>%
  summarise(Mean_CreditScore = mean(CreditScore, na.rm = TRUE)) %>%
  ggplot(aes(x = Default, y = Mean_CreditScore, fill = Default)) +
  geom_col(width = 0.5) +
  geom_text(aes(label = round(Mean_CreditScore, 1)), 
            vjust = -0.5, size = 5) +
  labs(title = "Điểm tín dụng trung bình theo trạng thái vỡ nợ",
       x = "Default (0 = Không vỡ nợ, 1 = Vỡ nợ)",
       y = "CreditScore (Mean)") +
  theme_minimal()

Kết luận: Nhóm vỡ nợ có điểm tín dụng thấp hơn nhóm không vỡ nợ.

1.2.2 Phân tích Income theo Default

df %>%
  group_by(Default) %>%
  summarise(
    Mean = mean(Income, na.rm = TRUE),
    Median = median(Income, na.rm = TRUE),
    SD = sd(Income, na.rm = TRUE),
    Min = min(Income, na.rm = TRUE),
    Max = max(Income, na.rm = TRUE)
  )

Nhận xét: Kết quả thống kê mô tả cho biến Income (thu nhập) theo trạng thái Default (vỡ nợ) cho thấy có sự khác biệt rõ ràng giữa hai nhóm khách hàng. Cụ thể, nhóm không vỡ nợ có thu nhập trung bình là 83.899, cao hơn đáng kể so với 71.845 của nhóm vỡ nợ. Giá trị trung vị cũng thể hiện xu hướng tương tự khi nhóm không vỡ nợ đạt 84.237, trong khi nhóm vỡ nợ chỉ đạt 66.566, chứng tỏ đa số khách hàng trả nợ đúng hạn sở hữu mức thu nhập cao hơn. Mặc dù độ lệch chuẩn của hai nhóm có giá trị tương đương (khoảng 38.499 và 40.785), cho thấy mức độ biến động thu nhập trong mỗi nhóm là tương đối giống nhau, nhưng sự chênh lệch về trung bình và trung vị cho thấy thu nhập có xu hướng thấp hơn ở nhóm vỡ nợ. Điều này phản ánh quy luật tài chính hợp lý: khách hàng có thu nhập thấp thường khó đảm bảo khả năng thanh toán, từ đó dễ dẫn đến vỡ nợ, trong khi khách hàng có thu nhập cao hơn có khả năng kiểm soát nghĩa vụ tài chính tốt hơn. Do đó, Income có thể là một yếu tố quan trọng ảnh hưởng ngược chiều đến khả năng vỡ nợ, và cần được xem xét sâu hơn bằng các kiểm định thống kê hoặc mô hình hồi quy để khẳng định mức độ ảnh hưởng.

# Biểu đồ trực quan hóa mối quan hệ giữa Income và Default
df %>%
  group_by(Default) %>%
  summarise(Mean_Income = mean(Income, na.rm = TRUE)) %>%
  ggplot(aes(x = Default, y = Mean_Income, fill = Default)) +
  geom_col(width = 0.5) +
  geom_text(aes(label = round(Mean_Income, 1)), vjust = -0.5, size = 5) +
  labs(title = "Thu nhập trung bình theo trạng thái vỡ nợ",
       x = "Default (0 = Không vỡ nợ, 1 = Vỡ nợ)",
       y = "Income (Mean)") +
  theme_minimal()

Kết luận: nhóm không vỡ nợ có thu nhập cao hơn nhóm vỡ nợ

1.2.3 Phân tích LoanAmount theo Default

df %>%
  group_by(Default) %>%
  summarise(
    Mean   = mean(LoanAmount, na.rm = TRUE),
    Median = median(LoanAmount, na.rm = TRUE),
    SD     = sd(LoanAmount, na.rm = TRUE),
    Min    = min(LoanAmount, na.rm = TRUE),
    Max    = max(LoanAmount, na.rm = TRUE)
  )

Nhận xét: Kết quả thống kê mô tả cho biến LoanAmount (số tiền vay) theo trạng thái Default cho thấy có sự khác biệt đáng chú ý giữa hai nhóm khách hàng. Cụ thể, nhóm không vỡ nợ có mức vay trung bình là 125.353, trong khi nhóm vỡ nợ có mức vay trung bình cao hơn đáng kể, lên tới 144.515. Giá trị trung vị cũng phản ánh xu hướng tương tự khi nhóm không vỡ nợ đạt 124.236, trong khi nhóm vỡ nợ lên tới 152.672, cho thấy phần lớn khách hàng vỡ nợ có xu hướng vay số tiền lớn hơn. Mặc dù độ lệch chuẩn của hai nhóm khá cao (khoảng 70.708 và 69.548), cho thấy mức độ biến động của số tiền vay là lớn và tương đối tương đồng giữa hai nhóm, nhưng sự chênh lệch về trung bình và trung vị cho thấy một mô hình rõ ràng: càng vay số tiền lớn thì rủi ro vỡ nợ càng cao. Điều này phù hợp với thực tế tín dụng, vì các khoản vay lớn tạo áp lực trả nợ cao hơn và làm tăng khả năng khách hàng không thể đáp ứng nghĩa vụ tài chính. Do đó, có thể đưa ra nhận định sơ bộ rằng LoanAmount có mối quan hệ cùng chiều với khả năng vỡ nợ và là một yếu tố quan trọng cần được kiểm định sâu hơn thông qua kiểm định thống kê hoặc mô hình hồi quy.

# Biểu đồ trực quan hóa mối quan hệ giữa LoanTerm và Default
df %>%
  group_by(Default) %>%
  summarise(Mean_LoanTerm = mean(LoanTerm, na.rm = TRUE)) %>%
  ggplot(aes(x = Default, y = Mean_LoanTerm, fill = Default)) +
  geom_col(width = 0.5) +
  geom_text(aes(label = round(Mean_LoanTerm, 1)), vjust = -0.5, size = 5) +
  labs(title = "Thời hạn vay trung bình theo trạng thái vỡ nợ",
       x = "Default (0 = Không vỡ nợ, 1 = Vỡ nợ)",
       y = "LoanTerm (Mean)") +
  theme_minimal()

Kết luận: Nhóm vỡ nợ có thời gian vay cao hơn nhóm không vỡ nợ

1.2.4 Phân tích LoanTerm theo Default

df %>%
  group_by(Default) %>%
  summarise(
    Mean   = mean(LoanTerm, na.rm = TRUE),
    Median = median(LoanTerm, na.rm = TRUE),
    SD     = sd(LoanTerm, na.rm = TRUE),
    Min    = min(LoanTerm, na.rm = TRUE),
    Max    = max(LoanTerm, na.rm = TRUE)
  )

Nhận xét: Kết quả thống kê mô tả cho biến LoanTerm (thời hạn vay) theo trạng thái Default cho thấy sự khác biệt giữa hai nhóm gần như không đáng kể. Cụ thể, thời hạn vay trung bình của nhóm không vỡ nợ là 36,02 tháng, trong khi nhóm vỡ nợ là 36,05 tháng, gần như tương đương nhau. Giá trị trung vị của cả hai nhóm đều bằng 36, cho thấy phân bố trung tâm của biến này gần như trùng khớp. Độ lệch chuẩn (khoảng 16,97 và 16,99) cũng gần như giống nhau, phản ánh mức độ biến động của thời hạn vay trong hai nhóm là tương đối tương đồng. Đồng thời, giá trị nhỏ nhất (12 tháng) và lớn nhất (60 tháng) đều giống nhau ở cả hai nhóm. Điều này cho thấy LoanTerm có thể không phải là yếu tố tạo ra sự khác biệt rõ ràng trong khả năng vỡ nợ của khách hàng. Nói cách khác, thời hạn vay dài hay ngắn không thể hiện ảnh hưởng rõ rệt đến việc khách hàng có vỡ nợ hay không. Tuy nhiên, để khẳng định chắc chắn liệu LoanTerm có thực sự không ảnh hưởng đến khả năng vỡ nợ, cần tiếp tục thực hiện các kiểm định thống kê suy luận hoặc phân tích hồi quy trong các bước tiếp theo.

# Biểu đồ trực quan hóa mối quan hệ giữa LoanAmount và Default
df %>%
  group_by(Default) %>%
  summarise(Mean_LoanAmount = mean(LoanAmount, na.rm = TRUE)) %>%
  ggplot(aes(x = Default, y = Mean_LoanAmount, fill = Default)) +
  geom_col(width = 0.5) +
  geom_text(aes(label = round(Mean_LoanAmount, 1)), vjust = -0.5, size = 5) +
  labs(title = "Số tiền vay trung bình theo trạng thái vỡ nợ",
       x = "Default (0 = Không vỡ nợ, 1 = Vỡ nợ)",
       y = "LoanAmount (Mean)") +
       theme_minimal()

Kết luận: Nhóm vỡ nợ có số tiền vay cao hơn đáng kể nhóm không vỡ nợ

1.3 R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

summary(cars)
##      speed           dist       
##  Min.   : 4.0   Min.   :  2.00  
##  1st Qu.:12.0   1st Qu.: 26.00  
##  Median :15.0   Median : 36.00  
##  Mean   :15.4   Mean   : 42.98  
##  3rd Qu.:19.0   3rd Qu.: 56.00  
##  Max.   :25.0   Max.   :120.00

1.4 Including Plots

You can also embed plots, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.