Bộ dữ liệu GiveMeSomeCredit.csv là một bộ dữ liệu công khai nổi tiếng, xuất phát từ một cuộc thi trên nền tảng khoa học dữ liệu Kaggle được tổ chức vào năm 2011. Mục tiêu của phân tích là đánh giá khả năng rủi ro tín dụng dựa trên đặc điểm nhân khẩu học và lịch sử tài chính của từng cá nhân.
| Tên biến | Ý nghĩa |
|---|---|
| SeriousDlqin2yrs | 1 nếu khách hàng bị nợ xấu trong 2 năm qua, 0 nếu không |
| RevolvingUtilizationOfUnsecuredLines | Tỷ lệ sử dụng tín dụng quay vòng so với tổng hạn mức |
| age | Tuổi của người vay |
| NumberOfTime30-59DaysPastDueNotWorse | Số lần trễ hạn thanh toán 30–59 ngày |
| DebtRatio | Tỷ lệ nợ trên thu nhập hàng tháng |
| MonthlyIncome | Thu nhập hàng tháng (USD) |
| NumberOfOpenCreditLinesAndLoans | Số lượng tài khoản tín dụng và khoản vay đang mở |
| NumberOfTimes90DaysLate | Số lần trễ hạn thanh toán ≥ 90 ngày |
| NumberRealEstateLoansOrLines | Số khoản vay bất động sản (nhà, đất, v.v.) |
| NumberOfTime60-89DaysPastDueNotWorse | Số lần trễ hạn thanh toán 60–89 ngày |
| NumberOfDependents | Số người phụ thuộc tài chính |
credit <- read.csv("GiveMeSomeCredit.csv")
Nhóm nhập dữ liệu vào bằng lệnh read.csv().
dim(credit)
## [1] 150000 11
Dữ liệu thô có 150000 quan sát và 11 biến.
str(credit)
## 'data.frame': 150000 obs. of 11 variables:
## $ SeriousDlqin2yrs : int 1 0 0 0 0 0 0 0 0 0 ...
## $ RevolvingUtilizationOfUnsecuredLines: num 0.766 0.957 0.658 0.234 0.907 ...
## $ age : int 45 40 38 30 49 74 57 39 27 57 ...
## $ NumberOfTime30.59DaysPastDueNotWorse: int 2 0 1 0 1 0 0 0 0 0 ...
## $ DebtRatio : num 0.803 0.1219 0.0851 0.036 0.0249 ...
## $ MonthlyIncome : int 9120 2600 3042 3300 63588 3500 NA 3500 NA 23684 ...
## $ NumberOfOpenCreditLinesAndLoans : int 13 4 2 5 7 3 8 8 2 9 ...
## $ NumberOfTimes90DaysLate : int 0 0 1 0 0 0 0 0 0 0 ...
## $ NumberRealEstateLoansOrLines : int 6 0 0 0 1 1 3 0 0 4 ...
## $ NumberOfTime60.89DaysPastDueNotWorse: int 0 0 0 0 0 0 0 0 0 0 ...
## $ NumberOfDependents : int 2 1 0 0 0 1 0 0 NA 2 ...
Kết quả kiểm tra cấu trúc dữ liệu bằng hàm str(credit)
cho thấy bộ dữ liệu Give Me Some Credit được lưu trữ
dưới dạng data.frame gồm 150.000 quan
sát và 11 biến.
Các biến trong tập dữ liệu chủ yếu thuộc kiểu số nguyên
(integer) và số thực (numeric), phù hợp cho
các phép tính thống kê và mô hình hóa.
sum(duplicated(credit))
## [1] 609
Kiểm tra phát hiện 609 quan sát bị trùng lặp.
colSums(is.na(credit))
## SeriousDlqin2yrs RevolvingUtilizationOfUnsecuredLines
## 0 0
## age NumberOfTime30.59DaysPastDueNotWorse
## 0 0
## DebtRatio MonthlyIncome
## 0 29731
## NumberOfOpenCreditLinesAndLoans NumberOfTimes90DaysLate
## 0 0
## NumberRealEstateLoansOrLines NumberOfTime60.89DaysPastDueNotWorse
## 0 0
## NumberOfDependents
## 3924
Trong bộ dữ liệu, hai biến có giá trị bị thiếu là
MonthlyIncome và NumberOfDependents.
summary(credit)
## SeriousDlqin2yrs RevolvingUtilizationOfUnsecuredLines age
## Min. :0.00000 Min. : 0.000 Min. : 0.0
## 1st Qu.:0.00000 1st Qu.: 0.030 1st Qu.: 41.0
## Median :0.00000 Median : 0.154 Median : 52.0
## Mean :0.06684 Mean : 6.048 Mean : 52.3
## 3rd Qu.:0.00000 3rd Qu.: 0.559 3rd Qu.: 63.0
## Max. :1.00000 Max. :50708.000 Max. :109.0
##
## NumberOfTime30.59DaysPastDueNotWorse DebtRatio MonthlyIncome
## Min. : 0.000 Min. : 0.00 Min. : 0
## 1st Qu.: 0.000 1st Qu.: 0.18 1st Qu.: 3400
## Median : 0.000 Median : 0.37 Median : 5400
## Mean : 0.421 Mean : 353.01 Mean : 6670
## 3rd Qu.: 0.000 3rd Qu.: 0.87 3rd Qu.: 8249
## Max. :98.000 Max. :329664.00 Max. :3008750
## NA's :29731
## NumberOfOpenCreditLinesAndLoans NumberOfTimes90DaysLate
## Min. : 0.000 Min. : 0.000
## 1st Qu.: 5.000 1st Qu.: 0.000
## Median : 8.000 Median : 0.000
## Mean : 8.453 Mean : 0.266
## 3rd Qu.:11.000 3rd Qu.: 0.000
## Max. :58.000 Max. :98.000
##
## NumberRealEstateLoansOrLines NumberOfTime60.89DaysPastDueNotWorse
## Min. : 0.000 Min. : 0.0000
## 1st Qu.: 0.000 1st Qu.: 0.0000
## Median : 1.000 Median : 0.0000
## Mean : 1.018 Mean : 0.2404
## 3rd Qu.: 2.000 3rd Qu.: 0.0000
## Max. :54.000 Max. :98.0000
##
## NumberOfDependents
## Min. : 0.0000
## 1st Qu.: 0.0000
## Median : 0.0000
## Mean : 0.7572
## 3rd Qu.: 1.0000
## Max. :20.0000
## NA's :3924
Kết quả từ hàm summary(credit) cung cấp các chỉ
số thống kê mô tả cơ bản cho từng biến trong bộ dữ liệu
Give Me Some Credit, bao gồm giá trị nhỏ nhất (Min), tứ phân vị
thứ nhất (1st Qu.), trung vị (Median), trung bình (Mean), tứ phân vị thứ
ba (3rd Qu.) và giá trị lớn nhất (Max).
Biến SeriousDlqin2yrs Biến mục tiêu
SeriousDlqin2yrs nhận giá trị 0 hoặc 1, thể hiện tình trạng
nợ xấu trong 2 năm qua.
Giá trị trung bình là 0.06684, nghĩa là khoảng
6,7% khách hàng bị nợ xấu, trong khi hơn 93%
không có nợ xấu.
Điều này cho thấy dữ liệu mất cân bằng giữa hai nhóm
khách hàng, cần chú ý khi phân tích hoặc mô hình hóa.
Biến RevolvingUtilizationOfUnsecuredLines Giá trị
trung bình là 6.048, nhưng giá trị lớn nhất lên tới
50.708, cho thấy tồn tại ngoại lai
(outliers) rất lớn so với phần lớn khách hàng có tỷ lệ sử dụng
tín dụng thấp (trung vị chỉ 0.154).
Điều này chứng tỏ một số ít khách hàng sử dụng hạn mức tín dụng vượt
trội so với phần còn lại.
Biến age Giá trị tuổi trung bình khoảng 52
tuổi, nhỏ nhất là 0 và lớn nhất là
109.
Tuổi bằng 0 là giá trị không hợp lý, cần được xem xét
và xử lý trước khi phân tích tiếp theo.
Phần lớn khách hàng tập trung ở độ tuổi 40–63, phù hợp
với nhóm dân số đang trong độ tuổi lao động.
Biến DebtRatio Giá trị trung bình của
DebtRatio là 353.01, trong khi trung vị
chỉ 0.37, cho thấy dữ liệu phân phối lệch phải
mạnh do một số khách hàng có tỷ lệ nợ cao bất thường (ngoại
lai).
Cần xem xét chuẩn hóa hoặc cắt ngưỡng giá trị cực đoan để tránh ảnh
hưởng đến kết quả phân tích.
Biến MonthlyIncome Giá trị trung bình 6.670
USD/tháng, trung vị 5.400 USD/tháng, cho thấy
phần lớn khách hàng có thu nhập ở mức trung bình.
Tuy nhiên, giá trị tối đa lên tới 3.008.750 USD và có
29.731 giá trị bị thiếu (NA), phản ánh sự tồn tại của
ngoại lai và dữ liệu thiếu.
Cần xử lý các giá trị thiếu và ngoại lai trong bước làm sạch dữ
liệu.
Biến NumberOfTime30-59DaysPastDueNotWorse,
NumberOfTimes90DaysLate, và
NumberOfTime60-89DaysPastDueNotWorse Các biến này có giá
trị trung bình rất nhỏ (khoảng 0.2–0.4) nhưng giá trị
tối đa lên tới 98, thể hiện rằng có một số khách hàng
có lịch sử trễ hạn cực kỳ nhiều lần.
Đây là dấu hiệu rõ ràng cho thấy sự xuất hiện của ngoại
lai, cần được xem xét trong phân tích.
Biến NumberOfOpenCreditLinesAndLoans Số lượng trung
bình là 8,45 tài khoản đang mở, dao động từ 0 đến
58.
Điều này cho thấy khách hàng trong tập dữ liệu có mức độ vay
mượn khá đa dạng, phản ánh nhiều kiểu hành vi tín dụng khác
nhau.
Biến NumberRealEstateLoansOrLines Trung bình khách
hàng có khoảng 1 khoản vay bất động sản, phần lớn trong
khoảng 0–2.
Điều này phù hợp với thực tế rằng không phải tất cả khách hàng đều có
vay bất động sản.
Biến NumberOfDependents Trung bình 0,76
người phụ thuộc, nhưng có 3.924 giá trị bị thiếu
(NA).
Phần lớn khách hàng không có người phụ thuộc, nhưng một số ít có đến
20 người phụ thuộc, cho thấy có thể tồn tại dữ liệu bất
thường hoặc sai sót nhập liệu.
credit$NumberOfDependents[is.na(credit$NumberOfDependents)] <- 0
Với NumberOfDependents, nhóm giả định rằng các khách hàng không khai báo có thể không có người phụ thuộc, vì vậy thay thế giá trị thiếu bằng 0.
median_income <- median(credit$MonthlyIncome, na.rm = TRUE)
credit$MonthlyIncome[is.na(credit$MonthlyIncome)] <- median_income
Với MonthlyIncome, do có nhiều giá trị bị thiếu và xuất hiện ngoại lai ở phần thu nhập cao, nhóm quyết định thay thế giá trị thiếu bằng trung vị (median) để giữ trung tâm phân phối và hạn chế sai lệch do ngoại lai.
credit <- credit[!duplicated(credit), ]
Kết quả thống kê mô tả cho thấy biến age có giá trị nhỏ
nhất bằng 0, đây là giá trị không hợp
lý vì khách hàng có độ tuổi bằng 0 không thể tồn tại trong thực
tế.
Các quan sát này có thể xuất hiện do lỗi nhập liệu hoặc mã hóa
sai dữ liệu trong quá trình thu thập. Để đảm bảo tính chính xác
của dữ liệu, nhóm tiến hành loại bỏ các quan sát có giá trị tuổi
không hợp lệ
credit <- credit %>% filter(age > 0)
str(credit)
## 'data.frame': 149232 obs. of 11 variables:
## $ SeriousDlqin2yrs : int 1 0 0 0 0 0 0 0 0 0 ...
## $ RevolvingUtilizationOfUnsecuredLines: num 0.766 0.957 0.658 0.234 0.907 ...
## $ age : int 45 40 38 30 49 74 57 39 27 57 ...
## $ NumberOfTime30.59DaysPastDueNotWorse: int 2 0 1 0 1 0 0 0 0 0 ...
## $ DebtRatio : num 0.803 0.1219 0.0851 0.036 0.0249 ...
## $ MonthlyIncome : int 9120 2600 3042 3300 63588 3500 5400 3500 5400 23684 ...
## $ NumberOfOpenCreditLinesAndLoans : int 13 4 2 5 7 3 8 8 2 9 ...
## $ NumberOfTimes90DaysLate : int 0 0 1 0 0 0 0 0 0 0 ...
## $ NumberRealEstateLoansOrLines : int 6 0 0 0 1 1 3 0 0 4 ...
## $ NumberOfTime60.89DaysPastDueNotWorse: int 0 0 0 0 0 0 0 0 0 0 ...
## $ NumberOfDependents : num 2 1 0 0 0 1 0 0 0 2 ...
Sau khi xử lý, ta thấy bộ dữ liệu còn 149390 quan sát và có 11 biến.
sum(duplicated(credit))
## [1] 0
colSums(is.na(credit))
## SeriousDlqin2yrs RevolvingUtilizationOfUnsecuredLines
## 0 0
## age NumberOfTime30.59DaysPastDueNotWorse
## 0 0
## DebtRatio MonthlyIncome
## 0 0
## NumberOfOpenCreditLinesAndLoans NumberOfTimes90DaysLate
## 0 0
## NumberRealEstateLoansOrLines NumberOfTime60.89DaysPastDueNotWorse
## 0 0
## NumberOfDependents
## 0
Sau khi xử lý, nhóm kiểm tra lại thấy dữ liệu không còn giá trị bị thiếu và quan sát bị trùng lặp.
summary(credit)
## SeriousDlqin2yrs RevolvingUtilizationOfUnsecuredLines age
## Min. :0.00000 Min. : 0.000 Min. : 21.0
## 1st Qu.:0.00000 1st Qu.: 0.030 1st Qu.: 41.0
## Median :0.00000 Median : 0.154 Median : 52.0
## Mean :0.06704 Mean : 6.077 Mean : 52.3
## 3rd Qu.:0.00000 3rd Qu.: 0.556 3rd Qu.: 63.0
## Max. :1.00000 Max. :50708.000 Max. :109.0
## NumberOfTime30.59DaysPastDueNotWorse DebtRatio MonthlyIncome
## Min. : 0.0000 Min. : 0.00 Min. : 0
## 1st Qu.: 0.0000 1st Qu.: 0.18 1st Qu.: 3900
## Median : 0.0000 Median : 0.37 Median : 5400
## Mean : 0.3884 Mean : 354.81 Mean : 6427
## 3rd Qu.: 0.0000 3rd Qu.: 0.88 3rd Qu.: 7409
## Max. :98.0000 Max. :329664.00 Max. :3008750
## NumberOfOpenCreditLinesAndLoans NumberOfTimes90DaysLate
## Min. : 0.000 Min. : 0.0000
## 1st Qu.: 5.000 1st Qu.: 0.0000
## Median : 8.000 Median : 0.0000
## Mean : 8.488 Mean : 0.2324
## 3rd Qu.:11.000 3rd Qu.: 0.0000
## Max. :58.000 Max. :98.0000
## NumberRealEstateLoansOrLines NumberOfTime60.89DaysPastDueNotWorse
## Min. : 0.000 Min. : 0.0000
## 1st Qu.: 0.000 1st Qu.: 0.0000
## Median : 1.000 Median : 0.0000
## Mean : 1.023 Mean : 0.2068
## 3rd Qu.: 2.000 3rd Qu.: 0.0000
## Max. :54.000 Max. :98.0000
## NumberOfDependents
## Min. : 0.0000
## 1st Qu.: 0.0000
## Median : 0.0000
## Mean : 0.7412
## 3rd Qu.: 1.0000
## Max. :20.0000
Đồng thời, nhóm cũng đã xử lý các giá trị không hợp lý trong thống kê mô tả.
Biểu đồ Box-plot được sử dụng để kiểm tra các giá trị ngoại lai của
các biến dễ có ngoại lai và cần phân tích ngoại lai như
RevolvingUtilizationOfUnsecuredLines,
DebtRatio, MonthlyIncome, giúp nhóm hiểu rõ
đặc tính của bộ dữ liệu.
ggplot(credit, aes(y = RevolvingUtilizationOfUnsecuredLines)) +
geom_boxplot(fill = "#1f78b4") +
coord_cartesian(ylim = c(0, 10)) +
labs(title = "Revolving Utilization of Unsecured Lines",
y = "Tỷ lệ sử dụng tín dụng") +
theme_minimal()
ggplot(credit, aes(y = DebtRatio)) +
geom_boxplot(fill = "#33a02c") +
coord_cartesian(ylim = c(0, 5)) +
labs(title = "Debt Ratio",
y = "Tỷ lệ nợ") +
theme_minimal()
ggplot(credit, aes(y = MonthlyIncome)) +
geom_boxplot(fill = "#ff7f00") +
coord_cartesian(ylim = c(0, 20000)) +
labs(title = "Thu nhập hàng tháng",
y = "Thu nhập (USD)") +
theme_minimal()
Biểu đồ 1: Tỷ lệ sử dụng tín dụng (Revolving Utilization): Phần lớn giá trị tập trung ở mức thấp (dữ liệu lệch phải) , trong khi nhiều điểm ngoại lai vượt xa ngưỡng bình thường, phản ánh một số ít khách hàng có tỷ lệ sử dụng tín dụng cực cao hoặc dữ liệu bất thường.
Biểu đồ 2 Tỷ lệ nợ (Debt Ratio): Tương tự biểu đồ 1, biến này xuất hiện nhiều ngoại lai với giá trị cực đại, cho thấy các trường hợp có tỷ lệ nợ trên thu nhập ở mức lớn bất thường so với đa số dữ liệu trong cùng biến.
Biểu đồ 3 (Monthly Income): Thu nhập chủ yếu tập trung trong khoảng trung bình, nhưng sự tồn tại của các giá trị thu nhập cực cao làm kéo dài đuôi phân phối, cho thấy sự chênh lệch lớn về mức thu nhập trong tập dữ liệu.
Trong phần này, nhóm tiến hành phân tổ khách hàng theo nhóm tuổi và nhóm thu nhập nhằm quan sát đặc điểm nhân khẩu học ảnh hưởng đến rủi ro tín dụng.
Cụ thể: - Nhóm tuổi được chia thành 3 mức: Dưới
30, 30–49, Từ 50 trở lên
- Nhóm thu nhập được chia thành 3 mức: Thấp,
Trung bình, Cao
Việc phân tổ giúp so sánh tỷ lệ nợ xấu và đặc điểm tín dụng giữa các nhóm khách hàng khác nhau.
credit <- credit %>%
mutate(AgeGroup = case_when(
age < 30 ~ "Dưới 30",
age >= 30 & age < 50 ~ "30–49",
age >= 50 ~ "50 trở lên"
))
credit <- credit %>%
mutate(IncomeLevel = case_when(
MonthlyIncome < 3000 ~ "Thấp",
MonthlyIncome >= 3000 & MonthlyIncome < 7000 ~ "Trung bình",
MonthlyIncome >= 7000 ~ "Cao",
TRUE ~ NA_character_
))
table(credit$AgeGroup)
##
## 30–49 50 trở lên Dưới 30
## 57464 83191 8577
table(credit$IncomeLevel)
##
## Cao Thấp Trung bình
## 41698 23229 84305
Số lượng quan sát của từng tổ.
Trong phần này, nhóm tiến hành phân tích ba biến chính trong bộ dữ liệu:
SeriousDlqin2yrs – Biến mục tiêu, thể hiện tình trạng
nợ xấu.age – Tuổi của khách hàng.MonthlyIncome – Thu nhập hàng tháng (USD).Mục tiêu là mô tả phân bố, mối quan hệ và ảnh hưởng của các biến này đến khả năng rủi ro tín dụng.
tyle_no_xau <- prop.table(table(credit$SeriousDlqin2yrs))
bar_data <- data.frame(
TrangThai = c("Không nợ xấu", "Nợ xấu"),
TyLe = as.numeric(tyle_no_xau)
)
bar_data
## TrangThai TyLe
## 1 Không nợ xấu 0.93296344
## 2 Nợ xấu 0.06703656
ggplot(bar_data, aes(x = TrangThai, y = TyLe, fill = TrangThai)) +
geom_col() +
scale_y_continuous(labels = scales::percent) +
labs(title = "Tỷ lệ khách hàng nợ xấu",
x = "Trạng thái tín dụng", y = "Tỷ lệ (%)") +
theme_minimal()
Kết quả cho thấy phần lớn khách hàng không bị nợ xấu, chỉ khoảng 6–7% khách hàng có nợ xấu trong 2 năm qua. Điều này thể hiện sự mất cân bằng dữ liệu (imbalanced data) — cần chú ý khi xây dựng mô hình dự đoán sau này.
summary(credit$age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.0 41.0 52.0 52.3 63.0 109.0
ggplot(credit, aes(x = age)) +
geom_histogram(bins = 30, fill = "steelblue", color = "white") +
labs(title = "Phân bố độ tuổi khách hàng",
x = "Tuổi", y = "Tần suất") +
theme_minimal()
Biểu đồ cho thấy phần lớn khách hàng nằm trong độ tuổi 30–55 tuổi. Rất ít khách hàng dưới 25 hoặc trên 70 tuổi, có thể là do nhóm trẻ ít vay vốn hoặc chưa đủ điều kiện tín dụng.
ggplot(credit, aes(x = age, y = MonthlyIncome, color = as.factor(SeriousDlqin2yrs))) +
geom_point(alpha = 0.5) +
labs(title = "Mối quan hệ giữa tuổi, thu nhập và nợ xấu",
x = "Tuổi", y = "Thu nhập (USD)", color = "Nợ xấu") +
theme_minimal()
Biểu đồ cho thấy khách hàng có thu nhập thấp và tuổi trẻ có xu hướng nợ xấu cao hơn. Những người lớn tuổi với thu nhập ổn định ít rủi ro hơn. Điều này phù hợp với giả thuyết “kinh nghiệm và tài chính ổn định giúp giảm khả năng vỡ nợ”.