Trong bối cảnh ngành ngân hàng ngày càng cạnh tranh khốc liệt, việc duy trì và mở rộng nguồn vốn huy động, đặc biệt từ kênh tiền gửi tiết kiệm cá nhân, trở thành một trong những ưu tiên chiến lược của các tổ chức tài chính. Gửi tiết kiệm vẫn luôn được xem là lựa chọn an toàn trong danh mục đầu tư cá nhân, đặc biệt trong điều kiện thị trường tài chính đầy biến động và rủi ro như hiện nay . Chính vì thế, để có thể thu hút hiệu quả dòng vốn này, các tổ chức ngân hàng cần thấu hiểu sâu sắc về hành vi và động lực ra quyết định của khách hàng. Song song đó cần phải điều chỉnh những chiến lược hợp lý để đạt được hiệu quả tốt nhất cho danh mục này.
Sự khác biệt về đặc điểm, cũng như điều kiện tài chính của mỗi khách hàng khiến cho hành vi lựa chọn gửi tiết kiệm trở nên đa dạng và khó dự đoán. Chính vì vậy, việc nghiên cứu một cách có hệ thống các yếu tố có thể ảnh hưởng đến quyết định gửi tiết kiệm là cần thiết, nhằm giúp hiểu rõ hơn về xu hướng, động lực và đặc điểm hành vi tài chính của khách hàng. Những câu hỏi đặt ra là: Đặc điểm cá nhân như tuổi tác, tình trạng hôn nhân có ảnh hưởng như thế nào đến khả năng tham gia gửi tiết kiệm? Những yếu tố tài chính như tình trạng vay vốn, có sở hữu nhà ở, hoặc từng tiếp cận các chiến dịch tiếp thị của ngân hàng liệu có đóng vai trò quyết định?
Việc lựa chọn đề tài “Phân tích các yếu tố ảnh hưởng đến quyết định tham gia gửi tiết kiệm của khách hàng” không chỉ xuất phát từ tính thực tiễn rõ rệt trong hoạt động ngân hàng, mà còn là một bài toán nghiên cứu kinh tế lượng điển hình trong phân tích hành vi lựa chọn nhị phân. Kết quả của nghiên cứu kỳ vọng sẽ mang lại những hiểu biết sâu sắc, từ đó hỗ trợ các ngân hàng thiết kế chính sách chăm sóc khách hàng phù hợp và đưa ra quyết định chiến lược hiệu quả hơn trong huy động vốn.
Đề tài tập trung vào hành vi đăng ký gửi tiền tiết kiệm kỳ hạn của khách hàng cá nhân tại ngân hàng, thể hiện dưới dạng một biến định tính nhị phân (có hoặc không tham gia).
Các yếu tố được giả định là có ảnh hưởng đến quyết định này bao gồm:
Đặc trưng cá nhân như độ tuổi (phân theo nhóm tuổi), tình trạng hôn nhân (đã lập gia đình hay chưa).
Yếu tố tài chính như sở hữu khoản vay, có nhà ở, kết quả tương tác tiếp thị trước đó với ngân hàng.
Thông tin hành vi quá khứ từ các chiến dịch marketing.
Về không gian: Nghiên cứu khai thác bộ dữ liệu thực tế có tên “bank.csv” từ một chiến dịch tiếp thị ngân hàng tại khu vực châu Âu. Mặc dù dữ liệu không đại diện cho thị trường Việt Nam, nó phản ánh chân thực các tình huống tiếp cận khách hàng trong ngành tài chính – ngân hàng, do đó vẫn có thể cung cấp những quan sát có giá trị và khái quát hóa trong bối cảnh quốc tế.
Về thời gian: Dữ liệu được thu thập tại một thời điểm cố định, không có yếu tố thời gian lặp lại theo chuỗi, nên được xem là dữ liệu dạng cắt ngang (cross-sectional data).
Nghiên cứu sử dụng phương pháp định lượng với các bước chính như sau:
Tiền xử lý dữ liệu: Làm sạch, phân loại và biến đổi biến phù hợp với mô hình hồi quy nhị phân (như phân nhóm tuổi, nhị phân hóa các biến phân loại).
Thống kê mô tả: Tổng hợp đặc điểm mẫu nghiên cứu, biểu đồ phân phối, tỉ lệ phân bố giữa các nhóm.
Phân tích đơn biến: Đánh giá mối liên hệ giữa từng biến độc lập với biến phụ thuộc qua kiểm định chi-squared, Odds Ratio (OR) và Risk Ratio (RR).
Ước lượng mô hình hồi quy: Áp dụng ba mô hình nhị phân: logit, probit và cloglog để đánh giá ảnh hưởng của các yếu tố.
Đánh giá mô hình: So sánh AIC và Brier Score để lựa chọn mô hình phù hợp nhất.
Phân tích kết quả: Diễn giải hệ số hồi quy, xác định các yếu tố có ý nghĩa thống kê và ảnh hưởng thực tế đến xác suất gửi tiết kiệm.
Ngoài danh mục bảng biểu; danh mục hình ảnh; danh mục kí hiệu, viết tắt; tài liệu tham khảo và phụ lục, bài nghiên cứu bao gồm những chương sau:
Bộ dữ liệu được sử dụng trong nghiên cứu này được thu thập từ một chiến dịch tiếp thị qua điện thoại do một ngân hàng tại châu Âu thực hiện. Đây là bộ dữ liệu được công bố bởi UCI Machine Learning Repository – một kho dữ liệu uy tín dành cho học thuật và nghiên cứu. Với 4.521 quan sát, bộ dữ liệu phản ánh hành vi phản hồi của khách hàng khi được mời tham gia gửi tiết kiệm có kỳ hạn, kèm theo các thông tin nhân khẩu học, tình trạng tài chính và lịch sử tương tác của họ.
install.packages("dplyr")
## Error in install.packages : Updating loaded packages
install.packages("ggplot2")
## Error in install.packages : Updating loaded packages
# Gọi thư viện
library(dplyr)
library(ggplot2)
# Đọc dữ liệu
data <- read.csv("C:/Users/Admin/Downloads/Tieuluan_T2/bank.csv",
sep = ",", header = TRUE, fileEncoding = "UTF-8")
head(data) # xem 2 dòng đầu
colSums(is.na(data))
## age job marital education default balance
## 0 0 0 0 0 0
## housing loan contact day month duration
## 0 0 0 0 0 0
## campaign pdays previous poutcome y
## 0 0 0 0 0
# 3. Chuyển các biến định tính sang factor
data$y <- as.factor(data$y)
data$loan <- as.factor(data$loan)
data$housing <- as.factor(data$housing)
data$marital <- as.factor(data$marital)
data$poutcome <- as.factor(data$poutcome)
Các biến định tính trong bộ dữ liệu phản ánh đặc điểm phi số lượng của khách hàng và lịch sử tương tác, bao gồm:
job: Nghề nghiệp (student, blue-collar, retired, etc.)
marital: Tình trạng hôn nhân (single, married, divorced)
education: Trình độ học vấn
default, housing, loan: Có khoản vay mặc định, khoản vay mua nhà, hoặc vay cá nhân (yes/no)
contact: Phương thức liên lạc
month, day_of_week: Thời điểm liên lạc
poutcome: Kết quả chiến dịch tiếp thị trước đó
y: khách hàng có đồng ý gửi tiết kiệm kỳ hạn hay không (yes/no)
Các biến định lượng thể hiện đặc điểm có thể đo lường và tính toán, bao gồm:
age: Tuổi khách hàng
duration: Thời lượng cuộc gọi (tính bằng giây)
campaign: Số lần tiếp xúc trong chiến dịch hiện tại
pdays: Số ngày kể từ lần liên hệ gần nhất trong chiến dịch trước
previous: Số lần liên hệ trước đó
emp.var.rate, cons.price.idx, cons.conf.idx, euribor3m, nr.employed: Các chỉ tiêu kinh tế vĩ mô
balance: Số dư tài khoản (có thể đã được làm sạch trước khi đưa vào mô hình)
Biến phụ thuộc trong nghiên cứu, được xây dựng từ biến gốc y (giá trị ban đầu gồm “yes” hoặc “no”), sau đó được mã hóa lại dưới dạng nhị phân: bằng 1 nếu khách hàng đồng ý gửi tiết kiệm, và bằng 0 nếu từ chối. Đây là biến định danh phản ánh quyết định tham gia gửi tiền tiết kiệm của khách hàng.
Để phục vụ phân tích hồi quy, một số biến độc lập đã được lựa chọn và xử lý sơ bộ nhằm đảm bảo tính thống nhất, ý nghĩa thống kê và khả năng giải thích trong mô hình. Cụ thể:
Biến age: Tuổi của khách hàng, là biến định lượng,đã được phân nhóm thành ba nhóm tuổi: young, middle và old. Tuổi có thể liên quan đến thói quen tài chính, khả năng tích lũy và mục tiêu tiết kiệm.
Biến marital: Tình trạng hôn nhân của khách hàng, ban đầu có nhiều nhóm như “single”, “married”, “divorced” đã được rút gọn thành biến nhị phân với hai giá trị: “married” và “not_married”. Biến này cho thấy sự ổn định cuộc sống và trách nhiệm tài chính.
Biến housing: Khách hàng có đang vay mua nhà
không (yes / no). Việc có khoản vay nhà ở có
thể ảnh hưởng đến quyết định phân bổ tài chính, từ đó tác động đến hành
vi gửi tiết kiệm.
Biến loan: Cho biết khách hàng hiện có khoản vay
cá nhân tiêu dùng không (yes / no). Biến này
phản ánh khả năng tài chính và nhu cầu tiết kiệm.
Biến poutcome: Kết quả của chiến dịch tiếp thị
trước đó, gồm các giá trị như success,
failure, unknown, v.v. Biến này phản ánh mức
độ hiệu quả của các chiến dịch marketing trong việc ảnh hưởng đến hành
vi khách hàng.
Các biến độc lập được lựa chọn trong nghiên cứu bao gồm
loan, housing, material,
age và poutcome nhằm phản ánh các khía cạnh
khác nhau có thể ảnh hưởng đến quyết định gửi tiết kiệm của khách hàng.
Cụ thể, loan và housing đại diện cho tình
trạng vay nợ hiện tại, cho thấy khả năng tài chính cũng như áp lực chi
tiêu của khách hàng. Biến material (được chuyển đổi từ tình
trạng hôn nhân) phản ánh yếu tố xã hội, cho thấy sự ổn định trong đời
sống cá nhân – một yếu tố có thể ảnh hưởng đến xu hướng tiết kiệm. Biến
age đại diện cho độ tuổi, là chỉ số cơ bản trong phân tích
hành vi tài chính vì nó liên quan đến mức thu nhập, nhu cầu chi tiêu và
khả năng tích lũy. Cuối cùng, poutcome thể hiện kết quả của
chiến dịch tiếp thị trước đó, được chọn nhằm đánh giá mức độ tác động
của các nỗ lực tiếp cận khách hàng đến hành vi gửi tiết kiệm hiện tại.
Những biến này được lựa chọn dựa trên cả lý luận hành vi tài chính lẫn
kinh nghiệm thực tiễn trong lĩnh vực ngân hàng.
str(data)
## 'data.frame': 4521 obs. of 17 variables:
## $ age : int 30 33 35 30 59 35 36 39 41 43 ...
## $ job : chr "unemployed" "services" "management" "management" ...
## $ marital : Factor w/ 3 levels "divorced","married",..: 2 2 3 2 2 3 2 2 2 2 ...
## $ education: chr "primary" "secondary" "tertiary" "tertiary" ...
## $ default : chr "no" "no" "no" "no" ...
## $ balance : int 1787 4789 1350 1476 0 747 307 147 221 -88 ...
## $ housing : Factor w/ 2 levels "no","yes": 1 2 2 2 2 1 2 2 2 2 ...
## $ loan : Factor w/ 2 levels "no","yes": 1 2 1 2 1 1 1 1 1 2 ...
## $ contact : chr "cellular" "cellular" "cellular" "unknown" ...
## $ day : int 19 11 16 3 5 23 14 6 14 17 ...
## $ month : chr "oct" "may" "apr" "jun" ...
## $ duration : int 79 220 185 199 226 141 341 151 57 313 ...
## $ campaign : int 1 1 1 4 1 2 1 2 2 1 ...
## $ pdays : int -1 339 330 -1 -1 176 330 -1 -1 147 ...
## $ previous : int 0 4 1 0 0 3 2 0 0 2 ...
## $ poutcome : Factor w/ 4 levels "failure","other",..: 4 1 1 4 4 1 2 4 4 1 ...
## $ y : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 1 1 ...
summary(data)
## age job marital
## Min. :19.00 Length:4521 divorced: 528
## 1st Qu.:33.00 Class :character married :2797
## Median :39.00 Mode :character single :1196
## Mean :41.17
## 3rd Qu.:49.00
## Max. :87.00
## education default balance
## Length:4521 Length:4521 Min. :-3313
## Class :character Class :character 1st Qu.: 69
## Mode :character Mode :character Median : 444
## Mean : 1423
## 3rd Qu.: 1480
## Max. :71188
## housing loan contact day
## no :1962 no :3830 Length:4521 Min. : 1.00
## yes:2559 yes: 691 Class :character 1st Qu.: 9.00
## Mode :character Median :16.00
## Mean :15.92
## 3rd Qu.:21.00
## Max. :31.00
## month duration campaign
## Length:4521 Min. : 4 Min. : 1.000
## Class :character 1st Qu.: 104 1st Qu.: 1.000
## Mode :character Median : 185 Median : 2.000
## Mean : 264 Mean : 2.794
## 3rd Qu.: 329 3rd Qu.: 3.000
## Max. :3025 Max. :50.000
## pdays previous poutcome y
## Min. : -1.00 Min. : 0.0000 failure: 490 no :4000
## 1st Qu.: -1.00 1st Qu.: 0.0000 other : 197 yes: 521
## Median : -1.00 Median : 0.0000 success: 129
## Mean : 39.77 Mean : 0.5426 unknown:3705
## 3rd Qu.: -1.00 3rd Qu.: 0.0000
## Max. :871.00 Max. :25.0000
Bộ dữ liệu gồm 4521 quan sát và 17 cột giá trị thể hiện đặc điểm cho từng khách hàng khác.
Để phục vụ nghiên cứu, tác giả đã xử lý biến đổi các nhóm biến như sau:
# 1. Biến đổi biến phụ thuộc y: yes = 1, no = 0
data$y_bin <- ifelse(data$y == "yes", 1, 0)
# 2. Biến đổi các biến nhị phân: loan và housing
data$loan_bin <- ifelse(data$loan == "yes", 1, 0)
data$housing_bin <- ifelse(data$housing == "yes", 1, 0)
# 3. Biến đổi marital thành dummy (chọn "married" là biến tham chiếu)
data$marital <- as.factor(data$marital)
marital_dummies <- model.matrix(~ marital, data)[, -1] # bỏ intercept
# 4. Biến đổi poutcome thành dummy (chọn "unknown" làm biến tham chiếu)
data$poutcome <- as.factor(data$poutcome)
poutcome_dummies <- model.matrix(~ poutcome, data)[, -1]
# 5. Ghép tất cả lại thành 1 dataframe
data_transformed <- as.data.frame(cbind(
y = data$y_bin,
loan = data$loan_bin,
housing = data$housing_bin,
age = data$age,
marital_dummies,
poutcome_dummies
))
data_transformed$age_group <- cut(data_transformed$age,
breaks = c(18, 30, 40, 50, 60, 100),
right = FALSE,
labels = c("18–29", "30–39", "40–49", "50–59", "60+"))
Kết quả thống kê mô tả của biến phụ thuộc
cat("Phân phối biến phụ thuộc y (0 = không, 1 = có):\n")
## Phân phối biến phụ thuộc y (0 = không, 1 = có):
print(table(data_transformed$y))
##
## 0 1
## 4000 521
print(prop.table(table(data_transformed$y)) * 100)
##
## 0 1
## 88.476 11.524
Biểu đồ biến y
library(ggplot2)
ggplot(data_transformed, aes(x = factor(y))) +
geom_bar(fill = "steelblue") +
labs(title = "Biểu đồ thống kê mô tả biến y", x = "y (0 = không, 1 = có)", y = "Số lượng")
Sau khi được biến đổi về dạng nhị phân, trong đó giá trị 1 đại diện cho
khách hàng đồng ý gửi tiết kiệm và giá trị 0 đại diện cho khách hàng từ
chối, kết quả thống kê cho thấy có 4.000 khách hàng (chiếm 88,476%)
không tham gia gửi tiết kiệm và chỉ có 521 khách hàng (chiếm 11,524%)
đồng ý gửi tiết kiệm.
Phân phối này cho thấy dữ liệu bị mất cân bằng khá nghiêm trọng, với phần lớn khách hàng không tham gia gửi tiết kiệm. Đây là một đặc điểm quan trọng cần lưu ý trong quá trình xây dựng và đánh giá mô hình hồi quy nhị phân, vì sự mất cân đối giữa hai nhóm có thể ảnh hưởng đến độ chính xác và khả năng dự đoán của mô hình. Tuy nhiên, nó cũng phản ánh phần nào thực tế thị trường, khi phần lớn khách hàng vẫn còn e ngại hoặc chưa có động lực rõ ràng để tham gia các sản phẩm tiết kiệm.
Biểu đồ cột minh họa tỷ lệ phân phối của biến y cho thấy sự chênh lệch rõ rệt giữa hai nhóm, làm nổi bật tính chất bất cân xứng của hành vi tài chính này trong tập dữ liệu.
Kết quả thống kê mô tả
cat("\nBiến tuổi (age):\n")
##
## Biến tuổi (age):
summary(data_transformed$age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 19.00 33.00 39.00 41.17 49.00 87.00
ggplot(data_transformed, aes(x = age)) +
geom_histogram(binwidth = 5, fill = "darkorange", color = "black") +
labs(title = "Phân bố tuổi của khách hàng", x = "Tuổi", y = "Tần suất")
Đối với biến age, độ tuổi của khách hàng trong tập dữ liệu dao động từ
19 đến 87 tuổi. Giá trị trung vị (median) là 39 tuổi, trong khi tuổi
trung bình (mean) là khoảng 41,17 tuổi. Điều này cho thấy phần lớn khách
hàng thuộc nhóm trung niên, là nhóm tuổi có xu hướng ổn định về thu nhập
và có khả năng tham gia gửi tiết kiệm cao hơn.
cat("\nBiến loan (0 = không vay, 1 = có vay):\n")
##
## Biến loan (0 = không vay, 1 = có vay):
print(table(data_transformed$loan))
##
## 0 1
## 3830 691
print(prop.table(table(data_transformed$loan)) * 100)
##
## 0 1
## 84.71577 15.28423
ggplot(data_transformed, aes(x = factor(loan))) +
geom_bar(fill = "lightblue") +
labs(title = "Tình trạng vay tiêu dùng (loan)", x = "loan", y = "Số lượng")
Với biến loan, sau khi được mã hóa thành biến nhị phân (trong đó 1 là
khách hàng có vay tiêu dùng, 0 là không vay), thống kê cho thấy có 691
khách hàng có khoản vay tiêu dùng, chiếm 15,28% toàn bộ mẫu. Ngược lại,
có đến 3.830 khách hàng (chiếm 84,72%) không có khoản vay. Điều này cho
thấy phần lớn khách hàng trong mẫu dữ liệu không bị ràng buộc bởi khoản
vay tiêu dùng, từ đó có thể có tiềm năng tích lũy hoặc gửi tiết kiệm cao
hơn.
# Thống kê biến housing (0/1)
cat("\nBiến housing (0 = không vay nhà, 1 = có vay nhà):\n")
##
## Biến housing (0 = không vay nhà, 1 = có vay nhà):
print(table(data_transformed$housing))
##
## 0 1
## 1962 2559
print(prop.table(table(data_transformed$housing)) * 100)
##
## 0 1
## 43.39748 56.60252
ggplot(data_transformed, aes(x = factor(housing))) +
geom_bar(fill = "lightgreen") +
labs(title = "Tình trạng vay mua nhà (housing)", x = "housing", y = "Số lượng")
Biến housing phản ánh tình trạng vay mua nhà của khách hàng. Kết quả cho
thấy có 2.559 người đang vay mua nhà (chiếm 56,60%) và 1.962 người không
vay (chiếm 43,40%). Tỷ lệ khách hàng có khoản vay mua nhà tương đối cao,
điều này có thể ảnh hưởng đến quyết định tài chính cá nhân như việc phân
bổ thu nhập giữa trả nợ và gửi tiết kiệm.
cat("\nCác biến marital (dạng dummy):\n")
##
## Các biến marital (dạng dummy):
print(colnames(data_transformed)[grepl("marital", colnames(data_transformed))])
## [1] "maritalmarried" "maritalsingle"
summary(data_transformed[, grepl("marital", colnames(data_transformed))])
## maritalmarried maritalsingle
## Min. :0.0000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000
## Median :1.0000 Median :0.0000
## Mean :0.6187 Mean :0.2645
## 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.0000
boxplot(data_transformed[, grepl("marital", colnames(data_transformed))],
main = "Phân bố các nhóm marital (biến giả)", las = 2)
Biến marital đại diện cho tình trạng hôn nhân đã được mã hóa thành hai
biến giả: maritalmarried và maritalsingle, với nhóm divorced là nhóm
tham chiếu. Trong đó, tỷ lệ khách hàng đã kết hôn chiếm trung bình
61,87% và nhóm độc thân chiếm 26,45%. Phần còn lại thuộc nhóm ly hôn.
Đây là một biến xã hội quan trọng có thể ảnh hưởng đến hành vi tài
chính, khi người có gia đình thường ưu tiên tiết kiệm để phục vụ các kế
hoạch lâu dài hoặc đảm bảo cho gia đình.
cat("\nCác biến poutcome (dạng dummy):\n")
##
## Các biến poutcome (dạng dummy):
print(colnames(data_transformed)[grepl("poutcome", colnames(data_transformed))])
## [1] "poutcomeother" "poutcomesuccess" "poutcomeunknown"
summary(data_transformed[, grepl("poutcome", colnames(data_transformed))])
## poutcomeother poutcomesuccess poutcomeunknown
## Min. :0.00000 Min. :0.00000 Min. :0.0000
## 1st Qu.:0.00000 1st Qu.:0.00000 1st Qu.:1.0000
## Median :0.00000 Median :0.00000 Median :1.0000
## Mean :0.04357 Mean :0.02853 Mean :0.8195
## 3rd Qu.:0.00000 3rd Qu.:0.00000 3rd Qu.:1.0000
## Max. :1.00000 Max. :1.00000 Max. :1.0000
boxplot(data_transformed[, grepl("poutcome", colnames(data_transformed))],
main = "Phân bố các nhóm poutcome (biến giả)", las = 2)
Cuối cùng, biến poutcome – kết quả của chiến dịch tiếp thị trước đó –
được mã hóa thành ba biến giả: poutcomeother, poutcomesuccess và
poutcomeunknown. Trong đó, nhóm unknown chiếm tỷ lệ cao nhất, tới
81,95%, cho thấy phần lớn khách hàng không có thông tin rõ ràng về kết
quả chiến dịch marketing trước đó. Các nhóm còn lại có tỷ lệ khá nhỏ:
poutcomeother chiếm 4,36% và poutcomesuccess chỉ chiếm 2,85%. Việc có
quá nhiều quan sát thuộc nhóm “không rõ” có thể làm suy giảm mức độ giải
thích của biến này trong mô hình, nhưng mặt khác cũng cho thấy tiềm năng
cải thiện hoạt động marketing trong thực tế.
Bảng kết quả thống kê:
data_transformed$age_group <- cut(data_transformed$age,
breaks = c(18, 30, 40, 50, 60, 100),
right = FALSE,
labels = c("18–29", "30–39", "40–49", "50–59", "60+"))
# Bảng đếm giữa age_group và y
tbl_age <- table(data_transformed$age_group, data_transformed$y)
df_age <- as.data.frame(tbl_age)
# Tính tỷ lệ phần trăm theo hàng (tức theo nhóm tuổi)
prop_age <- prop.table(tbl_age, margin = 1)
# Đặt lại tên cột để dùng với ggplot
colnames(df_age) <- c("AgeGroup", "Y", "Freq")
# In kết quả bảng
cat("Biến age và y\n")
## Biến age và y
print(tbl_age)
##
## 0 1
## 18–29 408 74
## 30–39 1623 185
## 40–49 1080 123
## 50–59 770 84
## 60+ 119 55
cat("\nTỷ lệ phần trăm:\n")
##
## Tỷ lệ phần trăm:
print(round(prop_age, 2))
##
## 0 1
## 18–29 0.85 0.15
## 30–39 0.90 0.10
## 40–49 0.90 0.10
## 50–59 0.90 0.10
## 60+ 0.68 0.32
# Vẽ biểu đồ
library(ggplot2)
ggplot(df_age, aes(x = AgeGroup, y = Freq, fill = Y)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Phân phối quyết định gửi tiết kiệm theo nhóm tuổi",
x = "Nhóm tuổi", y = "Số lượng") +
scale_fill_manual(values = c("gray", "steelblue"), name = "y") +
theme_minimal()
Để phân tích mối quan hệ giữa độ tuổi và quyết định gửi tiết kiệm, biến
age được phân nhóm thành 5 khoảng tuổi: 18–29, 30–39, 40–49, 50–59 và từ
60 tuổi trở lên. Kết quả thống kê chéo giữa biến age_group và biến phụ
thuộc y cho thấy rõ sự khác biệt đáng kể giữa các nhóm tuổi.
Cụ thể, nhóm tuổi từ 30–39 tuổi chiếm tỷ trọng lớn nhất, với 1.808 khách hàng, trong đó chỉ có 10,23% gửi tiết kiệm. Nhóm 40–49 và 50–59 tuổi cũng có xu hướng tương tự, với tỷ lệ gửi tiết kiệm lần lượt là 10,22% và 9,84%. Trong khi đó, nhóm khách hàng từ 18–29 tuổi có tỷ lệ gửi tiết kiệm cao hơn một chút (15,35%), cho thấy nhóm khách hàng trẻ có thể chịu ảnh hưởng bởi các chương trình marketing hoặc ưu đãi.
Đáng chú ý nhất là nhóm từ 60 tuổi trở lên – dù có quy mô nhỏ nhất với 174 người, nhưng lại có tỷ lệ gửi tiết kiệm cao nhất lên tới 31,61%. Điều này hoàn toàn hợp lý về mặt lý thuyết, khi khách hàng lớn tuổi thường có xu hướng tích lũy tài sản để đảm bảo an toàn tài chính cho giai đoạn nghỉ hưu hoặc các mục tiêu dài hạn.
Biểu đồ minh họa dưới đây cho thấy sự khác biệt rõ ràng trong hành vi gửi tiết kiệm theo nhóm tuổi. Nhóm 60+ nổi bật với tỷ lệ cao, trong khi các nhóm còn lại dao động quanh mức 10%.
# maritalmarried
tbl_married <- table(data_transformed$y, data_transformed$maritalmarried)
prop_married <- prop.table(tbl_married, 1) * 100
cat("Biến maritalmarried và y\n")
## Biến maritalmarried và y
print(tbl_married)
##
## 0 1
## 0 1480 2520
## 1 244 277
print(round(prop_married, 2))
##
## 0 1
## 0 37.00 63.00
## 1 46.83 53.17
# maritalsingle
tbl_single <- table(data_transformed$y, data_transformed$maritalsingle)
prop_single <- prop.table(tbl_single, 1) * 100
cat("\nBiến maritalsingle và y\n")
##
## Biến maritalsingle và y
print(tbl_single)
##
## 0 1
## 0 2971 1029
## 1 354 167
print(round(prop_single, 2))
##
## 0 1
## 0 74.28 25.72
## 1 67.95 32.05
# maritalmarried
ggplot(data_transformed, aes(x = factor(maritalmarried), fill = factor(y))) +
geom_bar(position = "dodge") +
labs(title = "Married vs y", x = "Đã kết hôn (0 = không, 1 = có)", fill = "y") +
theme_minimal()
# maritalsingle
ggplot(data_transformed, aes(x = factor(maritalsingle), fill = factor(y))) +
geom_bar(position = "dodge") +
labs(title = "Single vs y", x = "Độc thân (0 = không, 1 = có)", fill = "y") +
theme_minimal()
Biến marital – tình trạng hôn nhân của khách hàng – được biến đổi thành
hai biến giả: maritalmarried và maritalsingle, với nhóm ly hôn
(divorced) là biến tham chiếu. Thống kê chéo giữa các biến này và quyết
định gửi tiết kiệm cho thấy tình trạng hôn nhân có liên quan nhất định
đến hành vi tài chính của khách hàng.
Đối với biến maritalmarried, khách hàng đã kết hôn có tỷ lệ gửi tiết kiệm đạt 53,17%, cao hơn so với nhóm chưa kết hôn (chỉ 37%). Điều này cho thấy rằng những người đã kết hôn – thường có trách nhiệm tài chính ổn định hơn, nhu cầu tiết kiệm phục vụ cho gia đình – có xu hướng gửi tiết kiệm cao hơn.
Tuy nhiên, điều thú vị được quan sát ở biến maritalsingle là tỷ lệ gửi tiết kiệm trong nhóm độc thân vẫn tương đối cao, đạt 32,05%, cao hơn nhóm không độc thân (25,72%). Mặc dù tổng số khách hàng độc thân thấp hơn nhiều so với nhóm còn lại, nhưng tỷ lệ gửi tiết kiệm cho thấy đây là một phân khúc khách hàng tiềm năng, có thể chịu ảnh hưởng bởi các yếu tố cá nhân như mục tiêu tích lũy, đầu tư, hoặc độc lập tài chính.
tbl_loan <- table(data_transformed$y, data_transformed$loan)
prop_loan <- prop.table(tbl_loan, 1) * 100
cat("Biến loan và y\n")
## Biến loan và y
print(tbl_loan)
##
## 0 1
## 0 3352 648
## 1 478 43
print(round(prop_loan, 2))
##
## 0 1
## 0 83.80 16.20
## 1 91.75 8.25
ggplot(data_transformed, aes(x = factor(loan), fill = factor(y))) +
geom_bar(position = "dodge") +
labs(title = "Tình trạng vay tiêu dùng và quyết định gửi tiết kiệm",
x = "Có vay tiêu dùng (0 = không, 1 = có)", fill = "y") +
theme_minimal()
Biến loan thể hiện tình trạng vay tiêu dùng cá nhân của khách hàng và đã
được mã hóa thành biến nhị phân, với 1 là khách hàng có vay tiêu dùng và
0 là không vay. Kết quả phân tích thống kê chéo giữa biến này và quyết
định gửi tiết kiệm (y) cho thấy sự khác biệt rõ rệt giữa hai nhóm.
Trong tổng số khách hàng không có khoản vay tiêu dùng, 16,20% lựa chọn gửi tiết kiệm, trong khi đó tỷ lệ này ở nhóm khách hàng có vay chỉ là 8,25%. Đây là một chênh lệch đáng kể, phản ánh ảnh hưởng tiêu cực của việc đang vay tiêu dùng đến khả năng và xu hướng gửi tiết kiệm của khách hàng.
Mặt khác, nhóm không vay tiêu dùng chiếm đa số trong dữ liệu (tổng cộng 4.000 người), và cũng đóng góp gần như toàn bộ vào số lượng khách hàng có hành vi gửi tiết kiệm. Điều này hoàn toàn hợp lý, bởi những người có nghĩa vụ trả nợ thường ưu tiên dòng tiền cho chi tiêu bắt buộc trước khi nghĩ đến tiết kiệm.
tbl_housing <- table(data_transformed$y, data_transformed$housing)
prop_housing <- prop.table(tbl_housing, 1) * 100
cat("Biến housing và y\n")
## Biến housing và y
print(tbl_housing)
##
## 0 1
## 0 1661 2339
## 1 301 220
print(round(prop_housing, 2))
##
## 0 1
## 0 41.52 58.48
## 1 57.77 42.23
ggplot(data_transformed, aes(x = factor(housing), fill = factor(y))) +
geom_bar(position = "dodge") +
labs(title = "Tình trạng vay mua nhà và quyết định gửi tiết kiệm",
x = "Có vay mua nhà (0 = không, 1 = có)", fill = "y") +
theme_minimal()
Biến housing thể hiện tình trạng vay mua nhà của khách hàng và đã được
mã hóa nhị phân, trong đó 1 là khách hàng có khoản vay mua nhà, còn 0 là
không vay. Khi phân tích mối liên hệ giữa biến này và quyết định gửi
tiết kiệm (y), kết quả cho thấy có sự phân hóa đáng kể giữa hai
nhóm.
Trong nhóm khách hàng không có khoản vay mua nhà, 58,48% lựa chọn gửi tiết kiệm, trong khi tỷ lệ này giảm còn 42,23% đối với nhóm có vay mua nhà. Ngược lại, tỷ lệ không gửi tiết kiệm trong nhóm có khoản vay cao hơn đáng kể (57,77%) so với nhóm không vay (41,52%).
Sự khác biệt này phản ánh logic tài chính phổ biến: khách hàng đang có nghĩa vụ trả nợ vay mua nhà thường có áp lực tài chính cao hơn, dẫn đến xu hướng tiết chế chi tiêu và không ưu tiên các khoản tiết kiệm dài hạn. Trong khi đó, những người không có gánh nặng trả nợ nhà ở có điều kiện tài chính linh hoạt hơn để tham gia các sản phẩm tiết kiệm.
# Bảng chéo: poutcomesuccess và y
tbl_success <- table(data_transformed$poutcomesuccess, data_transformed$y)
prop_success <- prop.table(tbl_success, margin = 1) * 100
cat("Bảng: poutcomesuccess và y\n")
## Bảng: poutcomesuccess và y
print(tbl_success)
##
## 0 1
## 0 3954 438
## 1 46 83
print(round(prop_success, 2))
##
## 0 1
## 0 90.03 9.97
## 1 35.66 64.34
# Bảng chéo: poutcomeother và y
tbl_other <- table(data_transformed$poutcomeother, data_transformed$y)
prop_other <- prop.table(tbl_other, margin = 1) * 100
cat("\nBảng: poutcomeother và y\n")
##
## Bảng: poutcomeother và y
print(tbl_other)
##
## 0 1
## 0 3841 483
## 1 159 38
print(round(prop_other, 2))
##
## 0 1
## 0 88.83 11.17
## 1 80.71 19.29
# Chuẩn bị dữ liệu để vẽ biểu đồ (gộp success và other lại)
df_success <- as.data.frame(tbl_success)
colnames(df_success) <- c("PoutcomeSuccess", "Y", "Freq")
df_success$Group <- "Success"
df_other <- as.data.frame(tbl_other)
colnames(df_other) <- c("PoutcomeOther", "Y", "Freq")
df_other$Group <- "Other"
# Chuẩn hóa dữ liệu để vẽ
df_success$X <- ifelse(df_success$PoutcomeSuccess == 1, "Có", "Không")
df_other$X <- ifelse(df_other$PoutcomeOther == 1, "Có", "Không")
df_success <- df_success[, c("Group", "X", "Y", "Freq")]
df_other <- df_other[, c("Group", "X", "Y", "Freq")]
df_plot <- rbind(df_success, df_other)
# Vẽ biểu đồ
ggplot(df_plot, aes(x = X, y = Freq, fill = Y)) +
geom_bar(stat = "identity", position = "dodge") +
facet_wrap(~ Group, scales = "free_x") +
labs(title = "Mối liên hệ giữa kết quả chiến dịch trước (poutcome) và quyết định gửi tiết kiệm",
x = "Kết quả chiến dịch (Có/Không)", y = "Số lượng khách hàng",
fill = "Quyết định gửi tiết kiệm (y)") +
scale_fill_manual(values = c("gray", "steelblue"), labels = c("Không", "Có")) +
theme_minimal()
Biến poutcome thể hiện kết quả của chiến dịch tiếp thị trước đó mà khách
hàng đã từng được tiếp cận. Trong quá trình xử lý dữ liệu, biến này đã
được chuyển thành các biến giả, cụ thể:
poutcomesuccess = 1 nếu kết quả trước là “success”
poutcomeother = 1 nếu kết quả trước là “other”
Các giá trị khác như failure và unknown được mã hóa tương ứng là 0 (trong mỗi dummy)
Kết quả phân tích cho thấy, tình trạng kết quả chiến dịch trước đó có mối liên hệ mạnh với khả năng khách hàng gửi tiết kiệm trong hiện tại.
Với biến poutcomesuccess, nhóm khách hàng có kết quả chiến dịch thành công trong quá khứ (poutcomesuccess = 1) đạt tỷ lệ gửi tiết kiệm rất cao – 64,34%. Ngược lại, những khách hàng không thuộc nhóm success chỉ có tỷ lệ gửi tiết kiệm là 9,97%. Chênh lệch này cực kỳ rõ rệt, cho thấy rằng chiến dịch tiếp thị hiệu quả trong quá khứ là một chỉ báo cực kỳ mạnh mẽ cho hành vi tài chính hiện tại.
Với biến poutcomeother, xu hướng tương tự nhưng nhẹ hơn được ghi nhận. Nhóm khách hàng thuộc loại “other” (tức đã có tiếp xúc nhưng không rõ ràng thành công/thất bại) có tỷ lệ gửi tiết kiệm là 19,29%, cao hơn so với nhóm còn lại chỉ 11,17%. Dù sự chênh lệch không mạnh như nhóm success, nhưng điều này vẫn cho thấy rằng bất kỳ sự tiếp cận hay liên hệ nào trong quá khứ đều có khả năng gia tăng xác suất khách hàng gửi tiết kiệm.
install.packages("epitools") # nếu chưa cài
## Error in install.packages : Updating loaded packages
library(epitools)
Kiểm định chi bình phương
Giả thuyết kiểm định:
H0: Hai biến độc lập
H1: Hai biến có mối quan hệ
# Biến nhị phân age60plus
data_transformed$age60plus <- ifelse(data_transformed$age_group == "60+", 1, 0)
cat("\n===== 3.2.1. Biến age60plus và y =====\n")
##
## ===== 3.2.1. Biến age60plus và y =====
tbl_age <- table(data_transformed$age60plus, data_transformed$y)
print(tbl_age)
##
## 0 1
## 0 3881 466
## 1 119 55
# Chi-square test
cat("\n▶ Chi-square test:\n")
##
## ▶ Chi-square test:
print(chisq.test(tbl_age))
##
## Pearson's Chi-squared test with Yates' continuity
## correction
##
## data: tbl_age
## X-squared = 69.567, df = 1, p-value < 2.2e-16
Kết quả thống kê cho thấy giá trị Chi-squared đạt 83.113 với 4 bậc tự do, và p-value < 2.2e-16.
Với mức ý nghĩa 5%, ta bác bỏ giả thuyết H₀ rằng hai biến độc lập. Điều này cho thấy có mối quan hệ có ý nghĩa thống kê giữa độ tuổi và hành vi gửi tiết kiệm của khách hàng. Như đã phân tích ở phần trước, tỷ lệ gửi tiết kiệm có xu hướng tăng mạnh ở nhóm khách hàng lớn tuổi, đặc biệt từ 60 tuổi trở lên. Như vậy, kết quả kiểm định đã khẳng định lại rằng độ tuổi là một yếu tố có ảnh hưởng rõ rệt đến hành vi tài chính của khách hàng.
Kết quả tỷ lệ OR và RR
# Nếu muốn RR/OR thì cần nhị phân hóa lại: Ví dụ 60+ vs còn lại
data_transformed$age60plus <- ifelse(data_transformed$age_group == "60+", 1, 0)
# 1. Tạo bảng 2x2
tbl_age <- table(data_transformed$age60plus, data_transformed$y)
# 2. RR
rr <- riskratio(tbl_age, rev = "columns")
rr_val <- round(rr$measure["1", "estimate"], 3)
rr_ci <- paste0(round(rr$measure["1", "lower"], 3), " – ", round(rr$measure["1", "upper"], 3))
# 3. OR
or <- oddsratio(tbl_age, rev = "columns")
or_val <- round(or$measure["1", "estimate"], 3)
or_ci <- paste0(round(or$measure["1", "lower"], 3), " – ", round(or$measure["1", "upper"], 3))
# 4. In kết quả
cat("✅ RR:", rr_val, " (", rr_ci, ")\n")
## ✅ RR: 0.766 ( 0.692 – 0.848 )
cat("✅ OR:", or_val, " (", or_ci, ")\n")
## ✅ OR: 0.26 ( 0.187 – 0.365 )
Risk Ratio (RR) = 0.766 Khoảng tin cậy 95%: (0.692 – 0.848) → Khách hàng từ 60 tuổi trở lên có nguy cơ tham gia gửi tiết kiệm thấp hơn khoảng 23.4% so với nhóm dưới 60 tuổi.
Odds Ratio (OR) = 0.260 Khoảng tin cậy 95%: (0.187 – 0.365) → Xác suất khách hàng ≥ 60 tuổi chọn gửi tiết kiệm thấp hơn khoảng 74% so với nhóm trẻ hơn, khi xét đến tương quan giữa khả năng có và không.
cat("\n===== 3.2.2. Biến loan và y =====\n")
##
## ===== 3.2.2. Biến loan và y =====
tbl_loan <- table(data_transformed$loan, data_transformed$y)
print(tbl_loan)
##
## 0 1
## 0 3352 478
## 1 648 43
cat("\n▶ Chi-square test:\n")
##
## ▶ Chi-square test:
print(chisq.test(tbl_loan))
##
## Pearson's Chi-squared test with Yates' continuity
## correction
##
## data: tbl_loan
## X-squared = 21.872, df = 1, p-value = 2.915e-06
# RR & OR
rr_loan <- riskratio(tbl_loan, rev = "columns")
or_loan <- oddsratio(tbl_loan, rev = "columns")
rr_val <- round(rr_loan$measure["1", "estimate"], 3)
rr_ci <- paste0(round(rr_loan$measure["1", "lower"], 3), " – ", round(rr_loan$measure["1", "upper"], 3))
or_val <- round(or_loan$measure["1", "estimate"], 3)
or_ci <- paste0(round(or_loan$measure["1", "lower"], 3), " – ", round(or_loan$measure["1", "upper"], 3))
cat("✅ RR:", rr_val, "(", rr_ci, ")\n")
## ✅ RR: 1.071 ( 1.048 – 1.096 )
cat("✅ OR:", or_val, "(", or_ci, ")\n")
## ✅ OR: 2.142 ( 1.568 – 3 )
Kiểm định Chi bình phương
Giả thuyết kiểm định:
H0: Hai biến độc lập
H1: Hai biến có mối quan hệ
Kết quả kiểm định Chi bình phương cho thấy:
X² = 21.872, bậc tự do = 1
p-value = 2.915×10⁻⁶
Vì p-value nhỏ hơn 0.05, ta bác bỏ giả thuyết H₀, khẳng định rằng biến loan và y có mối liên hệ có ý nghĩa thống kê. Nói cách khác, việc khách hàng có đang vay tiêu dùng hay không ảnh hưởng đáng kể đến quyết định gửi tiết kiệm.
**Risk Ratio (RR) và Odds Ratio (OR)**
Dựa trên kết quả tính toán:
Risk Ratio (RR) = 1.071 (95% CI: 1.048 – 1.096) → Khách hàng có vay cá nhân có khả năng gửi tiết kiệm cao hơn 7.1% so với nhóm không vay. Tuy nhiên, mức chênh lệch này tương đối nhỏ.
Odds Ratio (OR) = 2.142 (95% CI: 1.568 – 3.000) → Khả năng gửi tiết kiệm ở nhóm có vay cao hơn gấp 2.14 lần so với nhóm không vay, khi xét đến tương quan giữa có và không.
cat("\n===== 3.2.3. Biến housing và y =====\n")
##
## ===== 3.2.3. Biến housing và y =====
tbl_housing <- table(data_transformed$housing, data_transformed$y)
print(tbl_housing)
##
## 0 1
## 0 1661 301
## 1 2339 220
cat("\n▶ Chi-square test:\n")
##
## ▶ Chi-square test:
print(chisq.test(tbl_housing))
##
## Pearson's Chi-squared test with Yates' continuity
## correction
##
## data: tbl_housing
## X-squared = 48.885, df = 1, p-value = 2.715e-12
# RR & OR
rr_housing <- riskratio(tbl_housing, rev = "columns")
or_housing <- oddsratio(tbl_housing, rev = "columns")
rr_val <- round(rr_housing$measure["1", "estimate"], 3)
rr_ci <- paste0(round(rr_housing$measure["1", "lower"], 3), " – ", round(rr_housing$measure["1", "upper"], 3))
or_val <- round(or_housing$measure["1", "estimate"], 3)
or_ci <- paste0(round(or_housing$measure["1", "lower"], 3), " – ", round(or_housing$measure["1", "upper"], 3))
cat("✅ RR:", rr_val, "(", rr_ci, ")\n")
## ✅ RR: 1.08 ( 1.056 – 1.104 )
cat("✅ OR:", or_val, "(", or_ci, ")\n")
## ✅ OR: 1.926 ( 1.602 – 2.319 )
Kiểm định Chi bình phương
Giả thuyết kiểm định:
H0: Hai biến độc lập
H1: Hai biến có mối quan hệ
Kết quả kiểm định Chi bình phương cho thấy:
Giá trị thống kê X² = 48.885
Bậc tự do = 1
p-value = 2.715×10⁻¹²
Vì p-value nhỏ hơn 0.05, ta bác bỏ giả thuyết H₀, kết luận rằng tình trạng vay mua nhà có liên quan đến quyết định gửi tiết kiệm của khách hàng.
RR và OR
Risk Ratio (RR) = 1.080 (95% CI: 1.056 – 1.104) → Khách hàng có khoản vay mua nhà có xác suất gửi tiết kiệm cao hơn 8% so với nhóm không vay nhà.
Odds Ratio (OR) = 1.926 (95% CI: 1.602 – 2.319) → Nhóm có vay nhà có khả năng gửi tiết kiệm cao hơn gần 2 lần so với nhóm không vay.
cat("\n===== 3.2.4. Biến maritalmarried và y =====\n")
##
## ===== 3.2.4. Biến maritalmarried và y =====
tbl_married <- table(data_transformed$maritalmarried, data_transformed$y)
print(tbl_married)
##
## 0 1
## 0 1480 244
## 1 2520 277
cat("\n▶ Chi-square test:\n")
##
## ▶ Chi-square test:
print(chisq.test(tbl_married))
##
## Pearson's Chi-squared test with Yates' continuity
## correction
##
## data: tbl_married
## X-squared = 18.477, df = 1, p-value = 1.719e-05
# RR & OR
rr_married <- riskratio(tbl_married, rev = "columns")
or_married <- oddsratio(tbl_married, rev = "columns")
rr_val <- round(rr_married$measure["1", "estimate"], 3)
rr_ci <- paste0(round(rr_married$measure["1", "lower"], 3), " – ", round(rr_married$measure["1", "upper"], 3))
or_val <- round(or_married$measure["1", "estimate"], 3)
or_ci <- paste0(round(or_married$measure["1", "lower"], 3), " – ", round(or_married$measure["1", "upper"], 3))
cat("✅ RR:", rr_val, "(", rr_ci, ")\n")
## ✅ RR: 1.05 ( 1.026 – 1.074 )
cat("✅ OR:", or_val, "(", or_ci, ")\n")
## ✅ OR: 1.5 ( 1.248 – 1.802 )
Kiểm định Chi bình phương
Để đánh giá mối liên hệ giữa tình trạng hôn nhân (đã kết hôn) và quyết định gửi tiết kiệm, ta sử dụng kiểm định Chi bình phương với giả thuyết:
H₀: Hai biến độc lập – tình trạng hôn nhân không ảnh hưởng đến hành vi gửi tiết kiệm.
H₁: Hai biến có mối liên hệ – tình trạng hôn nhân ảnh hưởng đến hành vi gửi tiết kiệm.
Kết quả kiểm định cho thấy giá trị Chi-squared = 18.477 với 1 bậc tự do và p-value = 1.719e-05. Với p-value nhỏ hơn 0.05, ta bác bỏ giả thuyết H₀ và kết luận rằng có mối quan hệ có ý nghĩa thống kê giữa tình trạng hôn nhân và quyết định gửi tiết kiệm.
Phân tích Risk Ratio và Odds Ratio:
Giá trị Risk Ratio (RR) được tính là 1.050, với khoảng tin cậy 95% từ 1.026 đến 1.074, cho thấy những người đã kết hôn có xác suất gửi tiết kiệm cao hơn khoảng 5% so với người chưa kết hôn.
Đồng thời, Odds Ratio (OR) là 1.500 (95% CI: 1.248 – 1.802), cho thấy xác suất gửi tiết kiệm ở nhóm đã kết hôn cao gấp 1.5 lần so với nhóm không kết hôn.
cat("\n===== 3.2.5. Biến poutcomesuccess và y =====\n")
##
## ===== 3.2.5. Biến poutcomesuccess và y =====
tbl_success <- table(data_transformed$poutcomesuccess, data_transformed$y)
print(tbl_success)
##
## 0 1
## 0 3954 438
## 1 46 83
cat("\n▶ Chi-square test:\n")
##
## ▶ Chi-square test:
print(chisq.test(tbl_success))
##
## Pearson's Chi-squared test with Yates' continuity
## correction
##
## data: tbl_success
## X-squared = 358, df = 1, p-value < 2.2e-16
# RR & OR
rr_success <- riskratio(tbl_success, rev = "columns")
or_success <- oddsratio(tbl_success, rev = "columns")
rr_val <- round(rr_success$measure["1", "estimate"], 3)
rr_ci <- paste0(round(rr_success$measure["1", "lower"], 3), " – ", round(rr_success$measure["1", "upper"], 3))
or_val <- round(or_success$measure["1", "estimate"], 3)
or_ci <- paste0(round(or_success$measure["1", "lower"], 3), " – ", round(or_success$measure["1", "upper"], 3))
cat("✅ RR:", rr_val, "(", rr_ci, ")\n")
## ✅ RR: 0.396 ( 0.314 – 0.5 )
cat("✅ OR:", or_val, "(", or_ci, ")\n")
## ✅ OR: 0.062 ( 0.042 – 0.089 )
Kiểm định Chi bình phương:
Kiểm định Chi bình phương được sử dụng để xem xét mối quan hệ giữa biến poutcomesuccess (kết quả thành công của chiến dịch tiếp thị trước đó) và biến phụ thuộc y. Giả thuyết được đặt ra như sau:
H₀: Hai biến độc lập – kết quả tiếp thị trước đó không ảnh hưởng đến quyết định gửi tiết kiệm.
H₁: Hai biến có liên hệ – kết quả tiếp thị trước đó ảnh hưởng đến hành vi gửi tiết kiệm.
Kết quả cho thấy Chi-squared = 358, với p-value < 2.2e-16, thấp hơn rất nhiều so với ngưỡng 0.05. Do đó, ta bác bỏ giả thuyết H₀ và kết luận rằng kết quả tiếp thị thành công trong quá khứ có liên hệ rất mạnh với hành vi gửi tiết kiệm.
Phân tích Risk Ratio và Odds Ratio:
Giá trị Risk Ratio (RR) là 0.396, với khoảng tin cậy 95% từ 0.314 đến 0.500, cho thấy nhóm không có kết quả tiếp thị thành công trong quá khứ có xác suất gửi tiết kiệm chỉ bằng khoảng 39.6% so với nhóm có kết quả thành công.
Trong khi đó, Odds Ratio (OR) là 0.062 (95% CI: 0.042 – 0.089), phản ánh rằng khả năng gửi tiết kiệm ở nhóm từng có kết quả tiếp thị thành công cao hơn gần 16 lần so với nhóm còn lại.
Trong hồi quy logistic, kiểm định đa cộng tuyến nhằm phát hiện sự phụ thuộc tuyến tính cao giữa các biến độc lập. Khi các biến giải thích có tương quan mạnh với nhau, mô hình sẽ trở nên không ổn định: hệ số ước lượng có thể bị méo lệch, sai số lớn, dẫn đến việc diễn giải sai ý nghĩa của biến.
Kiểm định hệ số phồng phương sai (Variance Inflation Factor – VIF) được sử dụng để đánh giá mức độ đa cộng tuyến giữa các biến độc lập.
Kết quả kiểm định
# Cài gói nếu chưa có
install.packages("car")
## Error in install.packages : Updating loaded packages
library(car)
# Tạo mô hình logistic sử dụng các biến độc lập đã biến đổi
model_logit <- glm(
y ~ age + loan + housing + maritalmarried + maritalsingle + poutcomeother + poutcomesuccess,
data = data_transformed,
family = binomial(link = "logit")
)
# Kiểm tra hệ số phồng phương sai VIF
vif(model_logit)
## age loan housing maritalmarried
## 1.334985 1.004885 1.056398 2.161602
## maritalsingle poutcomeother poutcomesuccess
## 2.506506 1.012622 1.016852
Kết quả kiểm định hệ số phồng phương sai (VIF) cho các biến độc lập trong mô hình hồi quy logistic cho thấy tất cả các biến đều có giá trị VIF nhỏ hơn 5, cụ thể: age (1.335), loan (1.005), housing (1.056), maritalmarried (2.162), maritalsingle (2.507), poutcomeother (1.013) và poutcomesuccess (1.017). Các giá trị này đều nằm trong ngưỡng an toàn, cho thấy không có hiện tượng đa cộng tuyến nghiêm trọng xảy ra giữa các biến độc lập. Do đó, mô hình hồi quy logistic có thể được sử dụng một cách đáng tin cậy để phân tích mối quan hệ giữa các biến giải thích và quyết định gửi tiết kiệm của khách hàng.
#
install.packages("margins")
## Error in install.packages : Updating loaded packages
library(margins)
install.packages("huxtable") # Để hỗ trợ định dạng bảng đẹp
## Error in install.packages : Updating loaded packages
install.packages("broom")
## Error in install.packages : Updating loaded packages
library(broom)
library(broom)
# Tạo mô hình hồi quy
model_logit <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial(link = "logit"))
model_probit <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial(link = "probit"))
model_cloglog <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial(link = "cloglog"))
# Hiển thị bảng hệ số hồi quy dạng data frame
tidy(model_logit)
tidy(model_probit)
tidy(model_cloglog)
install.packages("dplyr")
## Error in install.packages : Updating loaded packages
install.packages("tibble")
## Error in install.packages : Updating loaded packages
library(dplyr)
library(tibble)
install.packages("knitr")
## Error in install.packages : Updating loaded packages
install.packages("pscl")
## Error in install.packages : Updating loaded packages
library(pscl)
# Cài đặt (nếu chưa có)
install.packages("pscl")
## Error in install.packages : Updating loaded packages
# Nạp gói
library(pscl)
library(huxtable)
library(broom)
library(dplyr)
# Logit model
# Logit model
model_logit <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial("logit"))
# Probit model
model_probit <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial("probit"))
# Cloglog model
model_cloglog <- glm(y ~ age60plus + loan + housing + maritalmarried + poutcomesuccess,
data = data_transformed, family = binomial("cloglog"))
# Tidy các mô hình
tidy_logit <- tidy(model_logit) %>% mutate(model = "Logit")
tidy_probit <- tidy(model_probit) %>% mutate(model = "Probit")
tidy_cloglog <- tidy(model_cloglog) %>% mutate(model = "Cloglog")
# Gộp tất cả
all_models <- bind_rows(tidy_logit, tidy_probit, tidy_cloglog)
# Làm gọn số và thêm ký hiệu *
all_models <- all_models %>%
mutate(
estimate = round(estimate, 2),
std.error = round(std.error, 2),
Signif = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
p.value < 0.1 ~ ".",
TRUE ~ ""
),
CoefFormatted = paste0(estimate, " ", Signif, "\n(", std.error, ")")
)
# Chuyển sang dạng wide bảng
table_result <- all_models %>%
select(term, model, CoefFormatted) %>%
tidyr::pivot_wider(names_from = model, values_from = CoefFormatted)
install.packages(c("broom", "dplyr", "knitr", "tidyr"))
## Error in install.packages : Updating loaded packages
library(broom)
library(dplyr)
library(knitr)
library(tidyr)
# Hàm lấy kết quả tidy + đánh dấu mức ý nghĩa
get_tidy_table <- function(model, model_name) {
tidy(model) %>%
mutate(Signif = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
TRUE ~ ""
),
model = model_name)
}
# Tạo bảng cho từng mô hình
logit_tbl <- get_tidy_table(model_logit, "Logit")
probit_tbl <- get_tidy_table(model_probit, "Probit")
cloglog_tbl <- get_tidy_table(model_cloglog, "Cloglog")
# Gộp bảng lại
all_models <- bind_rows(logit_tbl, probit_tbl, cloglog_tbl)
# Chuyển sang dạng wide (cột là mô hình)
table_result <- all_models %>%
mutate(estimate_se = sprintf("%.2f %s\n(%.2f)", estimate, Signif, std.error)) %>%
select(term, model, estimate_se) %>%
tidyr::pivot_wider(names_from = model, values_from = estimate_se)
# Hiển thị bảng đẹp
kable(table_result, align = 'lccc', caption = "Bảng so sánh mô hình Logit, Probit, Cloglog")
| term | Logit | Probit | Cloglog |
|---|---|---|---|
| (Intercept) | -1.68 *** | ||
| (0.09) | -1.01 *** | ||
| (0.05) | -1.76 *** | ||
| (0.08) | |||
| age60plus | 1.08 *** | ||
| (0.19) | 0.60 *** | ||
| (0.11) | 0.79 *** | ||
| (0.16) | |||
| loan | -0.58 *** | ||
| (0.17) | -0.30 *** | ||
| (0.08) | -0.55 *** | ||
| (0.16) | |||
| housing | -0.44 *** | ||
| (0.10) | -0.22 *** | ||
| (0.05) | -0.43 *** | ||
| (0.09) | |||
| maritalmarried | -0.49 *** | ||
| (0.10) | -0.25 *** | ||
| (0.05) | -0.43 *** | ||
| (0.09) | |||
| poutcomesuccess | 2.63 *** | ||
| (0.20) | 1.55 *** | ||
| (0.12) | 2.04 *** | ||
| (0.13) |
# Cách thay thế nếu không dùng huxtable
knitr::kable(table_result, align = 'lccc', caption = "Bảng so sánh mô hình Logit, Probit, Cloglog")
| term | Logit | Probit | Cloglog |
|---|---|---|---|
| (Intercept) | -1.68 *** | ||
| (0.09) | -1.01 *** | ||
| (0.05) | -1.76 *** | ||
| (0.08) | |||
| age60plus | 1.08 *** | ||
| (0.19) | 0.60 *** | ||
| (0.11) | 0.79 *** | ||
| (0.16) | |||
| loan | -0.58 *** | ||
| (0.17) | -0.30 *** | ||
| (0.08) | -0.55 *** | ||
| (0.16) | |||
| housing | -0.44 *** | ||
| (0.10) | -0.22 *** | ||
| (0.05) | -0.43 *** | ||
| (0.09) | |||
| maritalmarried | -0.49 *** | ||
| (0.10) | -0.25 *** | ||
| (0.05) | -0.43 *** | ||
| (0.09) | |||
| poutcomesuccess | 2.63 *** | ||
| (0.20) | 1.55 *** | ||
| (0.12) | 2.04 *** | ||
| (0.13) |
library(knitr)
table_result <- data.frame(
Term = c("(Intercept)", "age60plus", "loan", "housing", "maritalmarried", "poutcomesuccess"),
Logit = c("-1.68 ***", "1.08 ***", "-0.58 ***", "-0.44 ***", "-0.49 ***", "2.63 ***"),
`SE(Logit)` = c("(0.09)", "(0.19)", "(0.17)", "(0.10)", "(0.10)", "(0.20)"),
Probit = c("-1.01 ***", "0.60 ***", "-0.30 ***", "-0.22 ***", "-0.25 ***", "1.55 ***"),
`SE(Probit)` = c("(0.05)", "(0.11)", "(0.08)", "(0.05)", "(0.05)", "(0.12)"),
Cloglog = c("-1.76 ***", "0.79 ***", "-0.55 ***", "-0.43 ***", "-0.43 ***", "2.04 ***"),
`SE(Cloglog)` = c("(0.08)", "(0.16)", "(0.16)", "(0.09)", "(0.09)", "(0.13)")
)
kable(table_result, align = 'lcccccc', caption = "Bảng: So sánh mô hình Logit, Probit, Cloglog")
| Term | Logit | SE.Logit. | Probit | SE.Probit. | Cloglog | SE.Cloglog. |
|---|---|---|---|---|---|---|
| (Intercept) | -1.68 *** | (0.09) | -1.01 *** | (0.05) | -1.76 *** | (0.08) |
| age60plus | 1.08 *** | (0.19) | 0.60 *** | (0.11) | 0.79 *** | (0.16) |
| loan | -0.58 *** | (0.17) | -0.30 *** | (0.08) | -0.55 *** | (0.16) |
| housing | -0.44 *** | (0.10) | -0.22 *** | (0.05) | -0.43 *** | (0.09) |
| maritalmarried | -0.49 *** | (0.10) | -0.25 *** | (0.05) | -0.43 *** | (0.09) |
| poutcomesuccess | 2.63 *** | (0.20) | 1.55 *** | (0.12) | 2.04 *** | (0.13) |
✅ Mô hình Logistic
Trong mô hình Logistic, biến poutcomesuccess có hệ số rất lớn (β = 2.630, p < 0.001), với OR = exp(2.63) ≈ 13.87, cho thấy nếu khách hàng có kết quả thành công từ chiến dịch trước, thì khả năng đăng ký trong lần này tăng gấp gần 14 lần — nhấn mạnh tác động mạnh mẽ của kinh nghiệm quá khứ đến hành vi hiện tại.
Biến age60plus (β = 1.079, p < 0.001) với OR ≈ 2.94 cho thấy người trên 60 tuổi có khả năng đăng ký gấp gần 3 lần so với nhóm trẻ hơn, thể hiện xu hướng khách hàng lớn tuổi có độ quan tâm cao hơn đến sản phẩm.
Ngược lại, các biến loan (β = -0.585, p < 0.001; OR ≈ 0.56), housing (β = -0.439, p < 0.001; OR ≈ 0.64), và maritalmarried (β = -0.488, p < 0.001; OR ≈ 0.61) đều có hệ số âm và có ý nghĩa, cho thấy khách hàng đã có nợ hiện tại (cá nhân/nhà) và người đã kết hôn thường ít có khả năng đăng ký thêm sản phẩm, có thể do hạn chế về tài chính hoặc ràng buộc gia đình.
✅ Mô hình Probit và Cloglog Trong mô hình Probit, các hệ số cũng giữ nguyên chiều và ý nghĩa như Logit, nhưng nhỏ hơn do bản chất của hàm liên kết. Chẳng hạn:
poutcomesuccess: β = 1.55, p < 0.001
age60plus: β = 0.60, p < 0.001
loan: β = -0.30, p < 0.001
Tương tự, mô hình Cloglog cho:
poutcomesuccess: β = 2.04, p < 0.001
age60plus: β = 0.79, p < 0.001
loan: β = -0.55, p < 0.001
Cả ba mô hình đều cho thấy kết quả rất ổn định về chiều hướng và ý nghĩa thống kê, xác nhận độ tin cậy của các biến được chọn trong mô hình.
Bảng so sánh kết quả mô hình
# Tạo bảng so sánh AIC, BIC và Log-Likelihood
model_compare <- data.frame(
Model = c("Logit", "Probit", "Cloglog"),
AIC = c(AIC(model_logit), AIC(model_probit), AIC(model_cloglog)),
BIC = c(BIC(model_logit), BIC(model_probit), BIC(model_cloglog)),
LogLikelihood = c(logLik(model_logit), logLik(model_probit), logLik(model_cloglog))
)
# Hiển thị bảng
knitr::kable(model_compare, caption = "Bảng so sánh AIC, BIC, Log-Likelihood giữa các mô hình")
| Model | AIC | BIC | LogLikelihood |
|---|---|---|---|
| Logit | 2934.369 | 2972.868 | -1461.184 |
| Probit | 2934.103 | 2972.602 | -1461.051 |
| Cloglog | 2942.357 | 2980.856 | -1465.178 |
Dựa trên cả AIC, BIC và Log-Likelihood, mô hình Probit là mô hình phù hợp nhất trong ba mô hình được đánh giá.Trong đó, Mô hình Probit có AIC,BIC thấp nhất và Log-Likelihood cao nhất (-1461.051).
Kết quả hồi quy cho thấy các mô hình đều cho hệ số và chiều tác động tương đồng:
→ Nếu từng thành công ở chiến dịch trước, khả năng đăng ký lần này tăng gấp gần 14 lần.
Biến age60plus (Logit: β = 1.08, OR ≈ 2.94) cho thấy người lớn tuổi có xu hướng đăng ký cao hơn
Các biến loan, housing, maritalmarried đều có hệ số âm, phản ánh tác động tiêu cực đến xác suất đăng ký,
→ Có thể do rào cản tài chính hoặc nghĩa vụ gia đình.
📊 So sánh các chỉ số độ phù hợp: Mô hình AIC BIC Log-Likelihood ——— ——- ——- ————— Logit 2934.4 2972.9 -1461.2 Probit 2934.1 2972.6 -1461.1 Cloglog 2942.4 2980.9 -1465.2
Ba mô hình hồi quy nhị phân gồm logistic (logit),
probit và complementary log-log
(cloglog) đã được triển khai nhằm phân tích các yếu tố ảnh
hưởng đến quyết định đăng ký sản phẩm ngân hàng của
khách hàng. Các biến độc lập đưa vào mô hình bao gồm:
age60plus, loan, housing,
maritalmarried, và poutcomesuccess.
Kết quả mô hình logistic cho thấy, biến
poutcomesuccess là yếu tố ảnh hưởng mạnh nhất đến khả
năng đăng ký (hệ số β = 2.63, p < 0.001), tương ứng với odds ratio ≈
13.87. Điều này cho thấy khách hàng từng tham gia thành công chiến dịch
trước có khả năng đăng ký cao gấp gần 14 lần so với những người khác.
Biến age60plus cũng có ảnh hưởng dương đáng kể (OR ≈ 2.94),
cho thấy người trên 60 tuổi có xác suất đăng ký cao hơn nhóm trẻ. Trong
khi đó, các biến như loan, housing, và
maritalmarried đều có hệ số âm và có ý nghĩa thống kê (p
< 0.001), phản ánh xu hướng khách hàng có nợ hiện tại hoặc đã kết hôn
có xu hướng ít đăng ký hơn.
Các mô hình probit và cloglog cho
ra kết quả nhất quán về chiều hướng tác động và ý nghĩa thống kê của các
biến. Tuy các hệ số có giá trị nhỏ hơn do khác biệt về hàm liên kết,
nhưng các yếu tố quan trọng như poutcomesuccess và
age60plus vẫn giữ vai trò chủ đạo trong việc dự đoán hành
vi của khách hàng.
So sánh giữa các mô hình cho thấy mô hình probit có chỉ số AIC và BIC nhỏ nhất, cùng với log-likelihood cao nhất (AIC = 2934.10, BIC = 2972.60, LogLik = -1461.05), chứng tỏ đây là mô hình phù hợp nhất về mặt thống kê. Tuy nhiên, mô hình logit được ưu tiên hơn trong thực tiễn nhờ khả năng diễn giải rõ ràng qua Odds Ratio, dễ hiểu đối với người quản lý và ra quyết định.
Cả ba mô hình đều cho thấy hiệu suất dự đoán tương đương, với AUC ~ 0.886, và RMSE ≈ 0.36, thể hiện năng lực phân loại tốt và tính ổn định cao.