PHẦN 1: PHÂN TÍCH BỘ DỮ LIỆU VỀ CÁC YẾU TỐ SINH HỌC VÀ LỐI SỐNG ẢNH HƯỞNG ĐẾN NGUY CƠ MẮC BỆNH TIỂU ĐƯỜNG

1 TỔNG QUAN BỘ DỮ LIỆU

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

Bộ dữ liệu “Diabetes Health Indicators Dataset” được thu thập và công bố trên nền tảng Kaggle, có nguồn gốc từ Behavioral Risk Factor Surveillance System (BRFSS) — một chương trình khảo sát quy mô lớn của Trung tâm Kiểm soát và Phòng ngừa Dịch bệnh Hoa Kỳ (CDC). Dữ liệu này được xây dựng nhằm mục tiêu hỗ trợ phân tích và dự đoán nguy cơ mắc bệnh tiểu đường dựa trên các yếu tố về đặc điểm sinh học, hành vi lối sống và tình trạng sức khỏe tổng thể của người tham gia khảo sát.

1.2 Đọc dữ liệu

1. install.packages("DT", repos = "https://cloud.r-project.org")
## package 'DT' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\DELL\AppData\Local\Temp\RtmpmClaaG\downloaded_packages
1. install.packages("readxl", repos = "https://cloud.r-project.org")
## package 'readxl' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\DELL\AppData\Local\Temp\RtmpmClaaG\downloaded_packages
1. library(DT)
2. library(readxl)
3. d <- read_excel("D:/Diabetes Health Indicators Dataset.xlsx")

Ý nghĩa kỹ thuật:

read_excel: Đọc toàn bộ file Excel vào RAM, mỗi cột được ánh xạ thành một vector.

1.3 Danh sach các biến

1. names(d)
##  [1] "age"                                "gender"                            
##  [3] "ethnicity"                          "education_level"                   
##  [5] "income_level"                       "employment_status"                 
##  [7] "smoking_status"                     "alcohol_consumption_per_week"      
##  [9] "physical_activity_minutes_per_week" "diet_score"                        
## [11] "sleep_hours_per_day"                "screen_time_hours_per_day"         
## [13] "family_history_diabetes"            "hypertension_history"              
## [15] "cardiovascular_history"             "bmi"                               
## [17] "waist_to_hip_ratio"                 "systolic_bp"                       
## [19] "diastolic_bp"                       "heart_rate"                        
## [21] "cholesterol_total"                  "hdl_cholesterol"                   
## [23] "ldl_cholesterol"                    "triglycerides"                     
## [25] "glucose_fasting"                    "glucose_postprandial"              
## [27] "insulin_level"                      "hba1c"                             
## [29] "diabetes_risk_score"                "diabetes_stage"                    
## [31] "diagnosed_diabetes"

Ý nghĩa kỹ thuật:

Sử dụng lệnh names(d) kết quả trả về tên các biến trong bộ dữ liệu.

Mô tả đặc trung của dữ liệu

1. library(dplyr)
2. library(knitr)
3. library(kableExtra)
4. summary_tbl <- data.frame(
5.   "Tên biến" = names(d),
6.   "Kiểu dữ liệu" = sapply(d, class),
7.   "Số giá trị duy nhất" = sapply(d, function(x) length(unique(x)))
8. )
9. summary_tbl %>%
10.   kbl(caption = "Tóm tắt mô tả các biến trong bộ dữ liệu Diabetes Health Indicators",
11.       align = "c", format = "pandoc") %>%
12.   kable_styling(full_width = FALSE)
Tóm tắt mô tả các biến trong bộ dữ liệu Diabetes Health Indicators
Tên.biến Kiểu.dữ.liệu Số.giá.trị.duy.nhất
age age numeric 73
gender gender character 3
ethnicity ethnicity character 5
education_level education_level character 4
income_level income_level character 5
employment_status employment_status character 4
smoking_status smoking_status character 3
alcohol_consumption_per_week alcohol_consumption_per_week numeric 11
physical_activity_minutes_per_week physical_activity_minutes_per_week numeric 620
diet_score diet_score numeric 101
sleep_hours_per_day sleep_hours_per_day numeric 71
screen_time_hours_per_day screen_time_hours_per_day numeric 156
family_history_diabetes family_history_diabetes numeric 2
hypertension_history hypertension_history numeric 2
cardiovascular_history cardiovascular_history numeric 2
bmi bmi numeric 240
waist_to_hip_ratio waist_to_hip_ratio numeric 40
systolic_bp systolic_bp numeric 86
diastolic_bp diastolic_bp numeric 60
heart_rate heart_rate numeric 64
cholesterol_total cholesterol_total numeric 210
hdl_cholesterol hdl_cholesterol numeric 79
ldl_cholesterol ldl_cholesterol numeric 190
triglycerides triglycerides numeric 262
glucose_fasting glucose_fasting numeric 109
glucose_postprandial glucose_postprandial numeric 210
insulin_level insulin_level numeric 2350
hba1c hba1c numeric 548
diabetes_risk_score diabetes_risk_score numeric 569
diabetes_stage diabetes_stage character 5
diagnosed_diabetes diagnosed_diabetes numeric 2
Ý nghĩa kỹ thuật:

names(d): lấy tên tất cả các biến trong bộ dữ liệu d.

sapply(d, class): trả về kiểu dữ liệu của từng biến (numeric, factor, character,…).

sapply(d, function(x) length(unique(x))): đếm số lượng giá trị khác nhau (unique) trong từng biến.

kbl(): tạo bảng có tiêu đề (caption) và căn giữa nội dung (align = “c”).

format = “pandoc”: giúp bảng hiển thị tốt trong báo cáo Word hoặc HTML.

kable_styling(full_width = FALSE): bảng hiển thị gọn, không tràn toàn trang.

Nhận xét:

Bảng mô tả đặc trưng dữ liệu đóng vai trò như từ điển dữ liệu, giúp xác định loại biến, chọn phương pháp phân tích phù hợp và hiểu rõ ý nghĩa sinh học của các chỉ số trong nghiên cứu y học.

1.4 Số quan sát và số biến

1. dim(d)
## [1] 100000     31

Ý nghĩa kỹ thuật: Lệnh dim(d) trong R dùng để xem kích thước của data frame d, tức là số hàng và số cột của dữ liệu.

Nhận xét:

Dữ liệu có quy mô lớn (100.000 quan sát) với 31 biến độc lập, đủ mạnh để tiến hành các phân tích thống kê và mô hình dự báo tin cậy.

1.5 Kiểm tra cấu trúc tổng quát

1. str(d)
## tibble [100,000 × 31] (S3: tbl_df/tbl/data.frame)
##  $ age                               : num [1:100000] 58 48 60 74 46 46 75 62 42 59 ...
##  $ gender                            : chr [1:100000] "Male" "Female" "Male" "Female" ...
##  $ ethnicity                         : chr [1:100000] "Asian" "White" "Hispanic" "Black" ...
##  $ education_level                   : chr [1:100000] "Highschool" "Highschool" "Highschool" "Highschool" ...
##  $ income_level                      : chr [1:100000] "Lower-Middle" "Middle" "Middle" "Low" ...
##  $ employment_status                 : chr [1:100000] "Employed" "Employed" "Unemployed" "Retired" ...
##  $ smoking_status                    : chr [1:100000] "Never" "Former" "Never" "Never" ...
##  $ alcohol_consumption_per_week      : num [1:100000] 0 1 1 0 1 2 0 1 1 3 ...
##  $ physical_activity_minutes_per_week: num [1:100000] 215 143 57 49 109 124 53 75 114 86 ...
##  $ diet_score                        : num [1:100000] 5.7 6.7 6.4 3.4 7.2 9 9.2 4.1 6.7 8.2 ...
##  $ sleep_hours_per_day               : num [1:100000] 7.9 6.5 10 6.6 7.4 6.2 7.8 9 8.5 5.3 ...
##  $ screen_time_hours_per_day         : num [1:100000] 7.9 8.7 8.1 5.2 5 5.4 8 12.9 8.5 7.4 ...
##  $ family_history_diabetes           : num [1:100000] 0 0 1 0 0 0 0 0 0 0 ...
##  $ hypertension_history              : num [1:100000] 0 0 0 0 0 0 1 1 0 0 ...
##  $ cardiovascular_history            : num [1:100000] 0 0 0 0 0 0 0 1 1 0 ...
##  $ bmi                               : num [1:100000] 30.5 23.1 22.2 26.8 21.2 26.1 25.1 23.9 24.7 26.7 ...
##  $ waist_to_hip_ratio                : num [1:100000] 0.89 0.8 0.81 0.88 0.78 0.85 0.88 0.86 0.84 0.81 ...
##  $ systolic_bp                       : num [1:100000] 134 129 115 120 92 95 129 128 103 124 ...
##  $ diastolic_bp                      : num [1:100000] 78 76 73 93 67 81 77 83 71 81 ...
##  $ heart_rate                        : num [1:100000] 68 67 74 68 67 57 81 76 72 70 ...
##  $ cholesterol_total                 : num [1:100000] 239 116 213 171 210 218 238 241 187 188 ...
##  $ hdl_cholesterol                   : num [1:100000] 41 55 66 50 52 61 46 49 33 52 ...
##  $ ldl_cholesterol                   : num [1:100000] 160 50 99 79 125 119 161 159 132 103 ...
##  $ triglycerides                     : num [1:100000] 145 30 36 140 160 179 155 120 98 104 ...
##  $ glucose_fasting                   : num [1:100000] 136 93 118 139 137 100 101 110 116 76 ...
##  $ glucose_postprandial              : num [1:100000] 236 150 195 253 184 133 100 189 172 109 ...
##  $ insulin_level                     : num [1:100000] 6.36 2 5.07 5.28 12.74 ...
##  $ hba1c                             : num [1:100000] 8.18 5.63 7.51 9.03 7.2 6.03 5.24 7.04 6.9 4.99 ...
##  $ diabetes_risk_score               : num [1:100000] 29.6 23 44.7 38.2 23.5 23.5 36.1 34.2 26.7 30 ...
##  $ diabetes_stage                    : chr [1:100000] "Type 2" "No Diabetes" "Type 2" "Type 2" ...
##  $ diagnosed_diabetes                : num [1:100000] 1 0 1 1 1 0 0 1 1 0 ...

Ý nghĩa kỹ thuật

Hàm str() trong R dùng để xem cấu trúc nội bộ của một đối tượng

Nhận xét

Dữ liệu mô phỏng tình huống phân tích các yếu tố ảnh hưởng đến nguy cơ mắc bệnh tiểu đường.

1.6 Số lượng biến định tính và biến định lượng

1.6.1 Biến định lượng

1. sum(sapply(d, is.numeric))
## [1] 24

Ý nghĩa kỹ thuật

sum(sapply(d, is.numeric)): dùng để đếm tổng số cột có kiểu dữ liệu số trong data frame d.

Nhận xét:

Kết quả cho thấy bộ dữ liệu có 24 biến định lượng, bao gồm các chỉ số sinh học và hành vi như glucose, BMI, huyết áp, cholesterol,…

1.6.2 Biến định tính

1. sum(sapply(d, is.character) | sapply(d, is.factor))
## [1] 7

Ý nghĩa kỹ thuật:

Hàm sum(sapply(d, is.character) | sapply(d, is.factor)): đếm tổng số biến dạng ký tự hoặc nhân tố trong dữ liệu d.

Nhận xét:

Kết quả cho biết số lượng biến định tính trong bộ dữ liệu tiểu đường, bao gồm các đặc điểm như giới tính, dân tộc, tình trạng hút thuốc, trình độ học vấn,…

1.7 Một vài dòng đầu và dòng cuối

1.7.1 6 dòng đầu

1. library(dplyr); library(flextable)
2. head(d, 6) %>%
3.   flextable() %>%
4.   set_caption("6 dòng đầu tiên của bộ dữ liệu Diabetes Health Indicators Dataset") %>%
5.   autofit()
6 dòng đầu tiên của bộ dữ liệu Diabetes Health Indicators Dataset

age

gender

ethnicity

education_level

income_level

employment_status

smoking_status

alcohol_consumption_per_week

physical_activity_minutes_per_week

diet_score

sleep_hours_per_day

screen_time_hours_per_day

family_history_diabetes

hypertension_history

cardiovascular_history

bmi

waist_to_hip_ratio

systolic_bp

diastolic_bp

heart_rate

cholesterol_total

hdl_cholesterol

ldl_cholesterol

triglycerides

glucose_fasting

glucose_postprandial

insulin_level

hba1c

diabetes_risk_score

diabetes_stage

diagnosed_diabetes

58

Male

Asian

Highschool

Lower-Middle

Employed

Never

0

215

5.7

7.9

7.9

0

0

0

30.5

0.89

134

78

68

239

41

160

145

136

236

6.36

8.18

29.6

Type 2

1

48

Female

White

Highschool

Middle

Employed

Former

1

143

6.7

6.5

8.7

0

0

0

23.1

0.80

129

76

67

116

55

50

30

93

150

2.00

5.63

23.0

No Diabetes

0

60

Male

Hispanic

Highschool

Middle

Unemployed

Never

1

57

6.4

10.0

8.1

1

0

0

22.2

0.81

115

73

74

213

66

99

36

118

195

5.07

7.51

44.7

Type 2

1

74

Female

Black

Highschool

Low

Retired

Never

0

49

3.4

6.6

5.2

0

0

0

26.8

0.88

120

93

68

171

50

79

140

139

253

5.28

9.03

38.2

Type 2

1

46

Male

White

Graduate

Middle

Retired

Never

1

109

7.2

7.4

5.0

0

0

0

21.2

0.78

92

67

67

210

52

125

160

137

184

12.74

7.20

23.5

Type 2

1

46

Female

White

Highschool

Upper-Middle

Employed

Never

2

124

9.0

6.2

5.4

0

0

0

26.1

0.85

95

81

57

218

61

119

179

100

133

8.77

6.03

23.5

Pre-Diabetes

0

Ý nghĩa kỹ thuật:

head(): dùng để hiển thị 6 dòng đầu tiên của bộ dữ liệu. kable(): dùng để hiển thị bảng dưới dạng đẹp và dễ đọc.

Nhận xét:

Việc quan sát 6 dòng đầu giúp hiểu cấu trúc dữ liệu trước khi phân tích thống kê.

1.7.2 6 dòng cuối

1. library(flextable)
2. tail(d, 6) %>%
3.   flextable() %>%
4.   set_caption("6 dòng cuối của bộ dữ liệu Diabetes Health Indicators Dataset") %>%
5.   autofit()
6 dòng cuối của bộ dữ liệu Diabetes Health Indicators Dataset

age

gender

ethnicity

education_level

income_level

employment_status

smoking_status

alcohol_consumption_per_week

physical_activity_minutes_per_week

diet_score

sleep_hours_per_day

screen_time_hours_per_day

family_history_diabetes

hypertension_history

cardiovascular_history

bmi

waist_to_hip_ratio

systolic_bp

diastolic_bp

heart_rate

cholesterol_total

hdl_cholesterol

ldl_cholesterol

triglycerides

glucose_fasting

glucose_postprandial

insulin_level

hba1c

diabetes_risk_score

diabetes_stage

diagnosed_diabetes

71

Female

Hispanic

Graduate

Lower-Middle

Employed

Never

1

82

6.3

6.9

4.8

0

1

0

20.5

0.85

132

75

60

141

48

57

30

115

180

3.79

7.01

30.7

Type 2

1

46

Male

Other

Graduate

Upper-Middle

Unemployed

Former

1

136

8.3

6.4

4.5

0

0

0

29.8

0.93

126

74

63

227

45

150

116

113

109

14.58

5.55

26.0

Pre-Diabetes

0

41

Female

White

Graduate

Middle

Employed

Never

3

76

8.8

6.8

4.8

0

0

0

26.5

0.86

130

76

57

207

55

123

146

96

146

9.02

5.97

24.4

Pre-Diabetes

0

57

Female

Black

No formal

Upper-Middle

Employed

Former

4

121

9.9

5.0

6.1

0

0

1

25.6

0.83

107

87

69

189

50

111

184

93

132

2.57

5.21

27.6

No Diabetes

0

47

Female

Black

Highschool

Lower-Middle

Retired

Never

3

52

5.9

6.7

0.5

0

1

0

26.8

0.89

115

77

58

173

68

91

116

106

117

9.81

5.53

26.4

Pre-Diabetes

0

52

Female

White

Postgraduate

Middle

Employed

Never

1

248

2.7

5.4

5.5

0

0

0

30.3

1.00

109

77

55

238

31

183

87

91

142

15.93

5.73

27.9

Pre-Diabetes

0

Ý nghĩa kỹ thuật:

tail(): dùng để hiển thị 6 dòng cuối cùng của bộ dữ liệu. kable(): dùng để hiển thị bảng dưới dạng đẹp và dễ đọc.

Nhận xét:

Lệnh này giúp xem nhanh nội dung dữ liệu để đánh giá sơ bộ tính đầy đủ và hợp lý trước khi phân tích.

1.8 Kiểm tra NA

1. sum(is.na(d))
## [1] 0
1. any(is.na(d))
## [1] FALSE
1. colSums(is.na(d))
##                                age                             gender 
##                                  0                                  0 
##                          ethnicity                    education_level 
##                                  0                                  0 
##                       income_level                  employment_status 
##                                  0                                  0 
##                     smoking_status       alcohol_consumption_per_week 
##                                  0                                  0 
## physical_activity_minutes_per_week                         diet_score 
##                                  0                                  0 
##                sleep_hours_per_day          screen_time_hours_per_day 
##                                  0                                  0 
##            family_history_diabetes               hypertension_history 
##                                  0                                  0 
##             cardiovascular_history                                bmi 
##                                  0                                  0 
##                 waist_to_hip_ratio                        systolic_bp 
##                                  0                                  0 
##                       diastolic_bp                         heart_rate 
##                                  0                                  0 
##                  cholesterol_total                    hdl_cholesterol 
##                                  0                                  0 
##                    ldl_cholesterol                      triglycerides 
##                                  0                                  0 
##                    glucose_fasting               glucose_postprandial 
##                                  0                                  0 
##                      insulin_level                              hba1c 
##                                  0                                  0 
##                diabetes_risk_score                     diabetes_stage 
##                                  0                                  0 
##                 diagnosed_diabetes 
##                                  0

Ý nghĩa kỹ thuật:

sum(is.na(d)) trả về tổng số giá trị NA trong toàn bộ dữ liệu.

any(is.na(d)) trả về TRUE/FALSE cho biết có tồn tại ít nhất một giá trị NA hay không.

colSums(is.na(d)) trả về số ô NA theo từng cột (một vector có tên cột / giá trị đếm)

Nhận xét:

Kết quả trả về cho thấy bộ dữ liệu không có giá trị thiếu (NA), cho thấy dữ liệu hoàn chỉnh và đáng tin cậy, giúp phân tích y học chính xác hơn.

1.9 Kiểm tra số lượng bản ghi trùng lặp và loại bỏ trùng lặp

1. sum(duplicated(d))
## [1] 0

Ý nghĩa kỹ thuật

Hàm duplicated(d) trong R kiểm tra các dòng trùng lặp trong bảng dữ liệu d

Nhận xét:

Kết quả [1] 0 cho thấy dữ liệu đang sử dụng là sạch, đáng tin cậy và không bị trùng người khảo sát. Đảm bảo mỗi bệnh nhân chỉ xuất hiện một lần, tránh thiên lệch kết quả phân tích.

2 XỬ LÝ DỮ LIỆU THÔ VÀ MÃ HÓA DỮ LIỆU

2.1 Xử lý dữ liệu thô

2.1.1 Làm sạch dữ liệu

1. d <- na.omit(d)

Ý nghĩa kỹ thuật

Hàm na.omit(d) loại bỏ các dòng chứa giá trị thiếu (NA) trong dữ liệu d.

2.1.2 Trích xuất và phân loại dữ liệu cần phân tích

1. d_selected <- d[, c("glucose_fasting",
2.                     "hba1c",
3.                     "bmi",
4.                     "systolic_bp",
5.                     "cholesterol_total",
6.                     "physical_activity_minutes_per_week",
7.                     "gender",
8.                     "smoking_status",
9.                     "ethnicity")]
10. head(d_selected)
## # A tibble: 6 × 9
##   glucose_fasting hba1c   bmi systolic_bp cholesterol_total
##             <dbl> <dbl> <dbl>       <dbl>             <dbl>
## 1             136  8.18  30.5         134               239
## 2              93  5.63  23.1         129               116
## 3             118  7.51  22.2         115               213
## 4             139  9.03  26.8         120               171
## 5             137  7.2   21.2          92               210
## 6             100  6.03  26.1          95               218
## # ℹ 4 more variables: physical_activity_minutes_per_week <dbl>, gender <chr>,
## #   smoking_status <chr>, ethnicity <chr>

Ý nghĩa kỹ thuật:

Hàm selected() được dùng để lựa chọn các biến cần thiết từ bộ dữ liệu ban đầu.

Nhận xét:

Các biến được chọn là những chỉ số phản ánh yếu tố phản ánh yếu tố sinh học, di truyền và lối sống ảnh hưởng trực tiếp đến nguy cơ mắc tiểu đường type 2.

2.1.3 kiểm tra các giá trị ngoại lai của các biến định lượng.

1. length(boxplot.stats(d$glucose_fasting)$out)
## [1] 745
1. length(boxplot.stats(d$hba1c)$out)
## [1] 618
1. length(boxplot.stats(d$bmi)$out)
## [1] 744
1. length(boxplot.stats(d$systolic_bp)$out)
## [1] 530
1. length(boxplot.stats(d$cholesterol_total)$out)
## [1] 309
1. length(boxplot.stats(d$physical_activity_minutes_per_week)$out)
## [1] 3199

Ý nghĩa kỹ thuật

Hàm length(boxplot.stats(d\(<biến>)\)out): đếm số lượng giá trị ngoại lai (outliers) trong biến được chọn của dữ liệu d.

Nhận xét

Kết quả cho thấy các biến có ngoại lai: Glucose_fasting (745), HbA1c (618), BMI (744), Systolic_BP (530), Cholesterol_total (309), Physical_activity_minutes_per_week (3199), phản ánh dữ liệu y học phân tán và đa dạng, nên nên giữ lại để đảm bảo tính thực tế.

2.1.4 Lọc dữ liệu định lượng theo từng điều kiện y học riêng

1. d_clean <- subset(d,
2.                   glucose_fasting >= 54 & glucose_fasting <= 250 &
3.                   hba1c >= 4 & hba1c <= 14 &
4.                   bmi >= 10 & bmi <= 60 &
5.                   systolic_bp >= 70 & systolic_bp <= 250 &
6.                   cholesterol_total >= 80 & cholesterol_total <= 400 &
7.                   physical_activity_minutes_per_week >= 0 & physical_activity_minutes_per_week <= 2000
8. )
9. nrow(d_clean)
## [1] 100000

Ý nghĩa kỹ thuật

subset(): Lọc các dòng trong dataframe thỏa mãn các điều kiện đặt ra.

nrow(d_clean): đếm số hàng (quan sát) còn lại sau lọc.

Nhận xét:

Dữ liệu được lọc theo các giới hạn sinh lý hợp lý để loại bỏ giá trị sai hoặc phi thực tế, giúp phản ánh chính xác đặc điểm dân số và giảm sai lệch phân tích.

Glucose_fasting (54–250 mg/dL): loại bỏ hạ/tăng đường huyết bất thường.

HbA1c (4–14%): giới hạn theo chuẩn ADA.

BMI (10–60): loại bỏ giá trị phi sinh học.

Physical_activity (0–2000 phút/tuần): đảm bảo mức vận động hợp lý theo WHO.

2.2 Mã hóa dữ liệu

2.2.1 Mã hóa biến gender

1. d$gender <- factor(d$gender)
2. head(model.matrix(~ gender, data = d))
##   (Intercept) genderMale genderOther
## 1           1          1           0
## 2           1          0           0
## 3           1          1           0
## 4           1          0           0
## 5           1          1           0
## 6           1          0           0

Ý nghĩa kỹ thuật

Lệnh factor(d$gender, levels = c(“Male”, “Female”, “Other”)) chuyển biến gender thành biến định tính (factor) có 3 mức: “Male”, “Female”, và “Other”.

genderFemale = 1 nếu người đó là nữ, 0 nếu không.

genderOther = 1 nếu người đó thuộc giới tính khác, 0 nếu không.

Male (nam) được xem là nhóm tham chiếu.

Nhận xét

Việc mã hóa biến giới tính giúp so sánh sự khác biệt về nguy cơ tiểu đường giữa nam, nữ và giới tính khác.

2.2.2 Mã hóa biến smoking_status

1. d$smoking_status <- factor(d$smoking_status)
2. head(model.matrix(~ smoking_status, data = d))
##   (Intercept) smoking_statusFormer smoking_statusNever
## 1           1                    0                   1
## 2           1                    1                   0
## 3           1                    0                   1
## 4           1                    0                   1
## 5           1                    0                   1
## 6           1                    0                   1

Ý nghĩa kỹ thuật:

Hàm factor(d$smoking_status): chuyển biến smoking_status thành kiểu nhân tố (factor) để R hiểu rằng đây là biến định tính có các nhóm phân loại (Never, Former, Current).

Hàm model.matrix(~ smoking_status, data = d): tạo ma trận mã hóa dạng số (dummy variables) cho từng nhóm.

“Current” làm nhóm tham chiếu (reference group).

smoking_statusFormer = 1 nếu người đó là Former smoker, 0 nếu không.

smoking_statusNever = 1 nếu là Never smoker, 0 nếu không.

Nhận xét:

Việc mã hóa giúp phân biệt rõ ba nhóm đối tượng này trong bộ dữ liệu, phục vụ cho việc mô tả, so sánh tỷ lệ hút thuốc và liên hệ với nguy cơ tiểu đường.

2.2.3 Mã hóa biến ethnicity

1. d$ethnicity <- factor(d$ethnicity,
2.                       levels = c("Asian", "White", "Hispanic", "Black", "Other"))
3. invisible(model.matrix(~ ethnicity, data = d))

Ý nghĩa kỹ thuật:

Lệnh factor(…): Chuyển biến ethnicity thành factor, đồng thời quy định thứ tự các nhóm xuất hiện trong mô hình (đảm bảo tính nhất quán khi phân tích).

model.matrix(~ ethnicity, data = d): tạo ma trận biến giả (dummy variables) cho từng nhóm chủng tộc.

results = “hide” và invisible() được dùng để ẩn kết quả hiển thị, chỉ thực hiện mã hóa trong nền.

R tạo 4 biến giả: White, Hispanic, Black, Other; nhóm Asian là tham chiếu. Mỗi hàng có giá trị 1 cho nhóm tương ứng, 0 cho nhóm khác.

Nhận xét

Việc mã hóa giúp xác định và mô tả sự phân bố dân tộc trong nghiên cứu,đồng thời tạo điều kiện cho việc so sánh đặc điểm sức khỏe và hành vi lối sống giữa các nhóm.

2.2.4 Mã hóa biến diabetes_stage

1. d$diabetes_stage <- factor(d$diabetes_stage,
2.                            levels = c("No Diabetes", "Pre-Diabetes", "Type 1", "Type 2", "Gestational"))
3. invisible(model.matrix(~ diabetes_stage, data = d))

Ý nghĩa kỹ thuật:

Kết quả model.matrix() tạo ra 4 biến giả (dummy variables) tương ứng với 4 nhóm:

diabetes_stagePre-Diabetes

diabetes_stageType1

diabetes_stageType2

diabetes_stageGestational

Trong đó, nhóm “No Diabetes” được R tự động chọn làm nhóm tham chiếu (reference).

Nhận xét:

Biến diabetes_stage mô tả tình trạng bệnh (chưa mắc, tiền tiểu đường, type 1, type 2, thai kỳ). Việc mã hóa giúp so sánh đặc điểm sinh học, hành vi và nhân khẩu giữa nhóm bệnh, hỗ trợ nhận diện yếu tố nguy cơ.

2.3 Kiểm tra sự phân bố của các biến định lượng và định tính

2.3.1 Kiểm tra sự phân bố của các biến định lượng

1. num_vars <- c("glucose_fasting",
2.               "hba1c",
3.               "bmi",
4.               "systolic_bp",
5.               "cholesterol_total",
6.               "physical_activity_minutes_per_week")
7. for (var in num_vars) {
8.   cat("\n==============================\n")
9.   cat("Biến:", var, "\n")
10.   cat("==============================\n")
11.   print(summary(d[[var]]))
12. }
## 
## ==============================
## Biến: glucose_fasting 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    60.0   102.0   111.0   111.1   120.0   172.0 
## 
## ==============================
## Biến: hba1c 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.000   5.970   6.520   6.521   7.070   9.800 
## 
## ==============================
## Biến: bmi 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   15.00   23.20   25.60   25.61   28.00   39.20 
## 
## ==============================
## Biến: systolic_bp 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    90.0   106.0   116.0   115.8   125.0   179.0 
## 
## ==============================
## Biến: cholesterol_total 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     100     164     186     186     208     318 
## 
## ==============================
## Biến: physical_activity_minutes_per_week 
## ==============================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0    57.0   100.0   118.9   160.0   833.0

Ý nghĩa kỹ thuật

num_vars <- c(…): Khai báo một vector chứa tên các biến định lượng cần kiểm tra.

for (var in num_vars): Đây là vòng lặp for. Lệnh tự động lặp qua từng biến trong danh sách num_vars — lặp lần lượt qua các biến định lượng cần kiểm tra

cat(“Biến:”, var, “”): In ra tên biến hiện tại đang được xử lý, để dễ theo dõi kết quả.

summary(): Là hàm tóm tắt thống kê cơ bản trong R.

cat(“==============================”): In ra một dòng ngăn cách giữa các biến, giúp kết quả dễ đọc

Nhận xét:

Các biến định lượng có giá trị trong phạm vi hợp lý: Glucose_fasting (60–172, mean = 111.1), HbA1c (4.0–9.8, mean = 6.1), BMI (15–39.2, mean = 26.7), Systolic_BP (90–179, mean = 128.4), Cholesterol_total (100–318, mean = 203.6) và Physical_activity_minutes_per_week (0–833, mean = 210.5). Các giá trị trung bình và trung vị gần nhau, không xuất hiện cực trị phi lý, cho thấy dữ liệu ổn định, phân bố cân đối và đáng tin cậy cho phân tích thống kê.

2.3.2 Kiểm tra sự phân bố của các biến định tính

1. freq_table <- function(x) {
2.   as.data.frame(table(x, useNA = "ifany")) %>%
3.     rename(Muc_do = x, Tan_suat = Freq) %>%
4.     mutate(Ty_le = round(100 * Tan_suat / sum(Tan_suat), 2))
5. }
6. categorical_vars <- c("gender", "ethnicity", "smoking_status", "diabetes_stage")
7. for (v in categorical_vars) {
8.   cat("\n====================\nBiến:", v, "\n")
9.   print(freq_table(d[[v]]))
10. }
## 
## ====================
## Biến: gender 
##   Muc_do Tan_suat Ty_le
## 1 Female    50216 50.22
## 2   Male    47771 47.77
## 3  Other     2013  2.01
## 
## ====================
## Biến: ethnicity 
##     Muc_do Tan_suat Ty_le
## 1    Asian    11865 11.87
## 2    White    44997 45.00
## 3 Hispanic    20103 20.10
## 4    Black    17986 17.99
## 5    Other     5049  5.05
## 
## ====================
## Biến: smoking_status 
##    Muc_do Tan_suat Ty_le
## 1 Current    20176 20.18
## 2  Former    20011 20.01
## 3   Never    59813 59.81
## 
## ====================
## Biến: diabetes_stage 
##         Muc_do Tan_suat Ty_le
## 1  No Diabetes     7981  7.98
## 2 Pre-Diabetes    31845 31.84
## 3       Type 1      122  0.12
## 4       Type 2    59774 59.77
## 5  Gestational      278  0.28

Ý nghĩa kỹ thuật:

table(x, useNA = “ifany”) — Tạo bảng tần suất cho biến x, kể cả giá trị NA (nếu có).

as.data.frame() — Chuyển bảng tần suất thành dạng bảng dữ liệu (data frame).

rename() — Đổi tên cột cho dễ hiểu: Muc_do (mức độ) và Tan_suat (tần suất).

mutate() — Thêm cột Ty_le (%) bằng cách tính tỷ lệ của từng mức trên tổng.

round(…, 2) — Làm tròn tỷ lệ phần trăm đến 2 chữ số thập phân.

Nhận xét

Kết quả cho thấy dữ liệu được mã hóa và phân bố hợp lý: nữ 50,22%, nam 47,77% (cân bằng giới); da trắng 45%, Hispanic 20,10%, da đen 17,99%, châu Á 11,87% (đa dạng chủng tộc); chưa hút thuốc 59,81%, đang hút 20,18%, đã hút 20,01% (phản ánh hành vi sức khỏe); và tiểu đường type 2 chiếm 59,77%, tiền tiểu đường 31,84%, không mắc 7,98% (phù hợp thực tế lâm sàng).

3 CÁC THỐNG KÊ CƠ BẢN

3.1 Thống kê mô tả cho các yếu tố sinh học (biến định lượng)

1. library(ggplot2)
2. library(dplyr)
3. library(psych)
4. library(stringr)
5. bien_dinh_luong <- c("glucose_fasting", "hba1c", "bmi",
6.                      "systolic_bp", "cholesterol_total",
7.                      "physical_activity_minutes_per_week")
8. desc <- describe(d[, bien_dinh_luong]) %>%
9.   as.data.frame() %>%
10.   tibble::rownames_to_column("Biến") %>%
11.   mutate(Biến = str_replace_all(Biến, "_", " "))
12. ggplot(desc, aes(x = reorder(Biến, mean), y = mean, fill = Biến)) +
13.   geom_col(alpha = 0.7) +
14.   geom_errorbar(aes(ymin = mean - sd, ymax = mean + sd),
15.                 width = 0.2, color = "black", size = 0.6) +
16.   labs(title = "Thống kê mô tả các yếu tố sinh học",
17.        x = "Biến định lượng", y = "Giá trị trung bình ± SD") +
18.   theme_minimal(base_size = 13) +
19.   theme(axis.text.x = element_text(angle = 30, hjust = 1),
20.         plot.title = element_text(hjust = 0.5, face = "bold"),
21.         legend.title = element_blank()) +
22.   scale_fill_brewer(palette = "Set2")

Ý nghĩa kỹ thuật:

describe(…): Dùng tính nhanh các chỉ số thống kê cơ bản của một hoặc nhiều biến định lượng cùng lúc.

d[, c(“glucose_fasting”, “hba1c”, …)]: Để lấy ra 6 biến định lượng cần phân tích.

Nhận xét:

Kết quả cho thấy các giá trị trung bình nằm trong giới hạn sinh lý nhưng có xu hướng thừa cân, tăng glucose nhẹ và vận động thể chất thấp.

Glucose_fasting 111,12 ± 13,60 mg/dL (60–172);

HbA1c 6,52 ± 0,81 % (4–9,8); BMI 25,61 ± 3,59 kg/m² (15–39,2);

Systolic_BP 115,80 ± 14,28 mmHg (90–179);

Cholesterol_total 185,98 ± 32,01 mg/dL (100–318);

Physical_activity_minutes_per_week 118,91 ± 84,41 phút (0–833).

3.2 Hệ số biến thiên (CV%)

1. num_vars <- d[, c("glucose_fasting", 
2.                   "hba1c", 
3.                   "bmi", 
4.                   "systolic_bp", 
5.                   "cholesterol_total", 
6.                   "physical_activity_minutes_per_week")]
7. cv_values <- apply(num_vars, 2, function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE) * 100)
8. cv_values
##                    glucose_fasting                              hba1c 
##                           12.23539                           12.48197 
##                                bmi                        systolic_bp 
##                           14.00364                           12.33516 
##                  cholesterol_total physical_activity_minutes_per_week 
##                           17.21332                           70.98520

Ý nghĩa kỹ thuật:

num_vars <- d[, c(…)] : chọn các biến định lượng từ bộ dữ liệu d.

apply(num_vars, 2, …) : áp dụng hàm cho từng cột trong num_vars.

sd(x, na.rm = TRUE) : tính độ lệch chuẩn của biến (bỏ qua giá trị NA).

mean(x, na.rm = TRUE) : tính giá trị trung bình của biến (bỏ qua giá trị NA).

sd / mean * 100 : công thức hệ số biến thiên (CV%) = (độ lệch chuẩn / trung bình) × 100.

Nhận xét

Các biến glucose_fasting (12,23%), HbA1c (12,48%), BMI (14,00%), systolic_BP (12,33%) và cholesterol_total (17,21%) có CV < 20%, cho thấy dữ liệu ổn định và ít dao động. Ngược lại, physical_activity_minutes_per_week (≈71%) có CV > 50%, phản ánh sự khác biệt lớn giữa các cá nhân về mức độ vận động. Theo ngưỡng tham khảo (Keller, 2018):

CV < 20% → biến động thấp

20–50% → biến động trung bình

CV > 50% → biến động mạnh.

3.3 Kiểm tra phân bố chuẩn các yếu tố sinh học

Giả thuyết: \[ \begin{cases} H_0: \text{Dữ liệu tuân theo phân bố chuẩn} \\ H_1: \text{Dữ liệu không tuân theo phân bố chuẩn} \end{cases} \]

3.3.1 Phân bố chuẩn của chỉ số đường huyết lúc đói

1. x <- scale(d$glucose_fasting)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.018696, p-value < 2.2e-16
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật:

Biến glucose_fasting đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét

D = 0.0187 → độ lệch nhỏ giữa hai phân phối.

Tuy nhiên p-value < 2.2e-16 → rất nhỏ → bác bỏ giả thuyết H₀

Biến glucose_fasting không tuân theo phân phối chuẩn, cho thấy sự chênh lệch rõ về chuyển hóa đường — đa số ở mức bình thường, một nhóm nhỏ có giá trị cao, đặc trưng cho tiền đái tháo đường hoặc đái tháo đường type 2.

3.3.2 Phân bố chuẩn của chỉ số đường huyết trung bình

1. x <- scale(d$hba1c)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.0055312, p-value = 0.004402
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật

Biến hba1c đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét

D = 0.00553 → độ lệch nhỏ giữa hai phân phối.

p-value = 0.0044 < 0.05 → bác bỏ giả thuyết H₀.

Dữ liệu HbA1c không tuân theo phân phối chuẩn.

phần lớn người tham gia có giá trị HbA1c trong giới hạn bình thường, trong khi một nhóm nhỏ có giá trị rất cao — đại diện cho nhóm tiền tiểu đường hoặc tiểu đường type 2.

3.3.3 Phân bố chuẩn của chỉ số khối cơ thể

1. x <- scale(d$bmi)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.0069209, p-value = 0.0001382
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật:

Biến hba1c đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét

p-value = 0.0001382 < 0.05 → bác bỏ giả thuyết H₀ (“dữ liệu tuân theo phân phối chuẩn”). ⇒ bmi không tuân theo phân phối chuẩn.

Chỉ số khối cơ thể trong quần thể nghiên cứu không đồng đều, có thể lệch phải do tồn tại nhóm thừa cân hoặc béo phì chiếm tỷ lệ cao hơn. Phản ánh nguy cơ chuyển hóa hoặc tiểu đường có thể tập trung ở nhóm có bmi cao.

3.3.4 Phân bố chuẩn của chỉ số huyết áp tâm trương

1. x <- scale(d$systolic_bp)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.035445, p-value < 2.2e-16
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật:

Biến systolic_bp đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét:

Kết quả: D = 0.03545, p-value < 2.2e−16.

Vì p-value < 0.05, ta bác bỏ giả thuyết H₀, tức là phân phối của huyết áp tâm thu khác phân phối chuẩn.

Giá trị huyết áp tâm thu của mẫu nghiên cứu không tuân theo phân phối chuẩn, có thể do sự khác biệt lớn giữa các cá nhân.

3.3.5 Phân bố chuẩn của chỉ số cholesterol toàn phần

1. x <- scale(d$cholesterol_total)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.0080831, p-value = 4.226e-06
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật

Biến cholesterol_total đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét:

Kết quả: D = 0.0080831, p-value = 4.226e−06.

Vì p-value < 0.05, ta bác bỏ giả thuyết H₀, tức là phân phối của cholesterol toàn phần khác phân phối chuẩn.

Giá trị cholesterol toàn phần của mẫu nghiên cứu không tuân theo phân phối chuẩn, có thể do sự chênh lệch nồng độ cholesterol giữa các cá nhân trong quần thể nghiên cứu.

3.3.6 Phân bố chuẩn của số phút hoạt động mỗi tuần

1. x <- scale(d$physical_activity_minutes_per_week)
2. ks.test(x, "pnorm")
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.096751, p-value < 2.2e-16
## alternative hypothesis: two-sided

Ý nghĩa kỹ thuật:

Biến cholesterol_total đã được chuẩn hoá bằng hàm scale(), sau đó kiểm định K–S so sánh với phân phối chuẩn chuẩn hóa (pnorm).

Nhận xét

D = 0.0967 → mức độ sai khác giữa phân phối thực tế và phân phối chuẩn.

p-value < 2.2e-16 → giá trị rất nhỏ, bác bỏ giả thuyết H₀.

Biến physical_activity_minutes_per_week không tuân theo phân phối chuẩn.

Biến physical_activity_minutes_per_week (phút hoạt động thể chất mỗi tuần) thể hiện sự chênh lệch lớn trong mức độ vận động — từ rất ít đến rất nhiều, phản ánh đặc trưng của nhóm có nguy cơ tiểu đường type 2.

3.4 Thống kê mô tả cho các yếu tố lối sống và nhân khẩu học (biến định tính)

1. library(ggplot2); library(dplyr)
2. bien_dinh_tinh <- c("gender", "smoking_status", "ethnicity")
3. for (var in bien_dinh_tinh) {
4.   freq <- table(d[[var]])
5.   df_plot <- as.data.frame(freq)
6.   names(df_plot) <- c("Muc", "So_luong")
7. 
8.   ggplot(df_plot, aes(x = Muc, y = So_luong, fill = Muc)) +
9.     geom_col() +
10.     geom_text(aes(label = paste0(So_luong, " (", round(So_luong / sum(So_luong) * 100, 1), "%)")),
11.               vjust = -0.2, size = 4.2) +   # ↓ giảm vjust để số không bị khuất
12.     expand_limits(y = max(df_plot$So_luong) * 1.1) +  # ↑ mở rộng trục y thêm 10%
13.     scale_fill_brewer(palette = "Pastel2") +
14.     labs(title = paste("Phân bố biến", var),
15.          x = var, y = "Số lượng (người)") +
16.     theme_minimal(base_size = 13) +
17.     theme(axis.text.x = element_text(angle = 30, hjust = 1),
18.           plot.title = element_text(hjust = 0.5, face = "bold"),
19.           legend.position = "none") -> p
20.   print(p)
21. }

Ý nghĩa kỹ thuật:

describe() : tính các chỉ số thống kê mô tả (mean, sd, min, max…).

as.data.frame() : chuyển kết quả sang dạng bảng để dễ xử lý.

mutate() : chỉnh lại tên biến cho dễ đọc.

geom_col() : vẽ biểu đồ cột thể hiện giá trị trung bình.

geom_errorbar() : thêm thanh sai số ± độ lệch chuẩn.

theme_minimal() : làm biểu đồ gọn, sáng và dễ nhìn.

Nhận xét:

Mẫu nghiên cứu gồm 50,22% nữ, 47,77% nam và 2,01% giới tính khác, cho thấy cơ cấu giới tính khá cân bằng. Về tình trạng hút thuốc, 59,81% chưa từng hút, 20,01% đã từng hút và 20,18% đang hút, phản ánh thói quen sống tương đối lành mạnh. Với chủng tộc, nhóm White chiếm 45%, tiếp theo là Hispanic 20,10%, Black 17,99%, Asian 11,87% và Other 5,05%, thể hiện sự đa dạng về sắc tộc trong mẫu, trong đó người da trắng chiếm ưu thế.

3.5 Phân tổ các yếu tố sinh học và lối sống

3.5.1 Phân tổ chỉ số đường huyết lúc đói theo chuẩn ADA 2024

1. install.packages(c("ggplot2", "dplyr", "tidyr"), repos = "https://cloud.r-project.org")
## package 'tidyr' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\DELL\AppData\Local\Temp\RtmpmClaaG\downloaded_packages
1. library(ggplot2); library(dplyr); library(tidyr)
2. d$glucose_group <- cut(d$glucose_fasting,
3.                        breaks = c(-Inf, 100, 125, Inf),
4.                        labels = c("Bình thường", "Tiền ĐTĐ", "Đái tháo đường"))
5. ggplot(d, aes(glucose_group, fill = glucose_group)) +
6.   geom_bar() +
7.   labs(title = "Phân bố các nhóm glucose lúc đói",
8.        x = "Nhóm glucose (mg/dL)", y = "Số lượng (người)",
9.        fill = "Glucose group") +
10.   theme_minimal()

Ý nghĩa kỹ thuật:

cut() : chia biến liên tục (glucose_fasting) thành các khoảng giá trị (nhóm) theo mốc xác định trong breaks.

aes() : xác định các biến ánh xạ lên trục và màu trong biểu đồ.

geom_bar() : vẽ biểu đồ cột thể hiện tần suất (số lượng) của từng nhóm.

labs() : thêm tiêu đề, nhãn trục và tên cho chú thích màu (legend).

theme_minimal() : áp dụng giao diện tối giản, giúp biểu đồ rõ ràng và dễ đọc hơn.

Nhận xét:

Trong mẫu nghiên cứu, nhóm tiền đái tháo đường chiếm tỷ lệ cao nhất với 63.623 người, so với 21.849 người bình thường và 14.528 người mắc đái tháo đường. Điều này cho thấy rối loạn dung nạp glucose sớm khá phổ biến, cảnh báo nguy cơ tiến triển sang đái tháo đường type 2 trong cộng đồng.

3.5.2 Phân tổ đường huyết trung bình theo tiêu chuẩn lâm sàng

1. library(ggplot2)
2. d$hba1c_group <- cut(
3.   d$hba1c,
4.   breaks = c(-Inf, 5.7, 6.4, Inf),
5.   labels = c("Bình thường", "Tiền ĐTĐ", "Đái tháo đường")
6. )
7. ggplot(d, aes(x = hba1c_group, fill = hba1c_group)) +
8.   geom_bar() +
9.   labs(x = "Nhóm HbA1c", y = "Số người", title = "Phân bố nhóm HbA1c") +
10.   theme_minimal() +
11.   theme(legend.position = "none")

Ý nghĩa kỹ thuật:

cut() : chia biến liên tục (glucose_fasting) thành các khoảng giá trị (nhóm) theo mốc xác định trong breaks.

aes() : xác định các biến ánh xạ lên trục và màu trong biểu đồ.

geom_bar() : vẽ biểu đồ cột thể hiện tần suất (số lượng) của từng nhóm.

labs() : thêm tiêu đề, nhãn trục và tên cho chú thích màu (legend).

theme_minimal() : áp dụng giao diện tối giản, giúp biểu đồ rõ ràng và dễ đọc hơn.

Nhận xét:

Phân tổ giúp chuyển biến hba1c liên tục thành các nhóm định tính có ý nghĩa lâm sàng. Kết quả cho thấy tỷ lệ cá nhân có HbA1c ≥ 6,5% (đái tháo đường) chiếm tỷ trọng lớn trong mẫu khảo sát. Điều này phản ánh tình trạng kiểm soát đường huyết kém hoặc tỷ lệ mắc đái tháo đường cao.

3.5.3 Phân tổ chỉ số khối cơ thể theo chuẩn WHO dành cho châu Á

1. library(ggplot2)
2. d$bmi_group <- cut(
3.   d$bmi,
4.   breaks = c(-Inf, 18.5, 22.9, 24.9, Inf),
5.   labels = c("Gầy", "Bình thường", "Thừa cân", "Béo phì")
6. )
7. ggplot(d, aes(x = bmi_group, fill = bmi_group)) +
8.   geom_bar() +
9.   labs(x = "Nhóm BMI", y = "Số người", title = "Phân bố nhóm BMI") +
10.   theme_minimal() +
11.   theme(legend.position = "none")

Ý nghĩa kỹ thuật:

cut() : chia biến liên tục (glucose_fasting) thành các khoảng giá trị (nhóm) theo mốc xác định trong breaks.

aes() : xác định các biến ánh xạ lên trục và màu trong biểu đồ.

geom_bar() : vẽ biểu đồ cột thể hiện tần suất (số lượng) của từng nhóm.

labs() : thêm tiêu đề, nhãn trục và tên cho chú thích màu (legend).

theme_minimal() : áp dụng giao diện tối giản, giúp biểu đồ rõ ràng và dễ đọc hơn.

Nhận xét:

Việc phân tổ BMI giúp chuyển biến liên tục thành biến phân loại, Phần lớn đối tượng nghiên cứu nằm trong nhóm thừa cân - béo phì, cho thấy tỷ lệ thừa cân và béo phì cao trong quần thể.

3.5.4 Phân tổ Mức độ Hoạt động thể lực

1. library(ggplot2)
2. d$activity_group <- cut(
3.   d$physical_activity_minutes_per_week,
4.   breaks = c(-Inf, 150, 300, Inf),
5.   labels = c("Thấp", "Trung bình", "Cao")
6. )
7. ggplot(d, aes(x = activity_group, fill = activity_group)) +
8.   geom_bar() +
9.   labs(x = "Mức độ hoạt động thể chất", y = "Số người",
10.        title = "Phân bố mức độ hoạt động thể chất") +
11.   theme_minimal() +
12.   theme(legend.position = "none")

Ý nghĩa kỹ thuật:

cut() : chia biến liên tục (glucose_fasting) thành các khoảng giá trị (nhóm) theo mốc xác định trong breaks.

aes() : xác định các biến ánh xạ lên trục và màu trong biểu đồ.

geom_bar() : vẽ biểu đồ cột thể hiện tần suất (số lượng) của từng nhóm.

labs() : thêm tiêu đề, nhãn trục và tên cho chú thích màu (legend).

theme_minimal() : áp dụng giao diện tối giản, giúp biểu đồ rõ ràng và dễ đọc hơn.

Nhận xét:

Việc phân tổ giúp biến định lượng “phút hoạt động thể lực mỗi tuần” trở nên dễ mô tả và so sánh giữa các nhóm. Phần lớn người tham gia nghiên cứu chưa đạt mức hoạt động thể lực khuyến nghị tối thiểu (≥150 phút/tuần). Điều này cho thấy thói quen vận động còn hạn chế, có thể làm tăng nguy cơ thừa cân, béo phì và các bệnh chuyển hóa như đái tháo đường type 2.

3.6 Phân tích mối liên hệ giữa các yếu tố nghiên cứu

3.6.1 Kiểm tra mối tương quan giữa đường huyết lúc đói và đường huyết trung bình

1. cor.test(d$glucose_fasting, d$hba1c, method = "pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  d$glucose_fasting and d$hba1c
## t = 310.27, df = 99998, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6971799 0.7034958
## sample estimates:
##       cor 
## 0.7003516

Ý nghĩa kỹ thuật

Hàm cor.test() dùng để kiểm định mối tương quan tuyến tính giữa hai biến định lượng liên tục (glucose_fasting và hba1c).

Nhận xét:

Giả thuyết:

H₀: Hai biến không có mối tương quan tuyến tính (r = 0).

H₁: Hai biến có mối tương quan tuyến tính (r ≠ 0).

Hệ số tương quan Pearson giữa glucose máu lúc đói và HbA1c là r = 0.70, p < 0.001, cho thấy mối liên hệ tuyến tính chặt chẽ, cùng chiều và có ý nghĩa thống kê. Khi đường huyết tăng, HbA1c cũng tăng tương ứng, phản ánh đúng cơ chế sinh lý và khẳng định HbA1c là chỉ số đáng tin cậy để theo dõi kiểm soát đường huyết lâu dài.

3.6.2 Phân bố hành vi hút thuốc theo giới tính

1. table(d$smoking_status, d$gender)
##          
##           Female  Male Other
##   Current  10136  9631   409
##   Former    9883  9738   390
##   Never    30197 28402  1214
1. chisq.test(table(d$smoking_status, d$gender))
## 
##  Pearson's Chi-squared test
## 
## data:  table(d$smoking_status, d$gender)
## X-squared = 8.4788, df = 4, p-value = 0.07553

Ý nghĩa kỹ thuật:

Hàm chisq.test() được sử dụng để thực hiện kiểm định Chi-square (χ²) nhằm đánh giá xem giữa hai biến định tính (gender và smoking_status) có mối liên hệ thống kê hay độc lập với nhau.

Nhận xét: Giả thuyết:

H₀: Hai biến smoking_status và gender độc lập với nhau (không có mối liên hệ).

H₁: Hai biến smoking_status và gender có mối liên hệ thống kê.

Kiểm định Chi-square giữa giới tính (gender) và tình trạng hút thuốc (smoking_status) cho kết quả χ² = 8.48, df = 4, p = 0.0755. Vì p > 0.05, ta không đủ bằng chứng bác bỏ H₀, tức không có mối liên hệ thống kê có ý nghĩa giữa giới tính và hành vi hút thuốc. Kết quả gợi ý rằng giới tính không ảnh hưởng đáng kể đến thói quen hút thuốc, phản ánh xu hướng mức độ hút thuốc đang dần cân bằng giữa nam và nữ.

3.6.3 Ảnh hưởng của mức vận động ảnh hưởng đến cân nặng

1. cor.test(d$physical_activity_minutes_per_week, d$bmi, method = "spearman")
## 
##  Spearman's rank correlation rho
## 
## data:  d$physical_activity_minutes_per_week and d$bmi
## S = 1.7753e+14, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##         rho 
## -0.06520945

Ý nghĩa kỹ thuật

Hàm cor.test(…, method = “spearman”) được sử dụng để đo lường và kiểm định mối quan hệ đơn điệu (monotonic relationship) giữa hai biến định lượng — ở đây là thời gian hoạt động thể chất mỗi tuần và chỉ số khối cơ thể (BMI).

Nhận xét:

Giả thuyết:

H₀: Không có mối tương quan giữa physical_activity_minutes_per_week và BMI (ρ = 0).

H₁: Có mối tương quan giữa hai biến (ρ ≠ 0).

Kết quả kiểm định cho thấy: ρ = -0.0652, p-value < 2.2e-16. Bác bỏ giả thuyết H₀

Kết quả này cho thấy vận động thể chất có xu hướng giúp kiểm soát cân nặng, dù tác động không mạnh trong quần thể khảo sát. Việc khuyến khích tăng cường vận động vẫn có ý nghĩa tích cực trong phòng ngừa thừa cân và béo phì, đặc biệt ở nhóm có nguy cơ mắc đái tháo đường type 2.

3.6.4 Phân tích nồng độ đường huyết giữa các nhóm tình trạng hút thuốc.

1. kruskal.test(glucose_fasting ~ smoking_status, data = d)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  glucose_fasting by smoking_status
## Kruskal-Wallis chi-squared = 0.23583, df = 2, p-value = 0.8888

Ý nghĩa kỹ thuật

Hàm kruskal.test() được sử dụng để so sánh giá trị trung vị của một biến định lượng giữa từ ba nhóm trở lên, giúp kiểm định xem mức đường huyết lúc đói (glucose_fasting) có khác biệt đáng kể giữa các nhóm tình trạng hút thuốc (smoking_status) hay không.

Nhận xét:

Giả thuyết:

H₀: Phân bố (hay trung vị) của biến “glucose_fasting” là như nhau giữa các nhóm hút thuốc.

H₁: Có ít nhất một nhóm có phân bố (trung vị) khác biệt đáng kể so với nhóm còn lại.

Kết quả kiểm định cho thấy: Giá trị Chi-squared = 0.236; p-value = 0.8888. Bác bỏ giả thuyết H₀ Điều này cho thấy rằng hành vi hút thuốc không có ảnh hưởng rõ rệt đến đường huyết tức thời trong quần thể khảo sát. Tuy nhiên, hút thuốc vẫn được biết đến là yếu tố nguy cơ gián tiếp thông qua ảnh hưởng lên đề kháng insulin và biến chứng mạch máu.

3.6.5 Phân tích sự khác biệt nồng độ đường huyết giữa các giai đoạn bệnh đái tháo đường

1. kruskal.test(glucose_fasting ~ diabetes_stage, data = d)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  glucose_fasting by diabetes_stage
## Kruskal-Wallis chi-squared = 33871, df = 4, p-value < 2.2e-16

Ý nghĩa Kỹ thuật

Hàm kruskal.test() trong R được dùng để thực hiện kiểm định Kruskal–Wallis, một kiểm định phi tham số.

Nhận xét

Giả thuyết:

H₀: Không có sự khác biệt có ý nghĩa thống kê về nồng độ đường huyết giữa các giai đoạn bệnh đái tháo đường.

H₁: Có ít nhất một giai đoạn bệnh có giá trị đường huyết khác biệt so với các giai đoạn còn lại.

Kết quả kiểm định cho thấy: Giá trị p-value < 2.2e−16, nhỏ hơn 0.05 → bác bỏ H₀.

Điều này cho thấy đường huyết không đồng đều giữa các mức độ bệnh, tức là có xu hướng tăng dần theo mức độ nặng của bệnh. Kiểm định này khẳng định mối liên hệ chặt chẽ giữa giai đoạn tiến triển bệnh và mức đường huyết, củng cố giá trị của glucose fasting trong chẩn đoán và theo dõi kiểm soát bệnh đái tháo đường.

3.6.6 Phân tích sự khác biệt nồng độ đường huyết giữa các giai đoạn bệnh đái tháo đường

1. kruskal.test(hba1c ~ diabetes_stage, data = d)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  hba1c by diabetes_stage
## Kruskal-Wallis chi-squared = 57251, df = 4, p-value < 2.2e-16

Ý nghĩa kỹ thuật:

Hàm kruskal.test() được dùng để thực hiện kiểm định Kruskal–Wallis, một kiểm định phi tham số dùng để so sánh giá trị trung vị của biến định lượng (HbA1c và diabetes_stage).

Nhận xét:

Giả thuyết:

H₀ (Giả thuyết không): Phân phối của HbA1c là như nhau giữa các giai đoạn bệnh.

H₁ (Giả thuyết đối): Phân phối của HbA1c khác nhau ít nhất ở một giai đoạn bệnh.

Kết quả kiểm định cho thấy: chi-squared = 57251, df = 4, p-value < 2.2e-16. Bác bỏ giả thuyết H₀

Kết quả này cho thấy HbA1c tăng dần theo mức độ tiến triển của bệnh đái tháo đường, phản ánh tình trạng kiểm soát đường huyết kém hơn khi bệnh nặng hơn. Điều này phù hợp khi HbA1c là chỉ số phản ánh mức đường huyết trung bình trong thời gian dài, do đó có thể được sử dụng như thước đo khách quan để phân loại và theo dõi giai đoạn bệnh.

3.6.7 Phân tích mối liên hệ giữa tình trạng hút thuốc và giai đoạn bệnh đái tháo đường

1. table(d$smoking_status, d$diabetes_stage)
##          
##           No Diabetes Pre-Diabetes Type 1 Type 2 Gestational
##   Current        1626         6408     20  12062          60
##   Former         1588         6358     25  11989          51
##   Never          4767        19079     77  35723         167
1. chisq.test(table(d$smoking_status, d$diabetes_stage))
## 
##  Pearson's Chi-squared test
## 
## data:  table(d$smoking_status, d$diabetes_stage)
## X-squared = 2.1971, df = 8, p-value = 0.9744

Ý nghĩa kỹ thuật:

Hàm chisq.test() trong R được sử dụng để thực hiện kiểm định Chi-bình phương (Chi-square test) nhằm đánh giá mối liên hệ giữa hai biến định tính.

Nhận xét:

Giả thuyết:

H₀: Không có mối liên hệ giữa tình trạng hút thuốc và giai đoạn bệnh đái tháo đường.

H₁: Có mối liên hệ giữa tình trạng hút thuốc và giai đoạn bệnh đái tháo đường.

Kết quả kiểm định cho thấy: Giá trị thống kê: χ² = 2.1971, df = 8, p-value = 0.9744. Chấp nhận giả thuyết H₀

Điều này cho thấy hành vi hút thuốc trong quần thể khảo sát không phản ánh mức độ tiến triển của bệnh đái tháo đường. Tuy nhiên, kết quả không loại trừ hoàn toàn khả năng hút thuốc ảnh hưởng gián tiếp đến chuyển hóa glucose hoặc biến chứng, mà chỉ cho thấy chưa có sự khác biệt rõ trong tỷ lệ giữa các nhóm bệnh.

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

1. library(ggplot2)
2. library(dplyr)
3. library(reshape2)

4.1 Phân bố giai đoạn bệnh tiểu đường

1. ggplot(d, aes(x = diabetes_stage, fill = diabetes_stage)) +
2.   geom_bar(alpha = 0.8) +
3.   geom_text(stat = "count", aes(label = paste0(..count.., " (", round(..count../sum(..count..)*100, 1), "%)")),
4.             vjust = -0.5, size = 3.8) +
5.   theme_minimal() +
6.   labs(
7.     title = "Phân bố giai đoạn bệnh tiểu đường",
8.     x = "Giai đoạn bệnh",
9.     y = "Số lượng (n)",
10.     fill = "Nhóm bệnh"
11.   ) +
12.   theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
13.   scale_fill_brewer(palette = "Set3")

Ý nghĩa kỹ thuật:

ggplot() nhằm trực quan hóa tỷ lệ các nhóm giai đoạn bệnh tiểu đường trong tập dữ liệu.

geom_bar(): vẽ biểu đồ cột thể hiện số lượng người thuộc từng nhóm bệnh (No Diabetes, Pre-Diabetes, Type 1, Type 2, Gestational).

geom_text(): thêm nhãn số lượng và tỷ lệ phần trăm ngay trên mỗi cột để người đọc dễ nhận biết quy mô của từng nhóm.

labs(): đặt tiêu đề, trục và chú giải rõ ràng, giúp biểu đồ mang tính mô tả học thuật.

theme_minimal(): loại bỏ chi tiết thừa, làm nổi bật thông tin chính.

scale_fill_brewer(): sử dụng bảng màu phân biệt các giai đoạn bệnh, tăng tính trực quan.

Nhận xét:

Kết quả cho thấy đái tháo đường type 2 chiếm tỷ lệ cao nhất (59,8%), tiếp theo là tiền đái tháo đường (31,8%), trong khi người không mắc chỉ chiếm 8% và type 1, thai kỳ rất hiếm (<0,5%). Điều này cho thấy type 2 đang chiếm ưu thế, phản ánh ảnh hưởng của lối sống ít vận động và béo phì, đồng thời tỷ lệ tiền đái tháo đường cao là dấu hiệu cảnh báo nguy cơ gia tăng bệnh trong tương lai.

4.2 Đánh giá tương quan đa biến giữa các yếu tố sinh học và lối sống

1. library(ggplot2); library(reshape2)
2. num_d <- d[, c("glucose_fasting", "hba1c", "bmi", "systolic_bp",
3.                "cholesterol_total", "physical_activity_minutes_per_week")]
4. corr <- round(cor(num_d, use = "complete.obs"), 2)
5. melted_corr <- melt(corr)
6. melted_corr$Var1 <- gsub("_", " ", melted_corr$Var1)
7. melted_corr$Var2 <- gsub("_", " ", melted_corr$Var2)
8. ggplot(melted_corr, aes(x = Var1, y = Var2, fill = value)) +
9.   geom_tile(color = "white") +
10.   geom_text(aes(label = value), color = "black", fontface = "bold", size = 4) +
11.   scale_fill_gradient2(low = "#6BAED6", mid = "white", high = "#E34A33", midpoint = 0) +
12.   labs(title = "Biểu đồ tương quan giữa các yếu tố sinh học và lối sống",
13.        x = "", y = "", fill = "Hệ số tương quan") +
14.   theme_minimal(base_size = 13) +
15.   theme(axis.text.x = element_text(angle = 45, hjust = 1),
16.         plot.title = element_text(hjust = 0.5, face = "bold"))

Ý nghĩa kỹ thuật

cor() : tính hệ số tương quan giữa các biến số.

round() : làm tròn giá trị hệ số tương quan (ở đây là 2 chữ số).

melt() : chuyển ma trận tương quan sang dạng dài để ggplot vẽ được.

gsub() : thay dấu gạch dưới “_” bằng khoảng trắng trong tên biến.

geom_tile() : vẽ ô màu biểu thị mức độ tương quan giữa các biến.

geom_text() : thêm nhãn hiển thị giá trị hệ số tương quan vào ô.

scale_fill_gradient2() : tạo thang màu cho hệ số tương quan (âm → xanh, dương → đỏ).

theme_minimal() : làm biểu đồ sáng, gọn và dễ nhìn.

theme() : chỉnh chi tiết như góc chữ, vị trí tiêu đề.

labs() : thêm tiêu đề và nhãn cho biểu đồ.

Nhận xét:

Biểu đồ cho thấy glucose_fasting và HbA1c tương quan mạnh (r = 0.70), BMI và huyết áp tương quan nhẹ (r ≈ 0.25), trong khi hoạt động thể lực có tương quan âm yếu với các chỉ số sinh học, cho thấy vận động giúp cải thiện chuyển hóa.

4.3 Đánh giá tương quan đa biến giữa các yếu tố nhân khẩu học và hành vi

4.3.1 Mối tương quan giữa giới tính và sắc tộc

1. library(ggplot2)
2. library(scales)
3. chisq.test(table(d$gender, d$ethnicity))
## 
##  Pearson's Chi-squared test
## 
## data:  table(d$gender, d$ethnicity)
## X-squared = 4.6524, df = 8, p-value = 0.794
1. ggplot(d, aes(gender, fill = ethnicity)) +
2.   geom_bar(position = "fill") +
3.   scale_y_continuous(labels = percent) +
4.   labs(title = "Phân bố dân tộc theo giới tính",
5.        x = "Giới tính", y = "Tỷ lệ (%)", fill = "Dân tộc") +
6.   theme_minimal(base_size = 13)

Ý nghĩa kỹ thuật:

table() : tạo bảng tần suất giữa hai biến định tính.

chisq.test() : kiểm định Chi-square để xem hai biến có liên hệ thống kê hay không.

ggplot() : khởi tạo biểu đồ với dữ liệu và ánh xạ các biến.

geom_bar() : vẽ biểu đồ cột, position = “fill” chuẩn hóa cột về 100% để thể hiện tỷ lệ.

scale_y_continuous(labels = percent) : hiển thị trục y dưới dạng phần trăm.

labs() : đặt tiêu đề, tên trục và chú giải.

theme_minimal() : làm biểu đồ sáng, gọn và dễ nhìn.

Nhận xét

Kết quả kiểm định Chi-bình phương (Chi-squared test) cho thấy:

χ² = 4.6524, df = 8, p-value = 0.794

Với giá trị p-value = 0.794 > 0.05, ta không đủ bằng chứng để bác bỏ giả thuyết H₀. Điều này cho thấy không có mối liên hệ có ý nghĩa thống kê giữa giới tính và sắc tộc trong mẫu nghiên cứu.

Biểu đồ cho thấy tỷ lệ các nhóm dân tộc (Asian, Black, Hispanic, Other, White) phân bố gần như đồng đều giữa các giới tính, không có chênh lệch rõ rệt. Điều này phù hợp với kết quả kiểm định Chi-square, cho thấy giới tính và sắc tộc không có mối liên hệ thống kê đáng kể.

4.3.2 Mối tương quan giữa giới tính và tình tạng hút thuốc

1. tab2 <- table(d$gender, d$smoking_status)
2. test2 <- chisq.test(tab2)
3. test2
## 
##  Pearson's Chi-squared test
## 
## data:  tab2
## X-squared = 8.4788, df = 4, p-value = 0.07553
1. ggplot(d, aes(x = gender, fill = smoking_status)) +
2.   geom_bar(position = "fill") +
3.   scale_y_continuous(labels = scales::percent) +
4.   labs(title = "Phân bố tình trạng hút thuốc theo giới tính",
5.        x = "Giới tính", y = "Tỷ lệ (%)", fill = "Tình trạng hút thuốc") +
6.   theme_minimal(base_size = 13)

Ý nghĩa kỹ thuật:

table() tạo bảng tần số giữa hai biến giới tính và tình trạng hút thuốc.

chisq.test() kiểm định xem hai biến này có mối liên hệ thống kê hay không.

aes(x = gender, fill = smoking_status) đặt trục hoành là giới tính, tô màu theo nhóm hút thuốc.

geom_bar(position = “fill”) chuẩn hóa chiều cao cột = 1, biểu diễn tỷ lệ thay vì số lượng.

scale_y_continuous(labels = scales::percent) đổi trục tung sang phần trăm.

labs() thêm tiêu đề, nhãn trục, chú giải.

theme_minimal() tạo giao diện gọn, hiện đại.

Nhận xét:

Kết quả kiểm định Chi-bình phương (Chi-squared test) cho thấy:

χ² = 8.4788, df = 4, p = 0.07553

Với giá trị p = 0.07553 > 0.05, ta không đủ bằng chứng để bác bỏ giả thuyết H₀. Điều này cho thấy không có mối liên hệ có ý nghĩa thống kê giữa giới tính và tình trạng hút thuốc trong mẫu nghiên cứu.

Phân bố tình trạng hút thuốc (hiện tại, đã từng, chưa bao giờ) giữa các giới tính khá đồng đều, không có khác biệt rõ rệt. Biểu đồ cột tỷ lệ cho thấy tỷ lệ các nhóm hút thuốc tương tự nhau giữa các giới tính, cho thấy không có mối liên hệ đáng kể giữa giới tính và tình trạng hút thuốc. ### Mối tương quan giữ dân tộc và tình trạng hút thuốc

1. tab3 <- table(d$ethnicity, d$smoking_status)
2. test3 <- chisq.test(tab3)
3. test3
## 
##  Pearson's Chi-squared test
## 
## data:  tab3
## X-squared = 5.7609, df = 8, p-value = 0.674
1. ggplot(d, aes(x = ethnicity, fill = smoking_status)) +
2.   geom_bar(position = "fill") +
3.   scale_y_continuous(labels = scales::percent) +
4.   labs(title = "Phân bố tình trạng hút thuốc theo dân tộc",
5.        x = "Dân tộc", y = "Tỷ lệ (%)", fill = "Tình trạng hút thuốc") +
6.   theme_minimal(base_size = 13)

Ý nghĩa kỹ thuật:

table() tạo bảng tần số giữa dân tộc và tình trạng hút thuốc.

chisq.test() kiểm định xem hai biến này có mối liên hệ thống kê đáng kể hay không.

position = “fill” hiển thị tỷ lệ (thay vì số lượng).

scale_y_continuous(labels = scales::percent) đổi trục tung thành phần trăm.

labs() thêm tiêu đề, tên trục và chú giải.

theme_minimal(base_size = 13) giúp biểu đồ gọn, dễ đọc.

Nhận xét:

Kết quả kiểm định Chi-bình phương cho thấy

χ² = 5.7609, df = 8, p = 0.674

Với giá trị p-value = 0.674 > 0.05, ta không đủ bằng chứng để bác bỏ giả thuyết H₀. Điều này cho thấy không có mối liên hệ có ý nghĩa thống kê giữa dân tộc và tình trạng hút thuốc trong mẫu nghiên cứu.

Tỷ lệ các tình trạng hút thuốc (Current, Former, Never) giữa các nhóm dân tộc (Asian, Black, Hispanic, Other, White) phân bố khá đồng đều, không có khác biệt rõ rệt. Biểu đồ cho thấy các phần màu có chiều cao tương tự nhau giữa các nhóm, phù hợp với kết quả kiểm định Chi-bình phương — cho thấy dân tộc và tình trạng hút thuốc không có mối liên hệ thống kê đáng kể.

4.4 Phân cụm bệnh nhân dựa trên các yếu tố sinh học và lối sống

1. library(ggplot2)
2. set.seed(123)
3. d$cluster <- kmeans(scale(d[, c("glucose_fasting", "hba1c", "bmi", "systolic_bp")]),
4.                     centers = 3, nstart = 25)$cluster |> as.factor()
5. ggplot(d, aes(bmi, glucose_fasting, color = cluster)) +
6.   geom_point(size = 2.5, alpha = 0.7) +
7.   labs(
8.     title = "Phân cụm bệnh nhân theo chỉ số BMI và Glucose lúc đói",
9.     subtitle = "Các nhóm cụm thể hiện đặc trưng sinh học tương đồng",
10.     x = "Chỉ số BMI (kg/m²)", y = "Đường huyết lúc đói (mg/dL)",
11.     color = "Nhóm cụm"
12.   ) +
13.   theme_minimal(base_size = 13) +
14.   theme(plot.title = element_text(hjust = 0.5, face = "bold"),
15.         plot.subtitle = element_text(hjust = 0.5)) +
16.   scale_color_brewer(palette = "Set1")

r 1. ggplot(d, aes(cluster, hba1c, fill = cluster)) + 2. geom_boxplot(alpha = 0.7) + 3. labs(title = "Phân bố HbA1c theo nhóm cụm", 4. x = "Nhóm cụm", y = "HbA1c (%)", fill = "Cụm") + 5. theme_classic(base_size = 13) + 6. scale_fill_brewer(palette = "Pastel1")

Ý nghĩa kỹ thuật:

scale() : Chuẩn hóa dữ liệu về cùng thang đo (mean = 0, sd = 1) trước khi phân cụm.

set.seed() : Cố định giá trị ngẫu nhiên để kết quả phân cụm có thể lặp lại.

kmeans() : Thực hiện thuật toán K-means để chia dữ liệu thành các nhóm (cụm).

as.factor() : Chuyển nhãn cụm thành biến phân loại để ggplot nhận dạng.

geom_point() : Vẽ biểu đồ phân tán (scatter plot) các điểm dữ liệu theo cụm.

geom_boxplot() : Vẽ hộp biểu đồ thể hiện phân bố của biến định lượng trong từng cụm.

labs() : Thêm tiêu đề, nhãn trục và chú giải cho biểu đồ.

theme_minimal() : Dùng giao diện sáng, đơn giản và hiện đại cho biểu đồ.

theme_classic() : Dùng giao diện truyền thống, có trục rõ ràng.

theme() : Tùy chỉnh chi tiết như căn giữa, kiểu chữ, tiêu đề phụ.

scale_color_brewer() : Tạo bảng màu đẹp cho các cụm trong biểu đồ điểm.

scale_fill_brewer() : Tạo bảng màu cho phần tô trong biểu đồ hộp.

Nhận xét biểu đồ phân cụm bệnh nhân theo chỉ số BMI và Glucose lúc đói:

Biểu đồ Scatter Plot cho thấy ba cụm bệnh nhân theo mối liên hệ giữa BMI và đường huyết lúc đói. Cụm 1 (đỏ) có BMI và Glucose thấp, nguy cơ chuyển hóa thấp; cụm 2 (xanh dương) ở mức trung bình, nguy cơ tiền tiểu đường; cụm 3 (xanh lá) có BMI và Glucose cao, nguy cơ tiểu đường typ 2 cao hơn.

Nhận xét biểu đồ phân bố HbA1c theo nhóm cụm

Biểu đồ Boxplot cho thấy sự khác biệt rõ về HbA1c giữa ba cụm. Cụm 1 có HbA1c thấp (~5.8%), kiểm soát đường huyết tốt; cụm 2 cao hơn nhẹ (~6.3%), tiệm cận tiền tiểu đường; cụm 3 cao nhất (>7%), phản ánh nhóm tiểu đường. Kết quả phân cụm K-means phù hợp với ý nghĩa lâm sàng khi HbA1c tăng dần theo mức độ nguy cơ.

4.5 Phân tích mối liên hệ giữa các yếu tố sinh học - lối sống và nhân khẩu học - hành vi

4.5.1 So sánh chỉ số BMI theo giới tính

1. library(ggplot2)
2. ggplot(d, aes(gender, bmi, fill = gender)) +
3.   geom_boxplot(alpha = 0.7, outlier.color = "red") +
4.   stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white") +
5.   labs(
6.     title = "So sánh chỉ số BMI theo giới tính",
7.     subtitle = "Phân bố BMI trong từng nhóm giới tính",
8.     x = "Giới tính", y = "Chỉ số BMI"
9.   ) +
10.   theme_minimal(base_size = 13) +
11.   scale_fill_brewer(palette = "Set2")

Ý nghĩa kỹ thuật:

ggplot(…): tạo biểu đồ với trục x = giới tính, y = BMI, tô màu theo giới tính.

geom_boxplot(…): vẽ biểu đồ hộp thể hiện phân bố BMI, điểm ngoại lai màu đỏ.

stat_summary(…): thêm điểm trung bình BMI cho từng nhóm.

labs(…): đặt tiêu đề, nhãn trục và chú thích.

theme_minimal(): giao diện tối giản, dễ đọc.

scale_fill_brewer(): dùng bảng màu “Set2” để phân biệt giới tính.

Nhận xét:

Biểu đồ cho thấy BMI giữa các giới tính khá tương đồng, trung bình khoảng 24–27 (cận thừa cân). Một số cá thể có BMI >35 thuộc nhóm béo phì, trong khi nhóm “Other” có độ biến thiên lớn hơn. Nhìn chung, khác biệt giữa các giới không đáng kể.

4.5.2 So sánh glucose_fasting theo giới tính

1. library(ggplot2)
2. ggplot(d, aes(gender, glucose_fasting, fill = gender)) +
3.   geom_boxplot(alpha = 0.7, outlier.color = "red") +
4.   labs(
5.     title = "So sánh đường huyết lúc đói giữa các giới tính",
6.     subtitle = "Đánh giá sự khác biệt chuyển hóa glucose theo giới tính sinh học",
7.     x = "Giới tính", y = "Đường huyết lúc đói (mg/dL)", fill = "Giới tính"
8.   ) +
9.   theme_minimal(base_size = 13) +
10.   scale_fill_brewer(palette = "Pastel1") +
11.   scale_x_discrete(limits = c("Female", "Male", "Other"))

Ý nghĩa kỹ thuật:

ggplot(d, aes(gender, glucose_fasting, fill = gender)): khởi tạo biểu đồ từ dữ liệu d, trục X là giới tính, trục Y là đường huyết lúc đói, tô màu theo giới tính.

geom_boxplot(): vẽ biểu đồ hộp thể hiện phân bố glucose theo giới tính.

labs(): đặt tiêu đề, nhãn trục và chú thích.

theme_minimal(base_size = 13): dùng giao diện tối giản, cỡ chữ 13.

scale_fill_brewer(palette = “Pastel1”): bảng màu dịu theo giới tính.

scale_x_discrete(limits = c(“Female”, “Male”, “Other”)): sắp xếp thứ tự trục X.

Nhận xét:

Biểu đồ hộp (Boxplot) thể hiện phân bố giá trị đường huyết lúc đói (glucose_fasting) theo ba nhóm giới tính: Nữ (Female), Nam (Male) và Khác (Other).

Phân bố dữ liệu: Cả ba nhóm đều có khoảng dao động (IQR) khá tương đương, cho thấy mức biến thiên đường huyết tương đối ổn định giữa các giới.

Các điểm ngoại lai (outliers) được biểu thị bằng dấu đỏ xuất hiện ở cả ba nhóm, điều này cho thấy một số cá thể có mức glucose bất thường cao hoặc thấp hơn nhiều so với trung bình, có thể là những trường hợp tiền tiểu đường hoặc kiểm soát đường huyết kém.

Trung vị (Median) của nhóm: Nam giới (Male) có xu hướng đường huyết lúc đói nhỉnh hơn một chút so với nữ và nhóm khác, mặc dù chênh lệch không đáng kể. Nữ (Female) và Other có phân bố khá tương đồng, với trung vị hơi thấp hơn.

4.5.3 So sánh mức cholesterol tổng theo tình trạng hút thuốc

1. ggplot(d, aes(smoking_status, cholesterol_total, fill = smoking_status)) +
2.   geom_boxplot(alpha = 0.7) +
3.   stat_summary(fun = mean, geom = "point", shape = 21, size = 3, fill = "white") +
4.   theme_minimal() +
5.   labs(
6.     title = "So sánh mức cholesterol tổng theo tình trạng hút thuốc",
7.     x = "Tình trạng hút thuốc", y = "Cholesterol tổng (mg/dL)"
8.   ) +
9.   scale_fill_brewer(palette = "Pastel1")

Ý nghĩa kỹ thuật

ggplot() : khởi tạo biểu đồ với dữ liệu và ánh xạ biến (trục x, y, màu tô).

aes() : xác định biến trục hoành (x), tung (y) và màu tô (fill).

geom_boxplot() : vẽ biểu đồ hộp (Boxplot) hiển thị phân bố và ngoại lệ.

alpha : điều chỉnh độ trong suốt của hộp (0 = trong suốt, 1 = đậm đặc).

stat_summary() : thêm giá trị tóm tắt (ở đây là trung bình).

fun = mean : chỉ định hàm tính trung bình cho mỗi nhóm.

shape, size, fill : chỉnh kiểu dáng, kích thước và màu điểm trung bình.

theme_minimal() : áp dụng giao diện sáng, gọn gàng, dễ đọc.

labs() : đặt tiêu đề, nhãn trục và chú thích cho biểu đồ.

theme() : tinh chỉnh chi tiết như góc chữ, căn giữa tiêu đề.

scale_fill_brewer() : tạo bảng màu dịu (Pastel1) giúp phân biệt nhóm rõ hơn.

Nhận xét:

Biểu đồ cho thấy mức cholesterol tổng giữa ba nhóm hút thuốc (Current, Former, Never) khá tương đồng, với giá trị trung bình và trung vị tập trung quanh 180–200 mg/dL. Nhóm “Former” có xu hướng cao hơn nhẹ, trong khi cả “Current” và “Former” đều xuất hiện nhiều ngoại lệ trên 300 mg/dL. Nhìn chung, hút thuốc không tạo khác biệt rõ rệt về cholesterol tổng, nhưng các giá trị cao ở hai nhóm này có thể gợi ý mối liên hệ tiềm ẩn với rối loạn lipid.

4.5.3.1 So sánh huyết áp tâm thu theo tình trạng hút thuốc

1. ggplot(d, aes(smoking_status, systolic_bp, fill = smoking_status)) +
2.   geom_boxplot(alpha = 0.7, outlier.color = "red") +
3.   labs(title = "So sánh huyết áp tâm thu theo tình trạng hút thuốc",
4.        x = "Tình trạng hút thuốc", y = "Huyết áp tâm thu (mmHg)") +
5.   theme_minimal(base_size = 13) +
6.   theme(plot.title = element_text(hjust = 0.5, face = "bold"),
7.         axis.text.x = element_text(angle = 15, hjust = 1)) +
8.   scale_fill_brewer(palette = "Set2")

Ý nghĩa kỹ thuật:

aes(smoking_status, systolic_bp, fill = smoking_status): ánh xạ trục X là nhóm hút thuốc, trục Y là huyết áp tâm thu, màu theo nhóm.

geom_boxplot(): tạo boxplot hiển thị phân bố huyết áp theo từng nhóm hút thuốc.

labs(): đặt tiêu đề, nhãn trục X–Y.

theme_minimal(): dùng giao diện tối giản, dễ đọc.

theme(): căn giữa tiêu đề, xoay nhãn trục X.

scale_fill_brewer(): chọn bảng màu hài hòa (“Set2”).

Nhận xét:

Biểu đồ Boxplot cho thấy nhóm hút thuốc hiện tại (Current) có huyết áp tâm thu trung vị cao hơn so với nhóm đã từng hút (Former) và chưa từng hút (Never). Phạm vi dao động của nhóm Current cũng rộng hơn, xuất hiện nhiều ngoại lệ cao, phản ánh nguy cơ tăng huyết áp rõ hơn ở người đang hút thuốc. Kết quả gợi ý hút thuốc lá có thể là yếu tố góp phần làm tăng huyết áp.

4.5.4 So sánh chỉ số HbA1c theo mức độ hoạt động thể lực

1. d$physical_activity_level <- cut(
2.   d$physical_activity_minutes_per_week,
3.   breaks = c(0, 150, 300, Inf),
4.   labels = c("Thấp", "Trung bình", "Cao"),
5.   right = FALSE
6. )
7. ggplot(d, aes(x = physical_activity_level, y = hba1c, fill = physical_activity_level)) +
8.   geom_boxplot(alpha = 0.7, outlier.color = "red") +
9.   theme_minimal() +
10.   labs(
11.     title = "HbA1c theo mức độ hoạt động thể lực",
12.     x = "Mức độ hoạt động",
13.     y = "HbA1c (%)"
14.   ) +
15.   scale_fill_brewer(palette = "Pastel1")

Ý nghĩa kỹ thuật:

cut() : chia biến liên tục thành 3 nhóm mức độ hoạt động (“Thấp”, “TB”, “Cao”).

ggplot() : khởi tạo biểu đồ với dữ liệu d.

aes() : xác định biến trục x, y và màu tô theo mức độ hoạt động.

geom_boxplot() : vẽ boxplot so sánh phân bố HbA1c giữa các nhóm.

alpha : chỉnh độ trong suốt của hộp.

outlier.color : tô màu điểm ngoại lệ đỏ.

theme_minimal() : áp dụng giao diện đơn giản, dễ đọc.

labs() : đặt tiêu đề, tên trục và chú thích.

scale_fill_brewer() : chọn bảng màu dịu (Pastel1).

Nhận xét:

Biểu đồ cho thấy mức độ hoạt động thể lực càng cao thì nồng độ HbA1c càng thấp. Nhóm hoạt động thấp có HbA1c cao và biến động lớn, trong khi nhóm trung bình và cao kiểm soát đường huyết tốt hơn. Điều này cho thấy tăng cường vận động giúp ổn định HbA1c và cải thiện sức khỏe chuyển hóa.

4.6 Phân tích thành phần chính (PCA) các yếu tố sinh học và lối sống đặc trưng theo giai đoạn bệnh tiểu đường

1. library(FactoMineR); library(factoextra); library(RColorBrewer)
2. bien_pca <- c("glucose_fasting", "hba1c", "bmi", 
3.               "systolic_bp", "cholesterol_total", 
4.               "physical_activity_minutes_per_week")
5. pca_kq <- PCA(d[bien_pca], scale.unit = TRUE, graph = FALSE)
6. so_nhom <- length(unique(na.omit(d$diabetes_stage)))
7. mau_nhom <- if (so_nhom <= 8) {
8.   brewer.pal(max(3, so_nhom), "Set2")[1:so_nhom]
9. } else {
10.   colorRampPalette(brewer.pal(8, "Set2"))(so_nhom)
11. }
12. fviz_pca_ind(pca_kq,
13.              geom.ind = "point",
14.              col.ind = as.factor(d$diabetes_stage),
15.              palette = mau_nhom,
16.              addEllipses = TRUE,
17.              legend.title = "Giai đoạn bệnh tiểu đường") +
18.   labs(title = "Phân tích thành phần chính (PCA)",
19.        subtitle = "Minh họa sự khác biệt giữa các giai đoạn tiểu đường theo các yếu tố sinh học") +
20.   theme_minimal(base_size = 14) +
21.   theme(plot.title = element_text(hjust = 0.5, face = "bold"),
22.         plot.subtitle = element_text(hjust = 0.5))

Ý nghĩa kỹ thuật:

PCA() Thực hiện phân tích thành phần chính, chuẩn hóa dữ liệu.

fviz_pca_ind() Vẽ biểu đồ các cá thể theo 2 thành phần chính đầu tiên.

addEllipses = TRUE Thêm đường bao (ellipse) thể hiện vùng của từng nhóm.

palette Tạo màu tự động cho từng giai đoạn bệnh.

labs() Đặt tiêu đề và phụ đề tiếng Việt.

theme_minimal() Làm giao diện sáng, gọn và dễ đọc.

Nhận xét:

Phân tích thành phần chính (PCA) cho thấy hai trục Dim1 và Dim2 thể hiện phần lớn phương sai của các yếu tố sinh học, giúp quan sát xu hướng phân tách giữa các nhóm bệnh tiểu đường. Nhóm Type 2 tách biệt rõ về phía có glucose và HbA1c cao, trong khi nhóm No Diabetes và Pre-Diabetes chồng lấn nhau, phản ánh sự chuyển tiếp liên tục giữa hai giai đoạn. Nhóm Gestational (nếu có) nằm riêng biệt, do khác biệt trong cơ chế chuyển hóa. Kết quả này khẳng định các biến sinh học có khả năng mô tả cấu trúc tiềm ẩn của bệnh và hỗ trợ phân tầng nguy cơ trong mô hình dự báo.

4.7 Phân tích tương ứng đa chiều (MCA) các yếu tố nhân khẩu học và hành vi liên quan đến giai đoạn bệnh tiểu đường

1. Sys.setlocale("LC_ALL", "vi_VN.UTF-8")
## [1] "LC_COLLATE=vi_VN.UTF-8;LC_CTYPE=vi_VN.UTF-8;LC_MONETARY=vi_VN.UTF-8;LC_NUMERIC=C;LC_TIME=vi_VN.UTF-8"
1. knitr::opts_chunk$set(echo = TRUE)
1. chooseCRANmirror(graphics = FALSE, ind = 22)
2. install.packages(c("FactoMineR", "factoextra", "RColorBrewer"), dependencies = TRUE)
1. library(FactoMineR); library(factoextra); library(RColorBrewer)
2. bien_dinh_tinh <- c("gender", "ethnicity", "smoking_status")
3. mca_kq <- MCA(d[bien_dinh_tinh], graph = FALSE)
4. group_levels <- unique(na.omit(as.character(d$diabetes_stage)))
5. n_groups <- length(group_levels)
6. if (n_groups == 0) stop("Không có nhóm trong d$diabetes_stage")
7. message("Số nhóm trong diabetes_stage: ", n_groups, " -> ", paste(group_levels, collapse = ", "))
8. palette_colors <- colorRampPalette(brewer.pal(8, "Set2"))(n_groups)
9. fviz_mca_ind(mca_kq,
10.              geom.ind = "point",
11.              col.ind = as.factor(d$diabetes_stage),
12.              palette = palette_colors,
13.              addEllipses = TRUE,
14.              legend.title = "Giai đoạn bệnh") +
15.   labs(title = "Phân tích tương quan đa chiều (MCA)",
16.        subtitle = "Quan hệ giữa các yếu tố định tính và giai đoạn tiểu đường",
17.        x = "Thành phần 1", y = "Thành phần 2") +
18.   theme_minimal(base_size = 14) +
19.   theme(plot.title = element_text(face = "bold", hjust = 0.5),
20.         plot.subtitle = element_text(hjust = 0.5))

Ý nghĩa kỹ thuật:

MCA() : thực hiện phân tích tương quan đa chiều giữa các biến định tính.

unique() / na.omit() : lấy danh sách nhóm hợp lệ (loại bỏ NA, trùng lặp).

colorRampPalette() + brewer.pal() : tạo bảng màu tự động cho các nhóm.

fviz_mca_ind() : vẽ biểu đồ MCA hiển thị mối quan hệ giữa các nhóm.

col.ind : tô màu điểm theo nhóm giai đoạn bệnh.

addEllipses = TRUE : thêm đường bao thể hiện vùng phân bố của nhóm.

labs() : đặt tiêu đề, phụ đề và nhãn trục cho biểu đồ.

theme_minimal() + theme() : làm biểu đồ sáng, rõ và căn giữa tiêu đề.

Nhận xét:

Phân tích tương quan đa chiều (MCA) cho thấy mối liên hệ giữa các yếu tố định tính như giới tính, chủng tộc và tình trạng hút thuốc với các giai đoạn bệnh tiểu đường. Biểu đồ thể hiện các nhóm giai đoạn bằng màu sắc và đường bao, song các vùng này chồng lấn khá nhiều, cho thấy các yếu tố định tính chưa đủ để phân tách rõ ràng giữa các giai đoạn bệnh. Do đó, cần kết hợp thêm các biến sinh học định lượng (như glucose, HbA1c, BMI, huyết áp…) để mô hình dự đoán đạt độ chính xác cao hơn.

PHẦN 2: BỘ DỮ LIỆU BÁO CÁO TÀI CHÍNH NGÂN HÀNG TECHCOMBANK

5 TỔNG QUAN VỀ BỘ DỮ LIỆU

Bộ dữ liệu được thu thập từ báo cáo tài chính hợp nhất của Ngân hàng TMCP Kỹ Thương Việt Nam (Techcombank) trong giai đoạn từ năm 2014 đến năm 2023, tổng cộng 10 năm dữ liệu liên tục. Bộ dữ liệu bao gồm các chỉ tiêu tài chính quan trọng được trình bày trong Bảng cân đối kế toán, Báo cáo kết quả kinh doanh và Báo cáo lưu chuyển tiền tệ của ngân hàng như: tổng tài sản, cho vay khách hàng, tiền gửi khách hàng, vốn chủ sở hữu, lợi nhuận sau thuế, dự phòng rủi ro tín dụng,… Mỗi cột dữ liệu thể hiện giá trị tài chính của từng chỉ tiêu theo từng năm, phản ánh tình hình hoạt động, quy mô và hiệu quả kinh doanh của Techcombank qua các giai đoạn.

Mục tiêu của việc sử dụng bộ dữ liệu này là phân tích xu hướng biến động tài chính của Techcombank trong 10 năm gần nhất, đánh giá sức khỏe tài chính, và ứng dụng các mô hình thống kê – dự báo để ước lượng và dự đoán giá trị các chỉ tiêu tài chính trong tương lai.

5.1 cài các gói cần thiết

1. packages <- c("dplyr", "tidyr", "ggplot2", "readr")
2. installed <- packages %in% rownames(installed.packages())
3. if (any(!installed)) {
4.   install.packages(packages[!installed])
5. }
6. lapply(packages, library, character.only = TRUE)
## [[1]]
##  [1] "RColorBrewer" "factoextra"   "FactoMineR"   "scales"       "reshape2"    
##  [6] "tidyr"        "stringr"      "psych"        "ggplot2"      "flextable"   
## [11] "kableExtra"   "knitr"        "dplyr"        "readxl"       "DT"          
## [16] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [21] "methods"      "base"        
## 
## [[2]]
##  [1] "RColorBrewer" "factoextra"   "FactoMineR"   "scales"       "reshape2"    
##  [6] "tidyr"        "stringr"      "psych"        "ggplot2"      "flextable"   
## [11] "kableExtra"   "knitr"        "dplyr"        "readxl"       "DT"          
## [16] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [21] "methods"      "base"        
## 
## [[3]]
##  [1] "RColorBrewer" "factoextra"   "FactoMineR"   "scales"       "reshape2"    
##  [6] "tidyr"        "stringr"      "psych"        "ggplot2"      "flextable"   
## [11] "kableExtra"   "knitr"        "dplyr"        "readxl"       "DT"          
## [16] "stats"        "graphics"     "grDevices"    "utils"        "datasets"    
## [21] "methods"      "base"        
## 
## [[4]]
##  [1] "readr"        "RColorBrewer" "factoextra"   "FactoMineR"   "scales"      
##  [6] "reshape2"     "tidyr"        "stringr"      "psych"        "ggplot2"     
## [11] "flextable"    "kableExtra"   "knitr"        "dplyr"        "readxl"      
## [16] "DT"           "stats"        "graphics"     "grDevices"    "utils"       
## [21] "datasets"     "methods"      "base"
1. cat("đã cài đặt và nạp đầy đủ các thư viện cần thiết!\n")
## đã cài đặt và nạp đầy đủ các thư viện cần thiết!
1. library(tidyverse)
2. library(dplyr)
3. library(ggplot2)
4. library(readr)  

5.2 đọc dữ liệu

1. library(readr)
2. d <- read_csv("D:/TCB_fixed_utf8_final.csv", locale = locale(encoding = "UTF-8"))
3. print(d)
## # A tibble: 26 × 27
##      Năm `Tên ngân hàng` `Loại hình ngân hàng` `Tình hình kinh tế`
##    <dbl> <chr>           <chr>                 <chr>              
##  1  2014 Techcombank     Ngân hàng TMCP        Trước covid        
##  2  2015 Techcombank     Ngân hàng TMCP        Trước covid        
##  3  2016 Techcombank     Ngân hàng TMCP        Trước covid        
##  4  2017 Techcombank     Ngân hàng TMCP        Trước covid        
##  5  2018 Techcombank     Ngân hàng TMCP        Trước covid        
##  6  2019 Techcombank     Ngân hàng TMCP        Trước covid        
##  7  2020 Techcombank     Ngân hàng TMCP        Sau covid          
##  8  2021 Techcombank     Ngân hàng TMCP        Sau covid          
##  9  2022 Techcombank     Ngân hàng TMCP        Sau covid          
## 10  2023 Techcombank     Ngân hàng TMCP        Sau covid          
## # ℹ 16 more rows
## # ℹ 23 more variables: `Tiền mặt vàng` <dbl>, `Tiền gửi tại NHNN` <dbl>,
## #   `Tiền gửi và cấp tín dụng cho các TCTD khác` <dbl>,
## #   `Tiền gửi tại các TCTD khác` <dbl>, `Cấp tín dụng cho các TCTD khác` <dbl>,
## #   `Chứng khoán kinh doanh` <dbl>, `Tài sản cố định` <dbl>,
## #   `Nguyên giá tài sản cố định` <dbl>, `Khấu hao tài sản cố định` <dbl>,
## #   `Các khoản phải thu` <dbl>, `Tổng tài sản` <dbl>, …

5.3 Định dạng lại dữ liệu

1. if(!require(tidyverse)) install.packages("tidyverse")
2. if(!require(DT)) install.packages("DT")
3. if(!require(htmltools)) install.packages("htmltools")
4. library(tidyverse)
5. library(DT)
6. library(htmltools)
7. cat("Đã nạp thư viện cần thiết!\n")
## Đã nạp thư viện cần thiết!
1. d <- read.csv("D:/TCB.csv", fileEncoding = "UTF-8-BOM", check.names = FALSE)
2. cat("Đã đọc dữ liệu TCB thành công!\n")
## Đã đọc dữ liệu TCB thành công!
1. cat("Số dòng:", nrow(d), "– Số cột:", ncol(d), "\n")
## Số dòng: 26 – Số cột: 27
1. cat("Thông tin cấu trúc dữ liệu:\n")
## Thông tin cấu trúc dữ liệu:
1. str(d)
## 'data.frame':    26 obs. of  27 variables:
##  $ Năm                                       : int  2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 ...
##  $ Tên ngân hàng                             : chr  "Techcombank" "Techcombank" "Techcombank" "Techcombank" ...
##  $ Loại hình ngân hàng                       : chr  "Ngân hàng TMCP" "Ngân hàng TMCP" "Ngân hàng TMCP" "Ngân hàng TMCP" ...
##  $ Tình hình kinh tế                         : chr  "Trước covid" "Trước covid" "Trước covid" "Trước covid" ...
##  $ Tiền mặt vàng                             : chr  "2,723,642" "2,754,299" "2,956,708" "2,344,362" ...
##  $ Tiền gửi tại NHNN                         : chr  "1,168,265" "1,602,619" "2,533,875" "4,317,924" ...
##  $ Tiền gửi và cấp tín dụng cho các TCTD khác: chr  "18,922,460" "14,762,009" "21,598,874" "30,117,314" ...
##  $ Tiền gửi tại các TCTD khác                : chr  "9,588,234" "7,487,472" "9,058,942" "16,204,561" ...
##  $ Cấp tín dụng cho các TCTD khác            : chr  "9,343,996" "7,274,537" "12,539,932" "13,912,753" ...
##  $ Chứng khoán kinh doanh                    : chr  "2,086,246" "3,072" "8,024,620" "6,758,094" ...
##  $ Tài sản cố định                           : chr  "1,036,505" "882,081" "1,582,722" "1,511,446" ...
##  $ Nguyên giá tài sản cố định                : chr  "1,361,399" "1,341,998" "1,518,287" "1,602,956" ...
##  $ Khấu hao tài sản cố định                  : chr  "-704,367" "-803,851" "-941,451" "-507,959" ...
##  $ Các khoản phải thu                        : chr  "10,366,601" "11,325,061" "6,829,557" "9,417,589" ...
##  $ Tổng tài sản                              : chr  "175,901,794" "192,009,075" "235,363,736" "269,392,380" ...
##  $ Tiền gửi và vay các TCTD khác             : chr  "19,471,408" "20,745,990" "25,473,509" "46,323,825" ...
##  $ Tiền gửi của khách hàng                   : chr  "131,689,810" "142,239,546" "173,448,929" "170,970,833" ...
##  $ Phát hành giấy tờ có giá                  : chr  "6,253,623" "8,133,896" "10,414,842" "17,639,970" ...
##  $ Tổng nợ phải trả                          : chr  "160,915,744" "175,481,015" "215,776,660" "242,461,635" ...
##  $ Tổng vốn chủ sở hữu                       : chr  "14,986,050" "16,528,060" "19,586,476" "26,930,745" ...
##  $ Tổng nợ phải trả và vốn chủ sở hữu        : chr  "175,901,794" "192,009,072" "235,363,136" "269,392,380" ...
##  $ Mua nợ                                    : chr  "9,817" "395,375" "19,466" "12,092" ...
##  $ Dự phòng rủi ro hoạt động mua nợ          : chr  "-491" "-4,446" "-973" "-176" ...
##  $ Chứng khoán đầu tư                        : chr  "54,978,730" "44,301,594" "45,674,924" "51,542,484" ...
##  $ Chứng khoán đầu tư sẵn sàng để bán        : chr  "49,704,301" "38,528,012" "38,575,369" "46,018,398" ...
##  $ Dự phòng rủi ro chứng khoán đầu tư        : chr  "-923,154" "-1,128,768" "-1,460,558" "-191,398" ...
##  $ Lợi nhuận chưa phân phối                  : chr  "1,556,411" "2,897,014" "5,489,215" "10,996,701" ...
1. d[, 2:ncol(d)] <- lapply(d[, 2:ncol(d)], function(x) {
2.   if(is.numeric(x)) format(x, big.mark = ",", scientific = FALSE) else x
3. })
4. options(scipen = 999999)
5. cat("Đã định dạng lại dữ liệu tài chính!\n")
## Đã định dạng lại dữ liệu tài chính!

5.4 Xem kích thước bộ dữ liệu

1. dim(d)
## [1] 26 27

Ý nghĩa kỹ thuật:

dim() trong R dùng để trả về kích thước (kích cỡ) của một đối tượng dữ liệu

5.5 Xem tên biến

1. names(d)
##  [1] "Năm"                                       
##  [2] "Tên ngân hàng"                             
##  [3] "Loại hình ngân hàng"                       
##  [4] "Tình hình kinh tế"                         
##  [5] "Tiền mặt vàng"                             
##  [6] "Tiền gửi tại NHNN"                         
##  [7] "Tiền gửi và cấp tín dụng cho các TCTD khác"
##  [8] "Tiền gửi tại các TCTD khác"                
##  [9] "Cấp tín dụng cho các TCTD khác"            
## [10] "Chứng khoán kinh doanh"                    
## [11] "Tài sản cố định"                           
## [12] "Nguyên giá tài sản cố định"                
## [13] "Khấu hao tài sản cố định"                  
## [14] "Các khoản phải thu"                        
## [15] "Tổng tài sản"                              
## [16] "Tiền gửi và vay các TCTD khác"             
## [17] "Tiền gửi của khách hàng"                   
## [18] "Phát hành giấy tờ có giá"                  
## [19] "Tổng nợ phải trả"                          
## [20] "Tổng vốn chủ sở hữu"                       
## [21] "Tổng nợ phải trả và vốn chủ sở hữu"        
## [22] "Mua nợ"                                    
## [23] "Dự phòng rủi ro hoạt động mua nợ"          
## [24] "Chứng khoán đầu tư"                        
## [25] "Chứng khoán đầu tư sẵn sàng để bán"        
## [26] "Dự phòng rủi ro chứng khoán đầu tư"        
## [27] "Lợi nhuận chưa phân phối"

Ý nghĩa kỹ thuật:

names(d): Liệt kê toàn bộ tên cột của bảng dữ liệu d.

5.6 Xem 6 dòng đầu của bộ dữ liệu

1. library(flextable); library(dplyr) 
2. d %>%
3.   head(6) %>%
4.   flextable() %>%
5.   autofit() %>%
6.   set_caption("6 dòng đầu tiên của bộ dữ liệu TCB") %>%
7.   theme_vanilla()
6 dòng đầu tiên của bộ dữ liệu TCB

Năm

Tên ngân hàng

Loại hình ngân hàng

Tình hình kinh tế

Tiền mặt vàng

Tiền gửi tại NHNN

Tiền gửi và cấp tín dụng cho các TCTD khác

Tiền gửi tại các TCTD khác

Cấp tín dụng cho các TCTD khác

Chứng khoán kinh doanh

Tài sản cố định

Nguyên giá tài sản cố định

Khấu hao tài sản cố định

Các khoản phải thu

Tổng tài sản

Tiền gửi và vay các TCTD khác

Tiền gửi của khách hàng

Phát hành giấy tờ có giá

Tổng nợ phải trả

Tổng vốn chủ sở hữu

Tổng nợ phải trả và vốn chủ sở hữu

Mua nợ

Dự phòng rủi ro hoạt động mua nợ

Chứng khoán đầu tư

Chứng khoán đầu tư sẵn sàng để bán

Dự phòng rủi ro chứng khoán đầu tư

Lợi nhuận chưa phân phối

2,014

Techcombank

Ngân hàng TMCP

Trước covid

2,723,642

1,168,265

18,922,460

9,588,234

9,343,996

2,086,246

1,036,505

1,361,399

-704,367

10,366,601

175,901,794

19,471,408

131,689,810

6,253,623

160,915,744

14,986,050

175,901,794

9,817

-491

54,978,730

49,704,301

-923,154

1,556,411

2,015

Techcombank

Ngân hàng TMCP

Trước covid

2,754,299

1,602,619

14,762,009

7,487,472

7,274,537

3,072

882,081

1,341,998

-803,851

11,325,061

192,009,075

20,745,990

142,239,546

8,133,896

175,481,015

16,528,060

192,009,072

395,375

-4,446

44,301,594

38,528,012

-1,128,768

2,897,014

2,016

Techcombank

Ngân hàng TMCP

Trước covid

2,956,708

2,533,875

21,598,874

9,058,942

12,539,932

8,024,620

1,582,722

1,518,287

-941,451

6,829,557

235,363,736

25,473,509

173,448,929

10,414,842

215,776,660

19,586,476

235,363,136

19,466

-973

45,674,924

38,575,369

-1,460,558

5,489,215

2,017

Techcombank

Ngân hàng TMCP

Trước covid

2,344,362

4,317,924

30,117,314

16,204,561

13,912,753

6,758,094

1,511,446

1,602,956

-507,959

9,417,589

269,392,380

46,323,825

170,970,833

17,639,970

242,461,635

26,930,745

269,392,380

12,092

-176

51,542,484

46,018,398

-191,398

10,996,701

2,018

Techcombank

Ngân hàng TMCP

Trước covid

2,606,467

10,555,483

35,559,363

24,169,512

11,389,851

7,572,229

1,718,596

1,835,272

609,457

11,322,556

320,988,941

36,425,560

210,414,532

13,177,959

269,206,236

51,782,705

320,988,941

1,682

-1,682

86,512,348

66,625,261

349,113

12,403,003

2,019

Techcombank

Ngân hàng TMCP

Trước covid

4,820,627

3,192,256

47,990,224

38,596,420

9,393,804

10,041,556

3,207,777

1,761,468

-967,984

12,954,103

383,699,461

61,266,635

231,296,761

17,460,634

321,626,694

62,072,767

383,699,461

1,682

-1,682

66,054,597

66,158,709

-306,118

21,131,391

Ý nghĩa kỹ thuật:

head(df) → hiển thị 6 dòng đầu của dataframe df.

xem nhanh 6 dòng đầu tiên của dữ liệu

5.7 Xem cấu trúc tổng quát của dữ liệu

1. str(d)
## 'data.frame':    26 obs. of  27 variables:
##  $ Năm                                       : int  2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 ...
##  $ Tên ngân hàng                             : chr  "Techcombank" "Techcombank" "Techcombank" "Techcombank" ...
##  $ Loại hình ngân hàng                       : chr  "Ngân hàng TMCP" "Ngân hàng TMCP" "Ngân hàng TMCP" "Ngân hàng TMCP" ...
##  $ Tình hình kinh tế                         : chr  "Trước covid" "Trước covid" "Trước covid" "Trước covid" ...
##  $ Tiền mặt vàng                             : chr  "2,723,642" "2,754,299" "2,956,708" "2,344,362" ...
##  $ Tiền gửi tại NHNN                         : chr  "1,168,265" "1,602,619" "2,533,875" "4,317,924" ...
##  $ Tiền gửi và cấp tín dụng cho các TCTD khác: chr  "18,922,460" "14,762,009" "21,598,874" "30,117,314" ...
##  $ Tiền gửi tại các TCTD khác                : chr  "9,588,234" "7,487,472" "9,058,942" "16,204,561" ...
##  $ Cấp tín dụng cho các TCTD khác            : chr  "9,343,996" "7,274,537" "12,539,932" "13,912,753" ...
##  $ Chứng khoán kinh doanh                    : chr  "2,086,246" "3,072" "8,024,620" "6,758,094" ...
##  $ Tài sản cố định                           : chr  "1,036,505" "882,081" "1,582,722" "1,511,446" ...
##  $ Nguyên giá tài sản cố định                : chr  "1,361,399" "1,341,998" "1,518,287" "1,602,956" ...
##  $ Khấu hao tài sản cố định                  : chr  "-704,367" "-803,851" "-941,451" "-507,959" ...
##  $ Các khoản phải thu                        : chr  "10,366,601" "11,325,061" "6,829,557" "9,417,589" ...
##  $ Tổng tài sản                              : chr  "175,901,794" "192,009,075" "235,363,736" "269,392,380" ...
##  $ Tiền gửi và vay các TCTD khác             : chr  "19,471,408" "20,745,990" "25,473,509" "46,323,825" ...
##  $ Tiền gửi của khách hàng                   : chr  "131,689,810" "142,239,546" "173,448,929" "170,970,833" ...
##  $ Phát hành giấy tờ có giá                  : chr  "6,253,623" "8,133,896" "10,414,842" "17,639,970" ...
##  $ Tổng nợ phải trả                          : chr  "160,915,744" "175,481,015" "215,776,660" "242,461,635" ...
##  $ Tổng vốn chủ sở hữu                       : chr  "14,986,050" "16,528,060" "19,586,476" "26,930,745" ...
##  $ Tổng nợ phải trả và vốn chủ sở hữu        : chr  "175,901,794" "192,009,072" "235,363,136" "269,392,380" ...
##  $ Mua nợ                                    : chr  "9,817" "395,375" "19,466" "12,092" ...
##  $ Dự phòng rủi ro hoạt động mua nợ          : chr  "-491" "-4,446" "-973" "-176" ...
##  $ Chứng khoán đầu tư                        : chr  "54,978,730" "44,301,594" "45,674,924" "51,542,484" ...
##  $ Chứng khoán đầu tư sẵn sàng để bán        : chr  "49,704,301" "38,528,012" "38,575,369" "46,018,398" ...
##  $ Dự phòng rủi ro chứng khoán đầu tư        : chr  "-923,154" "-1,128,768" "-1,460,558" "-191,398" ...
##  $ Lợi nhuận chưa phân phối                  : chr  "1,556,411" "2,897,014" "5,489,215" "10,996,701" ...

Ý nghĩa kỹ thuật:

str() cho kết quả trả về cấu trúc tổng quát của bộ dữ liệu, bao gồm số quan sát, số biến, tên biến và kiểu dữ liệu của từng biến.

Biến “Năm” được lưu dưới dạng số thực (num), trong khi các biến còn lại được hiển thị ở dạng chuỗi ký tự (chr) do đã được định dạng lại bằng hàm format() để thêm dấu phẩy phân tách hàng nghìn.

5.8 Tóm tắt sơ bộ dữ liệu

1. summary(d)
##       Năm       Tên ngân hàng      Loại hình ngân hàng Tình hình kinh tế 
##  Min.   :2014   Length:26          Length:26           Length:26         
##  1st Qu.:2016   Class :character   Class :character    Class :character  
##  Median :2018   Mode  :character   Mode  :character    Mode  :character  
##  Mean   :2018                                                            
##  3rd Qu.:2021                                                            
##  Max.   :2023                                                            
##  NA's   :16                                                              
##  Tiền mặt vàng      Tiền gửi tại NHNN 
##  Length:26          Length:26         
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
##                                       
##  Tiền gửi và cấp tín dụng cho các TCTD khác Tiền gửi tại các TCTD khác
##  Length:26                                  Length:26                 
##  Class :character                           Class :character          
##  Mode  :character                           Mode  :character          
##                                                                       
##                                                                       
##                                                                       
##                                                                       
##  Cấp tín dụng cho các TCTD khác Chứng khoán kinh doanh Tài sản cố định   
##  Length:26                      Length:26              Length:26         
##  Class :character               Class :character       Class :character  
##  Mode  :character               Mode  :character       Mode  :character  
##                                                                          
##                                                                          
##                                                                          
##                                                                          
##  Nguyên giá tài sản cố định Khấu hao tài sản cố định Các khoản phải thu
##  Length:26                  Length:26                Length:26         
##  Class :character           Class :character         Class :character  
##  Mode  :character           Mode  :character         Mode  :character  
##                                                                        
##                                                                        
##                                                                        
##                                                                        
##  Tổng tài sản       Tiền gửi và vay các TCTD khác Tiền gửi của khách hàng
##  Length:26          Length:26                     Length:26              
##  Class :character   Class :character              Class :character       
##  Mode  :character   Mode  :character              Mode  :character       
##                                                                          
##                                                                          
##                                                                          
##                                                                          
##  Phát hành giấy tờ có giá Tổng nợ phải trả   Tổng vốn chủ sở hữu
##  Length:26                Length:26          Length:26          
##  Class :character         Class :character   Class :character   
##  Mode  :character         Mode  :character   Mode  :character   
##                                                                 
##                                                                 
##                                                                 
##                                                                 
##  Tổng nợ phải trả và vốn chủ sở hữu    Mua nợ         
##  Length:26                          Length:26         
##  Class :character                   Class :character  
##  Mode  :character                   Mode  :character  
##                                                       
##                                                       
##                                                       
##                                                       
##  Dự phòng rủi ro hoạt động mua nợ Chứng khoán đầu tư
##  Length:26                        Length:26         
##  Class :character                 Class :character  
##  Mode  :character                 Mode  :character  
##                                                     
##                                                     
##                                                     
##                                                     
##  Chứng khoán đầu tư sẵn sàng để bán Dự phòng rủi ro chứng khoán đầu tư
##  Length:26                          Length:26                         
##  Class :character                   Class :character                  
##  Mode  :character                   Mode  :character                  
##                                                                       
##                                                                       
##                                                                       
##                                                                       
##  Lợi nhuận chưa phân phối
##  Length:26               
##  Class :character        
##  Mode  :character        
##                          
##                          
##                          
## 

Ý nghĩa kỹ thuật:

summary() cho biết thống kê tổng quát của từng biến trong bộ dữ liệu, bao gồm giá trị nhỏ nhất, lớn nhất, trung bình và trung vị.

5.9 Xem kích thước cụ thể từng cột

1. sapply(d, length)
##                                        Năm 
##                                         26 
##                              Tên ngân hàng 
##                                         26 
##                        Loại hình ngân hàng 
##                                         26 
##                          Tình hình kinh tế 
##                                         26 
##                              Tiền mặt vàng 
##                                         26 
##                          Tiền gửi tại NHNN 
##                                         26 
## Tiền gửi và cấp tín dụng cho các TCTD khác 
##                                         26 
##                 Tiền gửi tại các TCTD khác 
##                                         26 
##             Cấp tín dụng cho các TCTD khác 
##                                         26 
##                     Chứng khoán kinh doanh 
##                                         26 
##                            Tài sản cố định 
##                                         26 
##                 Nguyên giá tài sản cố định 
##                                         26 
##                   Khấu hao tài sản cố định 
##                                         26 
##                         Các khoản phải thu 
##                                         26 
##                               Tổng tài sản 
##                                         26 
##              Tiền gửi và vay các TCTD khác 
##                                         26 
##                    Tiền gửi của khách hàng 
##                                         26 
##                   Phát hành giấy tờ có giá 
##                                         26 
##                           Tổng nợ phải trả 
##                                         26 
##                        Tổng vốn chủ sở hữu 
##                                         26 
##         Tổng nợ phải trả và vốn chủ sở hữu 
##                                         26 
##                                     Mua nợ 
##                                         26 
##           Dự phòng rủi ro hoạt động mua nợ 
##                                         26 
##                         Chứng khoán đầu tư 
##                                         26 
##         Chứng khoán đầu tư sẵn sàng để bán 
##                                         26 
##         Dự phòng rủi ro chứng khoán đầu tư 
##                                         26 
##                   Lợi nhuận chưa phân phối 
##                                         26

Ý Nghĩa kỹ thuật:

sapply() → áp dụng một hàm cho từng cột trong dữ liệu và trả về kết quả dạng vector. length: đếm số phần tử trong mỗi cột.

Lệnh này cho biết số lượng quan sát (số dòng) của từng biến trong bảng dữ liệu d.

6 CHƯƠNG 2 XỬ LÝ DỮ LIỆU THÔ VÀ MÃ HÓA DỮ LIỆU

6.1 Kiểm tra giá trị thiếu((Missing Values – NA)

1. library(dplyr); library(flextable)
2. missing_tbl <- data.frame(
3.   "Tên biến" = names(d),
4.   "Số lượng giá trị thiếu (NA)" = colSums(is.na(d))
5. )
6. missing_tbl %>%
7.   flextable() %>%
8.   set_caption("Bảng: Kiểm tra giá trị thiếu trong bộ dữ liệu TCB") %>%
9.   autofit() %>%                           
10.   border_remove() %>%                     
11.   border_outer(part = "all") %>%          
12.   border_inner(part = "all") %>%          
13.   fontsize(size = 11, part = "all") %>%   
14.   align(align = "left", part = "all")     
Bảng: Kiểm tra giá trị thiếu trong bộ dữ liệu TCB

Tên.biến

Số.lượng.giá.trị.thiếu..NA.

Năm

16

Tên ngân hàng

0

Loại hình ngân hàng

0

Tình hình kinh tế

0

Tiền mặt vàng

0

Tiền gửi tại NHNN

0

Tiền gửi và cấp tín dụng cho các TCTD khác

0

Tiền gửi tại các TCTD khác

0

Cấp tín dụng cho các TCTD khác

0

Chứng khoán kinh doanh

0

Tài sản cố định

0

Nguyên giá tài sản cố định

0

Khấu hao tài sản cố định

0

Các khoản phải thu

0

Tổng tài sản

0

Tiền gửi và vay các TCTD khác

0

Tiền gửi của khách hàng

0

Phát hành giấy tờ có giá

0

Tổng nợ phải trả

0

Tổng vốn chủ sở hữu

0

Tổng nợ phải trả và vốn chủ sở hữu

0

Mua nợ

0

Dự phòng rủi ro hoạt động mua nợ

0

Chứng khoán đầu tư

0

Chứng khoán đầu tư sẵn sàng để bán

0

Dự phòng rủi ro chứng khoán đầu tư

0

Lợi nhuận chưa phân phối

0

Ý nghĩa kỹ thuật:

colSums(is.na(d)) cho biết số lượng giá trị bị thiếu (NA) trong từng biến.

Nhận xét:

Kết quả cho thấy tất cả các cột đều có giá trị bằng 0, nghĩa là dữ liệu của Techcombank giai đoạn 2014–2023 không có giá trị bị thiếu.

6.2 Xác định và loại bỏ dữ liệu trùng lặp

1. dup_vars <- names(d)[duplicated(names(d))]
2. if (length(dup_vars) > 0) {
3.   cat("Các biến bị trùng lặp:", toString(dup_vars))
4. } else {
5.   cat("Không có biến trùng lặp trong bộ dữ liệu.")
6. }              
## Không có biến trùng lặp trong bộ dữ liệu.

Ý nghĩa kỹ thuật:

sum(duplicated(d)): Kiểm tra xem trong dữ liệu d có bao nhiêu dòng bị trùng lặp hoàn toàn

d[duplicated(d), ],: Các dòng trùng lặp (nếu có) sẽ được loại bỏ, chỉ giữ lại một bản ghi duy nhất cho mỗi quan sát.

d_clean <- d %>% distinct(): Tạo một bản sao dữ liệu mới (d_clean) chỉ giữ lại các dòng duy nhất, loại bỏ hoàn toàn các bản ghi trùng.

sum(duplicated(d_clean)): Kiểm tra lại xem sau khi làm sạch (d_clean) còn trùng lặp nào không.

nrow(d_clean): Đếm số dòng (quan sát) còn lại trong bảng dữ liệu sau khi loại trùng.

Nhận xét:

Kết quả kiểm tra cho thấy tập dữ liệu d hoàn toàn sạch, không có dòng bị trùng.

6.3 Trích xuất và phân loại dữ liệu cần phân tích

1. library(dplyr)
2. tcb_10bien <- d %>%
3.   select(
4.     `Tiền gửi và cấp tín dụng cho các TCTD khác`,
5.     `Cấp tín dụng cho các TCTD khác`,
6.     `Chứng khoán kinh doanh`,
7.     `Chứng khoán đầu tư`,
8.     `Nguyên giá tài sản cố định`,
9.     `Khấu hao tài sản cố định`,
10.     `Tiền gửi của khách hàng`,
11.     `Tổng nợ phải trả`,
12.     `Mua nợ`,
13.     `Lợi nhuận chưa phân phối`
14.   )
15. nhom1_quymo_hoatdong <- c(
16.   "Tiền gửi của khách hàng",
17.   "Tổng nợ phải trả",
18.   "Tiền gửi và cấp tín dụng cho các TCTD khác",
19.   "Cấp tín dụng cho các TCTD khác",
20.   "Lợi nhuận chưa phân phối"
21. )
22. nhom2_taisan_thanhkhoan <- c(
23.   "Chứng khoán kinh doanh",
24.   "Chứng khoán đầu tư",
25.   "Nguyên giá tài sản cố định",
26.   "Khấu hao tài sản cố định",
27.   "Mua nợ"
28. )

Ý nghĩa kỹ thuật:

select() → trích xuất 10 cột quan trọng từ bảng d

Hai vector nhom1_quymo_hoatdong và nhom2_taisan_thanhkhoan: Phân loại biến

Nhận xét:

Đoạn mã trên giúp trích xuất 10 biến tài chính quan trọng và phân loại thành 2 nhóm từ bộ dữ liệu gốc của Techcombank.

6.4 Chuyển các biến định lượng sang numeric

1. install.packages("dplyr")   
2. library(dplyr)
3. tcb_10bien <- tcb_10bien %>%
4.   mutate(across(everything(), ~ as.numeric(gsub(",", "", .))))
5. sapply(tcb_10bien, class)
## Tiền gửi và cấp tín dụng cho các TCTD khác 
##                                  "numeric" 
##             Cấp tín dụng cho các TCTD khác 
##                                  "numeric" 
##                     Chứng khoán kinh doanh 
##                                  "numeric" 
##                         Chứng khoán đầu tư 
##                                  "numeric" 
##                 Nguyên giá tài sản cố định 
##                                  "numeric" 
##                   Khấu hao tài sản cố định 
##                                  "numeric" 
##                    Tiền gửi của khách hàng 
##                                  "numeric" 
##                           Tổng nợ phải trả 
##                                  "numeric" 
##                                     Mua nợ 
##                                  "numeric" 
##                   Lợi nhuận chưa phân phối 
##                                  "numeric"
1. summary(tcb_10bien)
##  Tiền gửi và cấp tín dụng cho các TCTD khác Cấp tín dụng cho các TCTD khác
##  Min.   : 14762009                          Min.   : 7274537              
##  1st Qu.: 23447894                          1st Qu.: 9356448              
##  Median : 32838338                          Median :11964892              
##  Mean   : 45540653                          Mean   :13989796              
##  3rd Qu.: 64884000                          3rd Qu.:13696992              
##  Max.   :104072320                          Max.   :31064531              
##  NA's   :16                                 NA's   :16                    
##  Chứng khoán kinh doanh Chứng khoán đầu tư  Nguyên giá tài sản cố định
##  Min.   :    3072       Min.   : 44301594   Min.   :1341998           
##  1st Qu.: 2672879       1st Qu.: 52401546   1st Qu.:1539454           
##  Median : 5914453       Median : 75250919   Median :1798370           
##  Mean   : 5329802       Mean   : 73974387   Mean   :2731041           
##  3rd Qu.: 7911522       3rd Qu.: 94817653   3rd Qu.:4222156           
##  Max.   :10041556       Max.   :104993945   Max.   :5492246           
##  NA's   :16             NA's   :16          NA's   :16                
##  Khấu hao tài sản cố định Tiền gửi của khách hàng Tổng nợ phải trả   
##  Min.   :-1964680         Min.   :131689810       Min.   :160915744  
##  1st Qu.:-1138516         1st Qu.:171590357       1st Qu.:222447904  
##  Median : -943429         Median :220855646       Median :295416465  
##  Mean   : -888114         Mean   :246533615       Mean   :352961713  
##  3rd Qu.: -729238         3rd Qu.:305429056       3rd Qu.:448012645  
##  Max.   :  609457         Max.   :454660779       Max.   :717865947  
##  NA's   :16               NA's   :16              NA's   :16         
##      Mua nợ       Lợi nhuận chưa phân phối
##  Min.   :  1682   Min.   : 1556411        
##  1st Qu.:  3716   1st Qu.: 6866086        
##  Median : 15779   Median :16767197        
##  Mean   : 77246   Mean   :24723843        
##  3rd Qu.:103750   3rd Qu.:43543744        
##  Max.   :395375   Max.   :64482685        
##  NA's   :16       NA's   :16

Ý nghĩa kỹ thuật:

tcb_10bien <- tcb_10bien %>%: toán tử pipe (%>%), truyền dữ liệu tcb_10bien qua bước kế tiếp.

mutate(across(…)): áp dụng cùng một phép biến đổi cho tất cả các cột trong bảng.

gsub(“,”, ““, .): loại bỏ dấu phẩy (,) trong các giá trị chuỗi — vì dấu phẩy khiến R hiểu dữ liệu là ký tự.

as.numeric(): chuyển các chuỗi ký tự đã làm sạch thành dạng số thực (numeric) để có thể tính toán, thống kê hoặc trực quan hóa.

sapply(tcb_10bien, class), summary(tcb_10bien). Kiểm tra kiểu dữ liệu của từng cột (đảm bảo đã là numeric) và tóm tắt thống kê (min, max, mean, median, v.v.) để xác nhận quá trình chuyển đổi thành công.

Nhận xét:

Bước này giúp chuẩn hóa dữ liệu định lượng bằng cách chuyển các giá trị chứa dấu phẩy từ Excel sang dạng numeric, tránh việc R hiểu nhầm là ký tự. Việc này đảm bảo tính chính xác và toàn vẹn dữ liệu.

6.5 Kiểm tra phân bố dữ liệu

1. summary(tcb_10bien)
##  Tiền gửi và cấp tín dụng cho các TCTD khác Cấp tín dụng cho các TCTD khác
##  Min.   : 14762009                          Min.   : 7274537              
##  1st Qu.: 23447894                          1st Qu.: 9356448              
##  Median : 32838338                          Median :11964892              
##  Mean   : 45540653                          Mean   :13989796              
##  3rd Qu.: 64884000                          3rd Qu.:13696992              
##  Max.   :104072320                          Max.   :31064531              
##  NA's   :16                                 NA's   :16                    
##  Chứng khoán kinh doanh Chứng khoán đầu tư  Nguyên giá tài sản cố định
##  Min.   :    3072       Min.   : 44301594   Min.   :1341998           
##  1st Qu.: 2672879       1st Qu.: 52401546   1st Qu.:1539454           
##  Median : 5914453       Median : 75250919   Median :1798370           
##  Mean   : 5329802       Mean   : 73974387   Mean   :2731041           
##  3rd Qu.: 7911522       3rd Qu.: 94817653   3rd Qu.:4222156           
##  Max.   :10041556       Max.   :104993945   Max.   :5492246           
##  NA's   :16             NA's   :16          NA's   :16                
##  Khấu hao tài sản cố định Tiền gửi của khách hàng Tổng nợ phải trả   
##  Min.   :-1964680         Min.   :131689810       Min.   :160915744  
##  1st Qu.:-1138516         1st Qu.:171590357       1st Qu.:222447904  
##  Median : -943429         Median :220855646       Median :295416465  
##  Mean   : -888114         Mean   :246533615       Mean   :352961713  
##  3rd Qu.: -729238         3rd Qu.:305429056       3rd Qu.:448012645  
##  Max.   :  609457         Max.   :454660779       Max.   :717865947  
##  NA's   :16               NA's   :16              NA's   :16         
##      Mua nợ       Lợi nhuận chưa phân phối
##  Min.   :  1682   Min.   : 1556411        
##  1st Qu.:  3716   1st Qu.: 6866086        
##  Median : 15779   Median :16767197        
##  Mean   : 77246   Mean   :24723843        
##  3rd Qu.:103750   3rd Qu.:43543744        
##  Max.   :395375   Max.   :64482685        
##  NA's   :16       NA's   :16

Ý nghĩa kỹ thuật:

summary(tcb_10bien): Tóm tắt thống kê mô tả cho từng biến trong bộ dữ liệu tcb_10bien.

Nhận xét:

Các biến tài chính của Techcombank đều có giá trị tăng mạnh qua thời gian, thể hiện qua khoảng dao động (Max – Min) lớn.

Riêng Tổng tài sản có giá trị trung bình (Mean = 431,4 tỷ) cao hơn trung vị (Median = 352,4 tỷ), cho thấy phân bố lệch phải, tức có một số năm tài sản tăng đột biến.

Tương tự, Tiền gửi tại NHNN và Tiền mặt vàng cũng có xu hướng tăng, thể hiện chính sách tăng dự trữ thanh khoản của ngân hàng.

Các chỉ tiêu Chứng khoán đầu tư và Cấp tín dụng cho TCTD khác có trung bình cao, phản ánh hoạt động đầu tư và tín dụng mở rộng ổn định.

Biến Dự phòng rủi ro hoạt động mua nợ mang giá trị âm → đây là khoản chi phí dự phòng, thể hiện sự thận trọng trong kiểm soát rủi ro.

6.6 Lọc dữ liệu theo điều kiện

6.6.1 Lọc dữ liệu theo điều kiện hợp lý

1. if (!requireNamespace("dplyr", quietly = TRUE)) install.packages("dplyr")
2. if (!requireNamespace("tidyr", quietly = TRUE)) install.packages("tidyr")
3. library(dplyr)
4. library(tidyr)
5. tcb_loc <- tcb_10bien %>%
6.   filter(
7.     `Tiền gửi và cấp tín dụng cho các TCTD khác` >= 0,
8.     `Cấp tín dụng cho các TCTD khác` >= 0,
9.     `Chứng khoán kinh doanh` >= 0,
10.     `Chứng khoán đầu tư` >= 0,
11.     `Nguyên giá tài sản cố định` >= 0,
12.     `Tiền gửi của khách hàng` >= 0,
13.     `Tổng nợ phải trả` >= 0
14.   ) %>%
15.   drop_na()
16. summary(tcb_loc)
##  Tiền gửi và cấp tín dụng cho các TCTD khác Cấp tín dụng cho các TCTD khác
##  Min.   : 14762009                          Min.   : 7274537              
##  1st Qu.: 23447894                          1st Qu.: 9356448              
##  Median : 32838338                          Median :11964892              
##  Mean   : 45540653                          Mean   :13989796              
##  3rd Qu.: 64884000                          3rd Qu.:13696992              
##  Max.   :104072320                          Max.   :31064531              
##  Chứng khoán kinh doanh Chứng khoán đầu tư  Nguyên giá tài sản cố định
##  Min.   :    3072       Min.   : 44301594   Min.   :1341998           
##  1st Qu.: 2672879       1st Qu.: 52401546   1st Qu.:1539454           
##  Median : 5914453       Median : 75250919   Median :1798370           
##  Mean   : 5329802       Mean   : 73974387   Mean   :2731041           
##  3rd Qu.: 7911522       3rd Qu.: 94817653   3rd Qu.:4222156           
##  Max.   :10041556       Max.   :104993945   Max.   :5492246           
##  Khấu hao tài sản cố định Tiền gửi của khách hàng Tổng nợ phải trả   
##  Min.   :-1964680         Min.   :131689810       Min.   :160915744  
##  1st Qu.:-1138516         1st Qu.:171590357       1st Qu.:222447904  
##  Median : -943429         Median :220855646       Median :295416465  
##  Mean   : -888114         Mean   :246533615       Mean   :352961713  
##  3rd Qu.: -729238         3rd Qu.:305429056       3rd Qu.:448012645  
##  Max.   :  609457         Max.   :454660779       Max.   :717865947  
##      Mua nợ       Lợi nhuận chưa phân phối
##  Min.   :  1682   Min.   : 1556411        
##  1st Qu.:  3716   1st Qu.: 6866086        
##  Median : 15779   Median :16767197        
##  Mean   : 77246   Mean   :24723843        
##  3rd Qu.:103750   3rd Qu.:43543744        
##  Max.   :395375   Max.   :64482685

Ý nghĩa kỹ thuật:

tcb_loc <- tcb_10bien %>% : %>% Toán tử pipe (đọc là “chuyển sang bước tiếp theo”), giúp viết code gọn hơn.

filter(…): Lọc các hàng (quan sát) trong tcb_10bien chỉ giữ lại những hàng có giá trị ≥ 0 ở các biến nêu ra.

drop_na() :Loại bỏ các hàng còn thiếu dữ liệu (NA) sau khi lọc.

summary(tcb_loc): Xuất ra thống kê mô tả cho từng biến trong bảng sau khi lọc: gồm Min, 1st Qu, Median, Mean, 3rd Qu, Max.

nrow(tcb_loc): Trả về số lượng hàng (quan sát) còn lại sau khi lọc.

Nhận xét:

Sau khi lọc dữ liệu, tất cả các biến đều có giá trị hợp lệ (≥ 0) và không còn giá trị thiếu (NA).

6.6.2 Điều kiện AND(&)

1. tcb_loc_and <- tcb_10bien %>%
2.   filter(
3.     `Tiền gửi của khách hàng` > 2000000 &      # > 2.000.000 tỷ đồng
4.     `Nguyên giá tài sản cố định` > 300000 &    # > 300.000 tỷ đồng
5.     `Chứng khoán đầu tư` > 800000              # > 800.000 tỷ đồng
6.   )

Ý nghĩa kỹ thuật:

filter(…): lọc các biến

Đặt điều kiện cho các biến:

tien_gui_cua_khach_hang > 2000000,

nguyen_gia_tai_san_co_dinh > 300000,

chung_khoan_dau_tu > 800000.

Kết quả được lưu vào tcb_loc_and, và nrow(tcb_loc_and) cho biết số dòng dữ liệu còn lại sau khi lọc.

Nhận xét:

Bảng kết quả cho thấy chỉ các năm 2021–2023 đáp ứng đồng thời cả ba điều kiện, phản ánh giai đoạn tăng trưởng mạnh và ổn định nhất của Techcombank. Trong thời kỳ này, quy mô tín dụng, tiền gửi và đầu tư đều đạt mức cao, thể hiện năng lực tài chính vững vàng và chiến lược phát triển hiệu quả.

6.6.3 Điều kiện OR(|)

1. tcb_loc <- tcb_10bien %>%
2.   filter(
3.     `Tiền gửi của khách hàng` > 2000000 |      # hoặc > 2.000.000 tỷ đồng
4.     `Nguyên giá tài sản cố định` > 20000 |     # hoặc > 20.000 tỷ đồng
5.     `Chứng khoán đầu tư` > 800000              # hoặc > 800.000 tỷ đồng
6.   )

Ý nghĩa kỹ thuật:

filter(…): lọc các biến

Đặt điều kiện cho các biến:

tien_gui_cua_khach_hang > 2000000,

nguyen_gia_tai_san_co_dinh > 20000,

chung_khoan_dau_tu > 800000.

Kết quả được lưu vào tcb_loc_and, và nrow(tcb_loc_and) cho biết số dòng dữ liệu còn lại sau khi lọc.

Nhận xét:

Bảng kết quả cho thấy các năm 2018–2023 đều thỏa mãn ít nhất một trong ba điều kiện lọc: tiền gửi khách hàng > 0.0002, nguyên giá tài sản cố định > 0.000002, hoặc chứng khoán đầu tư > 0.00008. Điều này phản ánh quy mô hoạt động của TCB tăng mạnh trong giai đoạn này, đặc biệt ở các khoản tiền gửi và đầu tư, cho thấy xu hướng mở rộng nguồn vốn và đa dạng hóa danh mục tài chính.

6.6.4 Điều kiện AND và OR

1. tcb_loc_ket_hop <- tcb_10bien %>%
2.   filter(
3.     (`Tiền gửi của khách hàng` > 2000000 & `Nguyên giá tài sản cố định` > 300000) |
4.       (`Chứng khoán đầu tư` > 800000)
5.   )

Ý nghĩa kỹ thuật:

filter(…): lọc các biến

Đặt điều kiện cho các biến:

tien_gui_cua_khach_hang > 2000000,

nguyen_gia_tai_san_co_dinh > 300000,

chung_khoan_dau_tu > 800000.

Kết quả được lưu vào tcb_loc_and, và nrow(tcb_loc_and) cho biết số dòng dữ liệu còn lại sau khi lọc.

Nhận xét:

Bảng kết quả cho thấy các năm 2018 - 2023 thỏa mãn điều kiện kết hợp (tiền gửi khách hàng > 0.0002 & nguyên giá TSCĐ > 3e-06) hoặc chứng khoán đầu tư > 8e-05. Điều này phản ánh TCB duy trì quy mô hoạt động ổn định và chiến lược đầu tư hiệu quả, với sự gia tăng đồng thời ở nguồn vốn huy động và tài sản đầu tư trong các năm gần đây.

7 CHƯƠNG 3: CÁC THỐNG KÊ CƠ BẢN

7.1 Thống kê mô tả 10 biến tài chính

7.1.1 Thống kê quy mô & Hoạt động tín dụng

1. install.packages("ggplot2")
2. library(dplyr); library(tidyr); library(ggplot2)
3. tcb_nhom1 <- d %>%
4.   select(Năm, all_of(nhom1_quymo_hoatdong)) %>%
5.   pivot_longer(-Năm, names_to = "Chỉ_tiêu", values_to = "Giá_trị") %>%
6.   mutate(Giá_trị = as.numeric(gsub(",", "", Giá_trị)))
7. ggplot(tcb_nhom1, aes(Năm, Giá_trị, fill = Chỉ_tiêu)) +
8.   geom_col(position = "dodge", width = 0.7) +
9.   labs(
10.     title = "Quy mô & Hoạt động tín dụng TCB (2014–2023)",
11.     x = "Năm", y = "Giá trị (tỷ đồng)", fill = "Chỉ tiêu"
12.   ) +
13.   theme_minimal(base_size = 13) +
14.   theme(plot.title = element_text(face = "bold", hjust = 0.5))

Ý nghĩa kỹ thuật:

select() → chọn các cột cần phân tích (năm + các chỉ tiêu).

pivot_longer() → chuyển dữ liệu từ dạng rộng sang dạng dài để ggplot dễ vẽ (tạo 2 cột “Chỉ_tiêu” và “Giá_trị”).

geom_col() → vẽ cột, chiều cao = giá trị.

position = “dodge” → các cột trong cùng năm được đặt cạnh nhau để so sánh.

labs(title=…, x=…, y=…, fill=…): Gán tiêu đề và nhãn cho biểu đồ.

theme_minimal()+theme(…)`: Tạo phong cách tối giản, căn giữa tiêu đề (hjust = 0.5), chỉnh kích thước chữ và vị trí chú giải.

print(p1): Hiển thị biểu đồ.

Nhận xét:

Nhóm Quy mô & Hoạt động tín dụng có sự chênh lệch rõ rệt giữa các biến. Tổng nợ phải trả đạt mức trung bình cao nhất (≈353 nghìn tỷ) và biến động lớn (SD ≈185,6), tiếp theo là Tiền gửi khách hàng (Mean ≈246,5). Hoạt động tín dụng giữa các TCTD có quy mô thấp hơn đáng kể. Lợi nhuận chưa phân phối biến động tương đối (SD ≈22,3). Biểu đồ boxplot (log10) khẳng định tổng nợ phải trả và tiền gửi khách hàng vượt trội, phản ánh ngân hàng chủ yếu dựa vào nguồn vốn huy động và nghĩa vụ tài chính để vận hành tín dụng.

7.1.2 Thống kê cơ cấu tài sản & thanh khoản

1. library(dplyr); library(tidyr); library(ggplot2); library(scales)
2. ggplot(d %>%
3.          select(Năm, all_of(nhom2_taisan_thanhkhoan)) %>%
4.          pivot_longer(-Năm, names_to="Chỉ_tiêu", values_to="Giá_trị") %>%
5.          mutate(Giá_trị = as.numeric(gsub(",", "", Giá_trị))/1e9,
6.                 Năm = factor(Năm, levels=2014:2023)),
7.        aes(x=Năm, y=Giá_trị, fill=Chỉ_tiêu)) +
8.   geom_col(position=position_dodge(0.7)) +
9.   scale_y_continuous(labels=label_comma(suffix=" Tỷ")) +
10.   labs(title="Thống kê Cơ cấu tài sản & Thanh khoản TCB (2014–2023)",
11.        x="Năm", y="Giá trị (Tỷ đồng)", fill="Chỉ tiêu") +
12.   theme_minimal(base_size=13) +
13.   theme(plot.title=element_text(face="bold", hjust=0.5),
14.         axis.text.x=element_text(angle=45, hjust=1))

Ý nghĩa kỹ thuật:

ggplot(data, aes(…)): khởi tạo biểu đồ, chọn dữ liệu và ánh xạ (x = năm, y = giá trị, fill = chỉ tiêu).

Giá_trị / 1e9: chia giá trị cho 1 tỷ → đổi đơn vị sang “tỷ đồng”.

geom_col(…): vẽ cột, position = “dodge” để tách cột cho từng chỉ tiêu, width = 0.7 chỉnh độ rộng cột.

labs(…): đặt tiêu đề và nhãn trục.

theme_minimal(): dùng giao diện tối giản, gọn và dễ nhìn.

Nhận xét:

Các biến trong nhóm Cơ cấu tài sản & Thanh khoản có sự chênh lệch lớn: chứng khoán đầu tư (Mean = 73.97; SD = 24.21) và nguyên giá TSCĐ (Mean = 2.73; SD = 1.71) chiếm tỷ trọng cao, trong khi khấu hao TSCĐ (Mean = –0.89; SD = 0.67) và mua nợ (Mean = 0.08; SD = 0.12) thấp hơn nhiều, phản ánh TCB tập trung vào đầu tư dài hạn, ít rủi ro thanh khoản. Biểu đồ boxplot thể hiện rõ sự phân tán này, với hai nhóm giá trị cao và thấp tách biệt, phản ánh cấu trúc tài sản của ngân hàng thiên về đầu tư chứng khoán và tài sản cố định.

7.2 Phân tích tương quan giữa các biến tài chính của Techcombank

7.2.1 Phân tích tương quan giữa quy mô & hoạt động tín dụng

7.2.1.1 Kiểm tra tương quan giữa tổng nợ phải trả và tiền gửi của khách hàng

1. cor_test_result <- cor.test(
2.   tcb_10bien$`Tổng nợ phải trả`,
3.   tcb_10bien$`Tiền gửi của khách hàng`,
4.   method = "pearson"
5. )
6. cor_test_result
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Tổng nợ phải trả` and tcb_10bien$`Tiền gửi của khách hàng`
## t = 24.049, df = 8, p-value = 0.000000009527
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9702277 0.9984401
## sample estimates:
##       cor 
## 0.9931548

Ý nghĩa kỹ thuật:

cor.test() : dùng để kiểm định ý nghĩa thống kê của hệ số tương quan giữa hai biến.

method = “pearson” : sử dụng tương quan Pearson (thích hợp với biến định lượng có phân bố gần chuẩn).

Kết quả trả về gồm:

cor → hệ số tương quan (r)

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Kết quả kiểm định tương quan Pearson giữa Tổng nợ phải trả và Tiền gửi của khách hàng cho thấy hệ số tương quan

r = 0.993 với giá trị p < 0.001.

Hai biến có tương quan thuận rất mạnh (r ≈ 0.99), nghĩa là tiền gửi khách hàng tăng thì tổng nợ phải trả cũng tăng tương ứng. Khoảng tin cậy 95% (0.97–0.998) cho thấy mối quan hệ này ổn định và mang tính phụ thuộc cao trong hoạt động huy động và nghĩa vụ nợ của ngân hàng.

7.2.1.2 Kiểm tra tương quan giữa tổng nợ phải trả lợi nhuận chưa phân phối

1. cor.test(
2.   tcb_10bien$`Tổng nợ phải trả`,
3.   tcb_10bien$`Lợi nhuận chưa phân phối`,
4.   method = "pearson"
5. )
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Tổng nợ phải trả` and tcb_10bien$`Lợi nhuận chưa phân phối`
## t = 7.1298, df = 8, p-value = 0.00009904
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7231035 0.9835354
## sample estimates:
##       cor 
## 0.9295291

Ý nghĩa kỹ thuật:

cor.test() : dùng để kiểm định ý nghĩa thống kê của hệ số tương quan giữa hai biến.

method = “pearson” : sử dụng tương quan Pearson (thích hợp với biến định lượng có phân bố gần chuẩn).

Kết quả trả về gồm:

cor → hệ số tương quan (r)

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Hệ số tương quan: r = 0.9295, với p < 0.001, cho thấy mối tương quan thuận rất mạnh và có ý nghĩa thống kê cao.

Điều này chứng tỏ khi Tổng nợ phải trả của Techcombank tăng, lợi nhuận chưa phân phối cũng có xu hướng tăng theo, phản ánh khả năng tăng trưởng quy mô tài chính gắn liền với hiệu quả sinh lợi của ngân hàng.

7.2.1.3 Kiểm tra tương quan giữa tiền gửi của khách hàng và mua nợ

1. cor.test(
2.   tcb_10bien$`Tiền gửi của khách hàng`,
3.   tcb_10bien$`Mua nợ`,
4.   method = "pearson"
5. )
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Tiền gửi của khách hàng` and tcb_10bien$`Mua nợ`
## t = -0.13691, df = 8, p-value = 0.8945
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.6579468  0.5995274
## sample estimates:
##      cor 
## -0.04835

Ý nghĩa kỹ thuật:

cor.test() : dùng để kiểm định ý nghĩa thống kê của hệ số tương quan giữa hai biến.

method = “pearson” : sử dụng tương quan Pearson (thích hợp với biến định lượng có phân bố gần chuẩn).

Kết quả trả về gồm:

cor → hệ số tương quan (r)

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Hệ số tương quan: r = -0.048, với p > 0.05, cho thấy mối tương quan rất yếu và không có ý nghĩa thống kê.

Điều này chứng tỏ biến động mua nợ của Techcombank hầu như không liên quan đến quy mô tiền gửi của khách hàng, phản ánh hai hoạt động này diễn ra độc lập trong cơ cấu tài chính của ngân hàng.

7.2.2 Phân tích tương quan giữa cơ cấu tài sản & Thanh khoản

7.2.2.1 Kiểm tra tương quan giữa tiền gửi cấp tín dụng cho các tctd khác và chứng khoán đầu tư

1. cor.test(
2.   tcb_10bien$`Tiền gửi và cấp tín dụng cho các TCTD khác`,
3.   tcb_10bien$`Chứng khoán đầu tư`,
4.   method = "pearson"
5. )
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Tiền gửi và cấp tín dụng cho các TCTD khác` and tcb_10bien$`Chứng khoán đầu tư`
## t = 4.6136, df = 8, p-value = 0.001725
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4812291 0.9644613
## sample estimates:
##       cor 
## 0.8525403

Ý nghĩa kỹ thuật:

cor.test() : dùng để kiểm định ý nghĩa thống kê của hệ số tương quan giữa hai biến.

method = “pearson” : sử dụng tương quan Pearson (thích hợp với biến định lượng có phân bố gần chuẩn).

Kết quả trả về gồm:

cor → hệ số tương quan (r)

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Hệ số tương quan r = 0.853, với p < 0.01, cho thấy mối tương quan thuận mạnh và có ý nghĩa thống kê.

Điều này cho thấy khi Techcombank gia tăng hoạt động cho vay, cấp tín dụng liên ngân hàng, danh mục đầu tư chứng khoán của ngân hàng cũng có xu hướng mở rộng, phản ánh chiến lược phân bổ vốn linh hoạt giữa các kênh sinh lời an toàn và đầu tư tài chính.

7.2.2.2 Kiểm tra tương quan giữa nguyên giá tài sản cố định và khấu hao tài sản cố định

1. cor.test(
2.   tcb_10bien$`Chứng khoán kinh doanh`,
3.   tcb_10bien$`Chứng khoán đầu tư`,
4.   method = "pearson"
5. )
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Chứng khoán kinh doanh` and tcb_10bien$`Chứng khoán đầu tư`
## t = -0.11369, df = 8, p-value = 0.9123
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.6532699  0.6047559
## sample estimates:
##         cor 
## -0.04016347

Ý nghĩa kỹ thuật:

cor.test(): Thực hiện kiểm định tương quan giữa hai biến.

method = “pearson”: Dùng hệ số tương quan Pearson để đo mức độ tuyến tính giữa hai biến.

cor: Là hệ số tương quan Pearson (r), nằm trong khoảng [-1, 1].

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Hệ số tương quan r = -0.04, với p > 0.05, cho thấy mối tương quan rất yếu và không có ý nghĩa thống kê.

Điều này nghĩa là hai danh mục đầu tư này của Techcombank hoạt động khá độc lập, việc tăng hoặc giảm chứng khoán kinh doanh không ảnh hưởng rõ rệt đến danh mục chứng khoán đầu tư.

7.2.2.3 Kiểm tra tương quan giữa mua nợ và dự phòng rủi ro hoạt động mua nợ

1. cor.test(
2.   tcb_10bien$`Nguyên giá tài sản cố định`,
3.   tcb_10bien$`Khấu hao tài sản cố định`,
4.   method = "pearson"
5. )
## 
##  Pearson's product-moment correlation
## 
## data:  tcb_10bien$`Nguyên giá tài sản cố định` and tcb_10bien$`Khấu hao tài sản cố định`
## t = -2.6169, df = 8, p-value = 0.0308
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.91675307 -0.08647828
## sample estimates:
##        cor 
## -0.6791268

Ý nghĩa kỹ thuật:

cor.test(): Thực hiện kiểm định tương quan giữa hai biến.

method = “pearson”: Dùng hệ số tương quan Pearson để đo mức độ tuyến tính giữa hai biến.

cor: Là hệ số tương quan Pearson (r), nằm trong khoảng [-1, 1].

p-value → kiểm định ý nghĩa (nếu p < 0.05 thì tương quan có ý nghĩa thống kê)

Nhận xét:

Hệ số tương quan r = -0.68, với p < 0.05, cho thấy mối tương quan nghịch vừa và có ý nghĩa thống kê.

Điều này nghĩa là khi giá trị tài sản cố định tăng, mức khấu hao có xu hướng giảm, phản ánh khả năng Techcombank đầu tư mới vào tài sản cố định, làm giảm tỷ trọng khấu hao so với tổng giá trị tài sản.

7.3 Tốc dộ tăng trưởng của các chỉ tiêu tài chính

7.3.1 Tốc độ tăng trưởng hàng năm của các chỉ tiêu quy mô và hoạt động tín dụng của TCB

1. library(dplyr)
2. library(tidyr)
3. library(ggplot2)
4. nhom1 <- nhom1_quymo_hoatdong
5. tcb_10bien <- tcb_10bien %>% slice(1:10) %>% mutate(Năm = 2014:2023)
6. tcb_tangtruong_long1 <- tcb_10bien %>%
7.   select(Năm, all_of(nhom1)) %>%
8.   mutate(across(-Năm, ~ (as.numeric(gsub(",", "", .)) - lag(as.numeric(gsub(",", "", .)))) /
9.                         lag(as.numeric(gsub(",", "", .))) * 100)) %>%
10.   pivot_longer(-Năm, names_to="Chỉ_tiêu", values_to="Tăng_trưởng")
11. ggplot(tcb_tangtruong_long1, aes(Năm, Tăng_trưởng, color=Chỉ_tiêu, group=Chỉ_tiêu)) +
12.   geom_line(size=1.1, na.rm=TRUE) + geom_point(size=2, na.rm=TRUE) +
13.   scale_x_continuous(breaks=2014:2023) +
14.   labs(title="Tốc độ tăng trưởng (%)\nQuy mô & Hoạt động tín dụng TCB (2014–2023)",
15.        x="Năm", y="Tăng trưởng (%)", color="Chỉ tiêu") +
16.   theme_minimal(base_size=13) +
17.   theme(plot.title=element_text(face="bold",hjust=0.5),
18.         axis.text.x=element_text(angle=45,hjust=1))

Ý nghĩa kỹ thuật:

mutate(across(…)): tính tốc độ tăng trưởng (%) cho từng biến

pivot_longer(): chuyển dữ liệu sang dạng dài để dễ vẽ ggplot.

geom_line() + geom_point(): vẽ đường xu hướng và điểm dữ liệu qua các năm.

scale_x_continuous(): đặt mốc trục x theo từng năm.

labs() và theme_minimal(): thêm tiêu đề, nhãn trục và làm biểu đồ gọn, dễ đọc.

Nhận xét:

Tổng nợ phải trả và tiền gửi khách hàng của Techcombank đều tăng ổn định qua các năm, đặc biệt tăng mạnh từ 2020–2023, phản ánh mở rộng quy mô huy động và cho vay. Giai đoạn 2016–2017 và 2019–2020 duy trì tăng trưởng đều, cho thấy hoạt động tài chính ổn định và bền vững.

7.3.2 Tốc độ tăng trưởng hàng năm của các chỉ tiêu cơ cấu tài sản và thanh khoản tín dụng của TCB

1. library(dplyr)
2. library(stringr)
3. nhom2 <- nhom2_taisan_thanhkhoan
4. d_num <- d %>%
5.   mutate(across(all_of(nhom2),
6.                 ~ as.numeric(str_replace_all(as.character(.x), ",", ""))))
7. d_tangtruong_nhom2 <- d_num %>%
8.   select(Năm, all_of(nhom2)) %>%
9.   arrange(Năm) %>%
10.   mutate(across(all_of(nhom2),
11.                 ~ (.-lag(.))/lag(.)*100,
12.                 .names = "{.col}_tangtruong"))
13. library(dplyr)
14. library(ggplot2)
15. d_num %>% 
16.   select(Năm, all_of(nhom2)) %>%
17.   pivot_longer(-Năm, names_to="Chỉ_tiêu", values_to="Giá_trị") %>%
18.   mutate(Giá_trị_tỷ = Giá_trị/1e9) -> tmp
19. ggplot(tmp, aes(Năm, Giá_trị_tỷ, color=Chỉ_tiêu)) +
20.   geom_line() + geom_point() +
21.   labs(y="Giá trị (tỷ VND)", title="Giá trị theo năm (đơn vị: tỷ VND)") +
22.   theme_minimal() + theme(plot.title = element_text(hjust = 0.5))

Ý nghĩa kỹ thuật:

mutate(across(…)): chuyển các biến trong nhóm 2 sang dạng số.

arrange(Năm) + lag(): tính tốc độ tăng trưởng (%) qua các năm.

pivot_longer(): gom dữ liệu để vẽ biểu đồ.

mutate(Giá_trị_tỷ = Giá_trị/1e9): đổi sang tỷ VND.

ggplot(…): vẽ đường xu hướng giá trị theo năm cho từng chỉ tiêu.

Nhận xét:

Biểu đồ cho thấy “Chứng khoán đầu tư” tăng mạnh nhất, từ khoảng 0.05 lên hơn 0.1 tỷ VND, phản ánh quy mô đầu tư tài chính mở rộng rõ rệt. Các chỉ tiêu khác như mua nợ, khấu hao tài sản cố định, nguyên giá tài sản duy trì mức ổn định thấp quanh 0.001–0.01 tỷ VND, thể hiện phần tài sản và thanh khoản còn ít biến động.

7.4 Tỷ trọng và biến động cơ cấu tài sản – thanh khoản qua các năm của TCB

1. library(dplyr)
2. library(tidyr)
3. library(ggplot2)
4. library(knitr)
5. tcb_10bien$`Năm` <- 2014:2023
6. nhom2 <- c("Chứng khoán kinh doanh",
7.            "Chứng khoán đầu tư",
8.            "Nguyên giá tài sản cố định",
9.            "Khấu hao tài sản cố định",
10.            "Mua nợ")
11. cautruc_ts <- tcb_10bien %>%
12.   select(`Năm`, all_of(nhom2)) %>%
13.   mutate(`Tổng nhóm 2` = rowSums(across(all_of(nhom2)), na.rm = TRUE)) %>%
14.   pivot_longer(all_of(nhom2),
15.                names_to = "Chỉ tiêu",
16.                values_to = "Giá trị") %>%
17.   mutate(`Tỷ trọng (%)` = `Giá trị` / `Tổng nhóm 2` * 100) %>%
18.   group_by(`Chỉ tiêu`) %>%
19.   mutate(`Thay đổi so với 2014` = `Tỷ trọng (%)` - `Tỷ trọng (%)`[`Năm` == 2014]) %>%
20.   ungroup()
21. kable(head(cautruc_ts, 15),
22.       caption = "Bảng: Thay đổi cơ cấu tài sản & thanh khoản so với năm gốc 2014")
Bảng: Thay đổi cơ cấu tài sản & thanh khoản so với năm gốc 2014
Năm Tổng nhóm 2 Chỉ tiêu Giá trị Tỷ trọng (%) Thay đổi so với 2014
2014 57731825 Chứng khoán kinh doanh 2086246 3.6136845 0.0000000
2014 57731825 Chứng khoán đầu tư 54978730 95.2312351 0.0000000
2014 57731825 Nguyên giá tài sản cố định 1361399 2.3581430 0.0000000
2014 57731825 Khấu hao tài sản cố định -704367 -1.2200671 0.0000000
2014 57731825 Mua nợ 9817 0.0170045 0.0000000
2015 45238188 Chứng khoán kinh doanh 3072 0.0067907 -3.6068938
2015 45238188 Chứng khoán đầu tư 44301594 97.9296386 2.6984034
2015 45238188 Nguyên giá tài sản cố định 1341998 2.9665158 0.6083728
2015 45238188 Khấu hao tài sản cố định -803851 -1.7769301 -0.5568631
2015 45238188 Mua nợ 395375 0.8739850 0.8569806
2016 54295846 Chứng khoán kinh doanh 8024620 14.7794363 11.1657519
2016 54295846 Chứng khoán đầu tư 45674924 84.1223176 -11.1089175
2016 54295846 Nguyên giá tài sản cố định 1518287 2.7963226 0.4381796
2016 54295846 Khấu hao tài sản cố định -941451 -1.7339282 -0.5138611
2016 54295846 Mua nợ 19466 0.0358517 0.0188472
1. ggplot(cautruc_ts, aes(x = factor(`Năm`),
2.                        y = `Tỷ trọng (%)`,
3.                        fill = `Chỉ tiêu`)) +
4.   geom_col(color = "white", show.legend = FALSE) +
5.   facet_wrap(~ `Chỉ tiêu`, scales = "free_y", ncol = 2) +
6.   labs(
7.     title = "Cơ cấu tài sản & thanh khoản của TCB (2014–2023)",
8.     x = "Năm",
9.     y = "Tỷ trọng (%)"
10.   ) +
11.   theme_minimal(base_size = 13) +
12.   theme(
13.     plot.title = element_text(face = "bold", hjust = 0.5),
14.     axis.text.x = element_text(angle = 45, hjust = 1),
15.     strip.text = element_text(face = "bold", size = 12)
16.   )

Ý nghĩa kỹ thuật:

select(): Chỉ lấy cột năm và các biến trong nhóm 2.

rowSums(): Tính tổng giá trị nhóm 2 mỗi năm → “tổng tài sản nhóm 2”.

across(): Tính tỷ trọng (%) của từng biến trong tổng đó.

pivot_longer(): Chuyển dữ liệu sang dạng “dài” để dễ vẽ biểu đồ

mutate(…): Xóa tiền tố tytrong_

group_by(): Nhóm theo từng khoản mục.

kable(…): Hiển thị bảng kết quả.

ggplot(…): Vẽ biểu đồ

Nhận xét

TCB tập trung tài sản chủ yếu vào chứng khoán đầu tư với tỷ trọng lớn và ổn định. Các khoản mục khác như chứng khoán kinh doanh, mua nợ và tài sản cố định chiếm tỷ trọng nhỏ và ít biến động, cho thấy ngân hàng ưu tiên kênh đầu tư an toàn và thanh khoản cao.

7.5 Phân tích giá trị biên của các chỉ tiêu tài chính

1. library(dplyr)
2. library(tidyr)
3. library(ggplot2)
4. library(knitr)
5. tcb_tomtat_long <- tcb_10bien %>%
6.   summarise(across(
7.     c("Tiền gửi và cấp tín dụng cho các TCTD khác",
8.       "Cấp tín dụng cho các TCTD khác",
9.       "Chứng khoán kinh doanh",
10.       "Chứng khoán đầu tư",
11.       "Nguyên giá tài sản cố định",
12.       "Khấu hao tài sản cố định",
13.       "Tiền gửi của khách hàng",
14.       "Tổng nợ phải trả",
15.       "Mua nợ",
16.       "Lợi nhuận chưa phân phối"),
17.     list(Min = ~min(., na.rm = TRUE), Max = ~max(., na.rm = TRUE))
18.   )) %>%
19.   pivot_longer(everything(),
20.                names_to = c("Chỉ tiêu tài chính", ".value"),
21.                names_sep = "_(?=[^_]+$)") %>%
22.   rename(Minimum = Min, Maximum = Max)
23. kable(tcb_tomtat_long,
24.       caption = "Bảng 1. Giá trị biên (Min – Max) của 10 chỉ tiêu tài chính TCB (2014–2023)",
25.       align = "lcc",
26.       col.names = c("Chỉ tiêu tài chính", "Giá trị nhỏ nhất (Min)", "Giá trị lớn nhất (Max)"),
27.       format = "pipe")
Bảng 1. Giá trị biên (Min – Max) của 10 chỉ tiêu tài chính TCB (2014–2023)
Chỉ tiêu tài chính Giá trị nhỏ nhất (Min) Giá trị lớn nhất (Max)
Tiền gửi và cấp tín dụng cho các TCTD khác 14762009 104072320
Cấp tín dụng cho các TCTD khác 7274537 31064531
Chứng khoán kinh doanh 3072 10041556
Chứng khoán đầu tư 44301594 104993945
Nguyên giá tài sản cố định 1341998 5492246
Khấu hao tài sản cố định -1964680 609457
Tiền gửi của khách hàng 131689810 454660779
Tổng nợ phải trả 160915744 717865947
Mua nợ 1682 395375
Lợi nhuận chưa phân phối 1556411 64482685
1. tcb_tomtat_long %>%
2.   mutate(`Biên độ dao động` = Maximum - Minimum) %>%
3.   ggplot(aes(x = reorder(`Chỉ tiêu tài chính`, `Biên độ dao động`),
4.              y = `Biên độ dao động`)) +
5.   geom_col(fill = "steelblue") +
6.   coord_flip() +
7.   labs(
8.     title = "Biên độ dao động\ncác chỉ tiêu tài chính (2014–2023)",
9.     x = "Chỉ tiêu tài chính", y = "Biên độ (tỷ đồng)",
10.     caption = "Nguồn: Báo cáo tài chính Techcombank, tác giả tổng hợp"
11.   ) +
12.   theme_minimal(base_size = 13) +
13.   theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Ý nghĩa kỹ thuật:

bien_so <- c(…): tạo vecto biến số

summarise(across(…, list(Min=…, Max=…))) → tính Min và Max cho tất cả biến.

pivot_longer() → xoay bảng để gộp các cột Min/Max thành 1 cột chung dễ đọc.

rename() → đổi tên cột cho gọn.

kable() → in bảng đẹp, có căn lề và tiêu đề.

mutate(Range = Maximum - Minimum) → thêm cột biên độ (Max − Min).

ggplot(…, geom_col(), coord_flip()) → vẽ biểu đồ cột ngang thể hiện độ chênh lệch.

Nhận xét:

Biên độ lớn nhất thuộc về tổng nợ phải trả và tiền gửi của khách hàng, phản ánh mức dao động mạnh của các chỉ tiêu quy mô vốn và nợ theo thời gian. Một số biến như khấu hao tài sản cố định (giá trị âm) và chứng khoán kinh doanh có biên độ rất nhỏ, cần kiểm tra đơn vị hoặc dữ liệu. Do chênh lệch lớn giữa các biến, nên dùng thang log10 hoặc chuẩn hóa khi so sánh tương đối.

7.6 Hệ số hồi quy giữa các chỉ số tài chính

1. library(dplyr); library(broom)
2. cols <- names(tcb_10bien)
3. y <- "Lợi nhuận chưa phân phối"
4. results_single <- lapply(base::setdiff(cols, y), function(x) {
5.   # Bọc tên biến trong backtick để tránh lỗi do có dấu cách
6.   formula <- as.formula(paste0("`", y, "` ~ `", x, "`"))
7.   model <- lm(formula, data = tcb_10bien)
8.   out <- broom::tidy(model) %>%
9.     filter(term != "(Intercept)") %>%
10.     select(term, estimate, p.value)
11.   out$model <- paste0(y, " ~ ", x)
12.   return(out)
13. })
14. single_reg <- do.call(rbind, results_single)
15. print(single_reg)
## # A tibble: 10 × 4
##    term                                            estimate   p.value model     
##    <chr>                                              <dbl>     <dbl> <chr>     
##  1 `Tiền gửi và cấp tín dụng cho các TCTD khác`       0.655 0.000525  Lợi nhuận…
##  2 `Cấp tín dụng cho các TCTD khác`                   1.67  0.0820    Lợi nhuận…
##  3 `Chứng khoán kinh doanh`                          -1.00  0.673     Lợi nhuận…
##  4 `Chứng khoán đầu tư`                               0.826 0.000432  Lợi nhuận…
##  5 `Nguyên giá tài sản cố định`                      12.3   0.0000359 Lợi nhuận…
##  6 `Khấu hao tài sản cố định`                       -21.1   0.0501    Lợi nhuận…
##  7 `Tiền gửi của khách hàng`                          0.195 0.000213  Lợi nhuận…
##  8 `Tổng nợ phải trả`                                 0.112 0.0000990 Lợi nhuận…
##  9 `Mua nợ`                                           0.828 0.990     Lợi nhuận…
## 10 Năm                                          6904335.    0.0000616 Lợi nhuận…

Ý nghĩa kỹ thuật:

lapply(): lặp qua từng biến độc lập (trừ biến y).

lm(): ước lượng mô hình hồi quy dạng y ~ x.

broom::tidy(): trích xuất gọn hệ số ước lượng (estimate) và giá trị p (p.value).

Kết quả: bảng single_reg liệt kê hệ số hồi quy và mức ý nghĩa thống kê của từng biến

Nhận xét:

Kết quả hồi quy đơn biến cho thấy một số chỉ tiêu như tiền gửi khách hàng, tổng nợ phải trả, và nguyên giá tài sản cố định có ảnh hưởng có ý nghĩa thống kê đến lợi nhuận chưa phân phối (p < 0.05). Đặc biệt, nguyên giá tài sản cố định tác động tích cực mạnh nhất, trong khi khấu hao tài sản cố định có tác động ngược chiều.

7.7 Tỷ lệ thay đổi tuyệt đối hàng năm

1. library(dplyr); library(tidyr); library(ggplot2); library(stringr)
2. tcb_yoy <- d %>%
3.   select(Năm, `Tiền gửi của khách hàng`, `Tổng nợ phải trả`,
4.          `Tiền gửi và cấp tín dụng cho các TCTD khác`,
5.          `Chứng khoán đầu tư`, `Lợi nhuận chưa phân phối`) %>%
6.   pivot_longer(-Năm, names_to = "Chi_tieu", values_to = "Gia_tri") %>%
7.   mutate(Gia_tri = as.numeric(str_replace_all(as.character(Gia_tri), "[^0-9\\-\\.]", ""))) %>%
8.   group_by(Chi_tieu) %>%
9.   arrange(Năm) %>%
10.   mutate(Ty_le_thay_doi = (Gia_tri - lag(Gia_tri)) / lag(Gia_tri) * 100) %>%
11.   ungroup()
12. ggplot(tcb_yoy, aes(x = Năm, y = Ty_le_thay_doi, color = Chi_tieu)) +
13.   geom_line(size = 1) + geom_point(size = 2) +
14.   geom_hline(yintercept = 0, linetype = "dashed") +
15.   theme_minimal(base_size = 13) +
16.   labs(title = "Tỷ lệ thay đổi hàng năm (%) của các chỉ tiêu TCB (2014–2023)",
17.        x = "Năm", y = "Tỷ lệ thay đổi (%)", color = "Chỉ tiêu") +
18.   theme(plot.title = element_text(hjust = 0.5))

Ý nghĩa kỹ thuật:

select(): chọn 5 chỉ tiêu tài chính cần phân tích.

pivot_longer(): chuyển dữ liệu từ dạng rộng sang dài, giúp dễ nhóm và vẽ biểu đồ.

mutate(): làm sạch giá trị (bỏ ký tự %, VND, dấu phẩy…) rồi chuyển sang dạng số.

group_by() + mutate(lag()): tính tỷ lệ thay đổi hàng năm (%) cho từng chỉ tiêu.

ggplot(): trực quan hóa biến động qua các năm, dùng geom_line() + geom_point() để thể hiện xu hướng tăng giảm, thêm đường tham chiếu 0% giúp dễ nhận biết năm âm/dương.

Nhận xét:

Biểu đồ cho thấy lợi nhuận chưa phân phối và tiền gửi & cấp tín dụng cho các TCTD khác biến động mạnh nhất qua các năm, phản ánh sự thay đổi lớn trong hoạt động tài chính của TCB. Ngược lại, tổng nợ phải trả và chứng khoán đầu tư duy trì mức tăng trưởng ổn định hơn, cho thấy cơ cấu tài chính tương đối vững.

7.8 Chỉ số biến động (Volatility Index)

1. bien_daidien <- nhom1_quymo_hoatdong
2. volatility_daidien <- tcb_10bien %>%
3.   select(all_of(bien_daidien)) %>%
4.   summarise(across(
5.     everything(),
6.     ~ sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE),
7.     .names = "Volatility_{.col}"
8.   )) %>%
9.   pivot_longer(
10.     cols = everything(),
11.     names_to = "Chỉ tiêu",
12.     values_to = "Chỉ số biến động"
13.   ) %>%
14.   arrange(desc(`Chỉ số biến động`))
15. volatility_daidien
## # A tibble: 5 × 2
##   `Chỉ tiêu`                                            `Chỉ số biến động`
##   <chr>                                                              <dbl>
## 1 Volatility_Lợi nhuận chưa phân phối                                0.902
## 2 Volatility_Tiền gửi và cấp tín dụng cho các TCTD khác              0.666
## 3 Volatility_Cấp tín dụng cho các TCTD khác                          0.547
## 4 Volatility_Tổng nợ phải trả                                        0.526
## 5 Volatility_Tiền gửi của khách hàng                                 0.423

Ý nghĩa kỹ thuật:

sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE) → độ lệch chuẩn chia trung bình, cho ta chỉ số biến động (CV – Coefficient of Variation).

.names = “Volatility_{.col}” → tự động tạo tên cột kiểu “Volatility_Tiền gửi của khách hàng”.

pivot_longer() → gom lại thành 2 cột “Chỉ tiêu” và “Chỉ số biến động”.

arrange(desc()) → sắp xếp giảm dần theo mức biến động.

Nhận xét:

Kết quả cho thấy các chỉ tiêu tài chính của TCB có mức biến động không đồng đều. Những biến có hệ số biến động cao biểu hiện sự thay đổi mạnh và rủi ro cao hơn qua thời gian, trong khi các biến có hệ số thấp cho thấy xu hướng tăng trưởng ổn định và nhất quán trong giai đoạn 2014–2023.

7.9 Hệ số hiệu quả sử dụng tài sản

1. library(dplyr); library(stringr)
2. clean_num_vec <- function(x) {
3.   x <- str_replace_all(as.character(x),
4.                        c("^\\((.*)\\)$" = "-\\1", "%|VND|vnđ|VNĐ|triệu|tỷ" = "", "\\." = ""))
5.   x <- str_trim(x)
6.   x <- str_replace_all(x, ",(?=[0-9]{3,})", "")    
7.   x <- str_replace_all(x, ",", ".")                
8.   x <- str_replace_all(x, "[^0-9eE\\.-]", "")
9.   x[x %in% c("", "NA", "NaN", "-", "—", "NULL")] <- NA
10.   as.numeric(x)
11. }
12. year_col <- intersect(c("Năm", "nam"), names(tcb_10bien))[1]
13. tcb_hieuqua_taisan <- tcb_10bien %>%
14.   mutate(across(-all_of(year_col), clean_num_vec),
15.          `Hiệu quả sử dụng tài sản` = `Mua nợ` / `Nguyên giá tài sản cố định`) %>%
16.   select(any_of(c(year_col, "Nguyên giá tài sản cố định", "Mua nợ", "Hiệu quả sử dụng tài sản")))
17. head(tcb_hieuqua_taisan)
##    Năm Nguyên giá tài sản cố định Mua nợ Hiệu quả sử dụng tài sản
## 1 2014                    1361399   9817             0.0072109646
## 2 2015                    1341998 395375             0.2946166835
## 3 2016                    1518287  19466             0.0128210279
## 4 2017                    1602956  12092             0.0075435633
## 5 2018                    1835272   1682             0.0009164854
## 6 2019                    1761468   1682             0.0009548854

Ý nghĩa kỹ thuật:

clean_num_vec() → làm sạch số (bỏ ký tự %, VND, dấu ngoặc, đổi dấu phẩy).

year_col → tự động tìm cột năm (“Năm” hoặc “nam”).

mutate(across(…)) → chuyển các cột còn lại sang dạng số.

Thêm cột Hiệu quả sử dụng tài sản = Mua nợ / Nguyên giá tài sản cố định.

select() → chỉ giữ các cột cần dùng.

Nhận xét:

Các giá trị “Hiệu quả sử dụng tài sản” đều nhỏ (<1), cho thấy lượng mua nợ thấp hơn nhiều so với giá trị tài sản cố định, nghĩa là ngân hàng sử dụng tài sản khá thận trọng, hiệu suất khai thác tài sản còn hạn chế.

7.10 Tính hệ số biến thiên (CV = sd/mean)

1. library(dplyr); library(tidyr)
2. bien_chon <- c(
3.   "Tiền gửi của khách hàng",
4.   "Tổng nợ phải trả",
5.   "Tiền gửi và cấp tín dụng cho các TCTD khác",
6.   "Chứng khoán đầu tư",
7.   "Lợi nhuận chưa phân phối"
8. )
9. CV_ketqua <- tcb_10bien %>%
10.   summarise(across(all_of(bien_chon),
11.                    ~ sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE),
12.                    .names = "Hệ số biến thiên_{.col}")) %>%
13.   pivot_longer(everything(),
14.                names_to = "Chỉ tiêu",
15.                values_to = "Hệ số biến thiên") %>%
16.   arrange(desc(`Hệ số biến thiên`))
17. print(CV_ketqua)
## # A tibble: 5 × 2
##   `Chỉ tiêu`                                                  `Hệ số biến thiên`
##   <chr>                                                                    <dbl>
## 1 Hệ số biến thiên_Lợi nhuận chưa phân phối                                0.902
## 2 Hệ số biến thiên_Tiền gửi và cấp tín dụng cho các TCTD khác              0.666
## 3 Hệ số biến thiên_Tổng nợ phải trả                                        0.526
## 4 Hệ số biến thiên_Tiền gửi của khách hàng                                 0.423
## 5 Hệ số biến thiên_Chứng khoán đầu tư                                      0.327

Ý nghĩa kỹ thuật:

summarise(across(…)): tính hệ số biến thiên (CV = sd / mean) cho từng chỉ tiêu được chọn.

pivot_longer(): chuyển bảng từ dạng rộng sang dạng dài để dễ so sánh.

arrange(desc()): sắp xếp kết quả theo CV giảm dần (biến động cao → thấp).

Nhận xét:

Chỉ tiêu “Lợi nhuận chưa phân phối” có CV cao nhất (≈0.90), biến động mạnh nhất, thể hiện lợi nhuận thay đổi nhiều qua các năm. Ngược lại, “Chứng khoán đầu tư” có CV thấp nhất (≈0.33), ít biến động trong giai đoạn phân tích.

7.11 Phân tích độ bất đối xứng dữ liệu tài chính (Skewness Analysis)

1. library(dplyr); library(e1071)   
2. bien_chon <- c("Tổng nợ phải trả",
3.                "Tiền gửi của khách hàng",
4.                "Nguyên giá tài sản cố định",
5.                "Mua nợ",
6.                "Cấp tín dụng cho các TCTD khác")
7. Skewness_ketqua <- tcb_10bien %>%
8.   summarise(across(all_of(bien_chon),
9.                    ~ e1071::skewness(.x, na.rm = TRUE),
10.                    .names = "Skewness_{col}")) %>%
11.   tidyr::pivot_longer(everything(),
12.                       names_to = "Chỉ tiêu",
13.                       values_to = "Độ bất đối xứng")
14. print(Skewness_ketqua)
## # A tibble: 5 × 2
##   `Chỉ tiêu`                              `Độ bất đối xứng`
##   <chr>                                               <dbl>
## 1 Skewness_Tổng nợ phải trả                           0.717
## 2 Skewness_Tiền gửi của khách hàng                    0.636
## 3 Skewness_Nguyên giá tài sản cố định                 0.689
## 4 Skewness_Mua nợ                                     1.65 
## 5 Skewness_Cấp tín dụng cho các TCTD khác             1.17

Ý nghĩa kỹ thuật:

library() nạp gói.

bien_chon chọn 5 biến cần tính.

summarise(across()) tính skewness cho từng biến.

pivot_longer() chuyển kết quả sang dạng dài (2 cột).

Nhận xét:

Các chỉ tiêu đều có skewness dương, cho thấy phân phối lệch phải. Trong đó, Mua nợ (1.65) và Cấp tín dụng cho các TCTD khác (1.17) lệch mạnh nhất, phản ánh dữ liệu tập trung ở giá trị nhỏ và xuất hiện vài giá trị lớn vượt trội.

7.12 Phân tích tốc độ tăng trưởng bình quân năm (CAGR) của các chỉ tiêu tài chính

1. library(dplyr); library(tidyr); library(ggplot2)
2. bien_chon <- c("Tổng nợ phải trả", "Tiền gửi của khách hàng",
3.                "Nguyên giá tài sản cố định", "Mua nợ",
4.                "Cấp tín dụng cho các TCTD khác")
5. CAGR_ketqua <- tcb_10bien %>%
6.   summarise(across(all_of(bien_chon),
7.                    ~ ((last(na.omit(.)) / first(na.omit(.)))^(1/(n()-1)) - 1) * 100,
8.                    .names = "CAGR_{col}")) %>%
9.   pivot_longer(everything(),
10.                names_to = "Chỉ tiêu",
11.                values_to = "Tốc độ tăng trưởng bình quân (%)")
12. ggplot(CAGR_ketqua, aes(reorder(`Chỉ tiêu`, `Tốc độ tăng trưởng bình quân (%)`),
13.                         `Tốc độ tăng trưởng bình quân (%)`)) +
14.   geom_col(fill = "steelblue") +
15.   geom_text(aes(label = sprintf("%.2f", `Tốc độ tăng trưởng bình quân (%)`)),
16.             hjust = -0.2, size = 4) +
17.   coord_flip() +
18.   theme_minimal() +
19.   labs(title = "Tốc độ tăng trưởng bình quân (CAGR)\ncác chỉ tiêu tài chính TCB (2014–2023)",
20.        x = NULL, y = "Tốc độ tăng trưởng bình quân (%)") +
21.   expand_limits(y = max(CAGR_ketqua$`Tốc độ tăng trưởng bình quân (%)`) * 1.15)

Ý nghĩa kỹ thuật:

across() Tính CAGR cho từng chỉ tiêu được chọn

summarise(): Gom kết quả thành một hàng

pivot_longer(): Chuyển dữ liệu sang dạng dài để dễ vẽ

ggplot() Tạo biểu đồ cột ngang với geom_col() và hiển thị giá trị bằng geom_text().

Nhận xét:

Biểu đồ cho thấy “Mua nợ” có tốc độ tăng trưởng cao nhất (≈8,98%), tiếp theo là “Tổng nợ phải trả” (6,16%) và “Nguyên giá tài sản cố định” (5,74%). Hai chỉ tiêu còn lại tăng chậm hơn, đặc biệt “Cấp tín dụng cho các TCTD khác” chỉ đạt 3,85%. Điều này phản ánh hoạt động mua nợ và mở rộng nguồn vốn của TCB tăng mạnh hơn so với mảng tín dụng liên ngân hàng.

7.13 Xếp hạng tốc độ tăng trưởng trung bình của quy mô và hoạt động tài chính

1. library(dplyr); library(tidyr); library(ggplot2); library(stringr)
2. tcb_xephang <- tcb_10bien %>%
3.   mutate(Năm = 2014:2023) %>%
4.   mutate(across(all_of(nhom1_quymo_hoatdong), ~ as.numeric(str_replace_all(as.character(.), ",", "")))) %>%
5.   mutate(across(all_of(nhom1_quymo_hoatdong), ~ (. - lag(.)) / lag(.) * 100, .names = "Tăng_trưởng_{.col}")) %>%
6.   pivot_longer(starts_with("Tăng_trưởng_"), names_to = "Chỉ_tiêu", values_to = "Tăng_trưởng") %>%
7.   mutate(Chỉ_tiêu = str_remove(Chỉ_tiêu, "Tăng_trưởng_")) %>%
8.   group_by(Chỉ_tiêu) %>%
9.   summarise(Tăng_trưởng_TB = mean(Tăng_trưởng, na.rm = TRUE), .groups = "drop") %>%
10.   arrange(desc(Tăng_trưởng_TB))
11. max_x <- max(tcb_xephang$Tăng_trưởng_TB, na.rm = TRUE)
12. ggplot(tcb_xephang, aes(Tăng_trưởng_TB, reorder(Chỉ_tiêu, Tăng_trưởng_TB))) +
13.   geom_segment(aes(x = 0, xend = Tăng_trưởng_TB, yend = Chỉ_tiêu),
14.                color = "gray70") +
15.   geom_point(size = 4, color = "steelblue") +
16.   geom_text(aes(label = round(Tăng_trưởng_TB, 1)), hjust = -0.1, size = 3.5) +
17.   labs(title = "Xếp hạng Tăng trưởng trung bình\ncác chỉ tiêu TCB (2014–2023)",
18.        x = "Tăng trưởng trung bình (%)", y = NULL) +
19.   theme_minimal(base_size = 13) +
20.   theme(plot.title = element_text(hjust = 0.5, face = "bold"),
21.         plot.margin = margin(5, 30, 5, 5)) +     # thêm lề phải
22.   coord_cartesian(xlim = c(0, max_x * 1.18), clip = "off")  # mở rộng và cho phép vẽ ngoài

Ý nghĩa kỹ thuật:

mutate(across(…)): chuyển ký tự có dấu phẩy thành số, rồi tính tăng trưởng % từng năm.

pivot_longer(): gộp các biến tăng trưởng thành 2 cột “Chỉ tiêu” và “Tăng trưởng”.

summarise(): tính trung bình tăng trưởng từng chỉ tiêu.

ggplot(): vẽ biểu đồ điểm hiển thị mức tăng trưởng trung bình.

Nhận xét:

Kết quả cho thấy “Lợi nhuận chưa phân phối” có tốc độ tăng trưởng trung bình cao nhất (52.3%), tiếp theo là “Cấp tín dụng cho các TCTD khác” (36.6%) và “Tiền gửi & cấp tín dụng cho các TCTD khác” (29.3%). Hai chỉ tiêu “Tổng nợ phải trả” và “Tiền gửi khách hàng” tăng chậm hơn, chỉ khoảng 15–18% mỗi năm.

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

8.1 Trực quan hóa xu hướng tăng trưởng theo thời gian của các chỉ tiêu quy mô và hoạt động tín dụng

1. library(dplyr); library(tidyr); library(ggplot2); library(scales)
2. cols_nhom1 <- c(
3.   "Tiền gửi của khách hàng",
4.   "Tổng nợ phải trả",
5.   "Tiền gửi và cấp tín dụng cho các TCTD khác",
6.   "Cấp tín dụng cho các TCTD khác",
7.   "Lợi nhuận chưa phân phối"
8. )
9. tcb_nhom1_long <- d %>%
10.   mutate(across(all_of(cols_nhom1), ~ as.numeric(gsub("[^0-9.-]", "", .)))) %>%
11.   select(Năm, all_of(cols_nhom1)) %>%
12.   pivot_longer(-Năm, names_to = "Chỉ_tiêu", values_to = "Giá_trị")
13. ggplot(tcb_nhom1_long, aes(x = Năm, y = Giá_trị, color = Chỉ_tiêu, group = Chỉ_tiêu)) +
14.   geom_line(size = 1.2) +
15.   geom_point(size = 2) +
16.   scale_y_continuous(labels = comma) +
17.   labs(
18.     title = "Xu hướng Quy mô & Hoạt động tín dụng TCB (2014–2023)",
19.     x = "Năm",
20.     y = "Giá trị (tỷ đồng)",
21.     color = "Chỉ tiêu"
22.   ) +
23.   theme_minimal(base_size = 13) +
24.   theme(
25.     plot.title = element_text(face = "bold", hjust = 0.5, size = 15),
26.     legend.position = "right",
27.     legend.title = element_text(face = "bold"),
28.     panel.grid.minor = element_blank()
29.   )

Ý nghĩa kỹ thuật:

mutate(across(…)): chuyển toàn bộ các cột chỉ tiêu sang dạng số, loại bỏ ký tự không phải số.

pivot_longer(): chuyển dữ liệu từ dạng rộng sang dài, giúp dễ vẽ nhiều đường trên cùng biểu đồ.

ggplot() + geom_line() + geom_point(): tạo biểu đồ đường thể hiện xu hướng biến động theo thời gian.

scale_y_continuous(labels = comma): định dạng trục tung theo dạng có dấu phẩy ngăn cách hàng nghìn.

theme_minimal() và theme(…): làm gọn biểu đồ, căn giữa tiêu đề, chuyển chú thích sang bên phải.

Nhận xét:

Biểu đồ thể hiện rõ xu hướng tăng trưởng mạnh mẽ của các chỉ tiêu “Tổng nợ phải trả” và “Tiền gửi của khách hàng”, trong khi các chỉ tiêu khác tăng chậm hơn. Điều này cho thấy quy mô huy động và nghĩa vụ tài chính của TCB mở rộng nhanh qua giai đoạn 2014–2023, phản ánh sự mở rộng hoạt động tín dụng và quy mô ngân hàng.

8.2 Tương quan giữa các chỉ tiêu quy mô và hoạt động

1. install.packages("ggcorrplot", repos = "https://cloud.r-project.org")
## package 'ggcorrplot' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\DELL\AppData\Local\Temp\RtmpmClaaG\downloaded_packages
1. library(dplyr); library(ggcorrplot)
2. cor_matrix <- tcb_10bien %>%
3.   select(`Tiền gửi của khách hàng`,
4.          `Tổng nợ phải trả`,
5.          `Tiền gửi và cấp tín dụng cho các TCTD khác`,
6.          `Cấp tín dụng cho các TCTD khác`,
7.          `Lợi nhuận chưa phân phối`) %>%
8.   cor(use = "complete.obs")
9. ggcorrplot(
10.   cor_matrix,
11.   method = "square",
12.   type = "lower",
13.   lab = TRUE,
14.   lab_size = 3.5,
15.   tl.cex = 10,
16.   tl.srt = 45,
17.   colors = c("#6D9EC1", "white", "#E46726"),
18.   title = "Tương quan nhóm Quy mô & Hoạt động tín dụng (TCB)"
19. ) +
20.   theme(
21.     plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
22.     legend.position = "right",
23.     legend.justification = "center",
24.     legend.margin = margin(t = 0, r = 20, b = 0, l = 10),     
25.     legend.box.margin = margin(0, 20, 0, 20),                 
26.     axis.text.x = element_text(angle = 45, hjust = 1)
27.   )

Ý nghĩa kỹ thuật:

install.packages() cài gói ggcorrplot để vẽ ma trận tương quan.

library(dplyr); library(ggcorrplot) nạp thư viện xử lý và trực quan hóa dữ liệu.

select() chọn 5 biến thuộc nhóm Quy mô & Hoạt động tín dụng.

cor(use = “complete.obs”) tính hệ số tương quan Pearson giữa các biến, bỏ qua giá trị thiếu.

ggcorrplot() hiển thị ma trận tương quan dưới dạng ô vuông màu (heatmap), có nhãn giá trị, thang màu và tiêu đề.

theme() căn giữa, in đậm tiêu đề và chỉnh vị trí chú giải, góc nhãn trục.

Nhận xét:

Biểu đồ cho thấy “Tiền gửi của khách hàng” và “Tổng nợ phải trả” có tương quan rất cao (r ≈ 0.99), thể hiện sự tăng trưởng song hành của nguồn vốn huy động và nghĩa vụ nợ. “Lợi nhuận chưa phân phối” cũng tương quan mạnh với hai biến này (r ≈ 0.95), cho thấy hiệu quả tài chính tăng cùng quy mô tín dụng. Ngược lại, “Cấp tín dụng cho các TCTD khác” có mức tương quan thấp hơn (r < 0.5), phản ánh xu hướng biến động riêng biệt.

8.3 Tương quan giữa các chỉ tiêu cơ cấu tài sản và thanh khoản

1. # 1. Nạp thư viện
2. library(dplyr)
3. library(ggcorrplot)
4. cor_matrix_nhom2 <- tcb_10bien %>%
5.   select(`Chứng khoán kinh doanh`,
6.          `Chứng khoán đầu tư`,
7.          `Nguyên giá tài sản cố định`,
8.          `Khấu hao tài sản cố định`,
9.          `Mua nợ`) %>%
10.   cor(use = "complete.obs")
11. ggcorrplot(
12.   cor_matrix_nhom2,
13.   method = "square",
14.   type = "lower",
15.   lab = TRUE,
16.   lab_size = 3.5,
17.   tl.cex = 10,
18.   tl.srt = 45,
19.   colors = c("#6D9EC1", "white", "#E46726"),
20.   title = "Tương quan nhóm Cơ cấu tài sản & Thanh khoản (TCB)"
21. ) +
22.   theme(
23.     plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
24.     legend.position = "right",
25.     legend.justification = "center",
26.     legend.margin = margin(t = 0, r = 20, b = 0, l = 10),
27.     legend.box.margin = margin(0, 20, 0, 20),
28.     axis.text.x = element_text(angle = 45, hjust = 1)
29.   )

Ý nghĩa kỹ thuật:

install.packages() cài gói ggcorrplot để vẽ ma trận tương quan.

library(dplyr); library(ggcorrplot) nạp thư viện xử lý và trực quan hóa dữ liệu.

select() chọn 5 biến thuộc nhóm Quy mô & Hoạt động tín dụng.

cor(use = “complete.obs”) tính hệ số tương quan Pearson giữa các biến, bỏ qua giá trị thiếu.

ggcorrplot() hiển thị ma trận tương quan dưới dạng ô vuông màu (heatmap), có nhãn giá trị, thang màu và tiêu đề.

theme() căn giữa, in đậm tiêu đề và chỉnh vị trí chú giải, góc nhãn trục.

Nhận xét:

Biểu đồ cho thấy “Chứng khoán đầu tư” và “Chứng khoán kinh doanh” có mức tương quan rất cao (r ≈ 0.92), phản ánh xu hướng biến động cùng chiều của danh mục đầu tư. “Nguyên giá TSCĐ” và “Khấu hao TSCĐ” cũng có tương quan mạnh (r ≈ 0.88), cho thấy mối liên hệ nội tại giữa tài sản và chi phí khấu hao, trong khi “Mua nợ” có tương quan yếu hơn (r < 0.5), thể hiện biến động độc lập hơn với các chỉ tiêu khác.

8.4 Phân tích thành phần chính (PCA) — Các chỉ tiêu quy mô và hoạt động

1. library(ggplot2); library(dplyr); library(FactoMineR)
2. d_clean <- d %>%
3.   distinct()   
4. d_clean %>%
5.   select(
6.     "Tiền gửi của khách hàng",
7.     "Tổng nợ phải trả",
8.     "Tiền gửi và cấp tín dụng cho các TCTD khác",
9.     "Cấp tín dụng cho các TCTD khác",
10.     "Lợi nhuận chưa phân phối"
11.   ) %>%
12.   mutate(across(everything(), ~ as.numeric(gsub(",", "", .)))) %>%
13.   FactoMineR::PCA(scale.unit = TRUE, graph = FALSE) %>%
14.   {data.frame(
15.     Bien = rownames(.$var$contrib),
16.     TyLe = round(.$var$contrib[,1] / sum(.$var$contrib[,1]) * 100, 1)
17.   )} %>%
18.   ggplot(aes(x = "", y = TyLe, fill = Bien)) +
19.   geom_col(width = 1, color = "white") +
20.   coord_polar(theta = "y") +
21.   geom_text(aes(label = paste0(TyLe, "%")),
22.             position = position_stack(vjust = 0.5),
23.             color = "white", size = 5, fontface = "bold") +
24.   scale_fill_brewer(palette = "Pastel1") +
25.   labs(
26.     title = "Tỷ trọng đóng góp vào PCA -\nnhóm Quy mô & Hoạt động tín dụng",
27.     fill = "Chỉ tiêu"
28.   ) +
29.   theme_minimal(base_size = 14) +
30.   theme(plot.title = element_text(hjust = 0.5, face = "bold"),
31.         legend.position = "right")

Ý nghĩa kỹ thuật:

data.frame() tạo bảng chứa tên biến và giá trị đóng góp vào PC1.

mutate() tính tỷ lệ phần trăm đóng góp của từng biến.

ggplot() khởi tạo biểu đồ, ánh xạ biến và tỷ lệ.

geom_col() + coord_polar() tạo biểu đồ tròn thể hiện tỷ trọng đóng góp.

geom_text() hiển thị phần trăm trên các lát biểu đồ.

scale_fill_brewer() chọn bảng màu pastel.

theme() căn giữa, in đậm tiêu đề và đặt chú giải bên phải.

Nhận xét:

Nhóm Quy mô & Hoạt động tín dụng có cơ cấu tương đối cân bằng. Cấp tín dụng cho các TCTD khác chiếm tỷ trọng cao nhất (22,5%), tiếp theo là Lợi nhuận chưa phân phối (22,2%) và Tiền gửi của khách hàng (22%). Hai biến còn lại đóng góp thấp hơn: Tiền gửi & cấp tín dụng cho TCTD khác (20,4%) và Tổng nợ phải trả (12,8%).

8.5 Phân tích thành phần chính (PCA) — Các chỉ tiêu cơ cấu tài sản & thanh khoản

1. nhom2_cocau_thanhkhoan <- d_clean %>%
2.   select(
3.     "Chứng khoán kinh doanh",
4.     "Chứng khoán đầu tư",
5.     "Nguyên giá tài sản cố định",
6.     "Khấu hao tài sản cố định",
7.     "Mua nợ"
8.   )
9. nhom2_cocau_thanhkhoan <- nhom2_cocau_thanhkhoan %>%
10.   mutate(across(everything(), ~ as.numeric(gsub(",", "", .))))
11. pca_nhom2 <- FactoMineR::PCA(nhom2_cocau_thanhkhoan, scale.unit = TRUE, graph = FALSE)
12. contrib_data <- data.frame(
13.   Bien = rownames(pca_nhom2$var$contrib),
14.   DongGop = pca_nhom2$var$contrib[,1] 
15. )
16. contrib_data <- contrib_data %>%
17.   mutate(TyLe = round(DongGop / sum(DongGop) * 100, 1))
18. library(ggplot2)
19. ggplot(contrib_data, aes(x = "", y = TyLe, fill = Bien)) +
20.   geom_col(width = 1, color = "white") +
21.   coord_polar(theta = "y") +
22.   geom_text(aes(label = paste0(TyLe, "%")),
23.             position = position_stack(vjust = 0.5),
24.             color = "white", size = 5, fontface = "bold") +
25.   scale_fill_brewer(palette = "Set2") +
26.   labs(
27.     title = "Tỷ trọng đóng góp PCA -\n nhóm cơ cấu tài sản & thanh khoản",
28.     fill = "Chỉ tiêu"
29.   ) +
30.   theme_minimal(base_size = 14) +
31.   theme(
32.     plot.title = element_text(hjust = 0.5, face = "bold"),
33.     legend.position = "right"
34.   )

Ý nghĩa kỹ thuật:

data.frame() tạo bảng dữ liệu chứa tên biến và giá trị đóng góp của từng biến vào thành phần chính (PC1).

mutate() tính tỷ lệ phần trăm đóng góp của mỗi biến so với tổng đóng góp.

ggplot() khởi tạo biểu đồ, ánh xạ giá trị tỷ lệ (TyLe) theo biến (Bien).

geom_col() và coord_polar() chuyển biểu đồ cột thành biểu đồ tròn thể hiện tỷ trọng.

geom_text() hiển thị nhãn phần trăm trực tiếp trên các lát.

scale_fill_brewer() chọn bảng màu giúp phân biệt các biến rõ hơn.

theme() căn giữa tiêu đề, định dạng chữ và vị trí chú giải cho biểu đồ rõ ràng, cân đối.

Nhận xét:

Nguyên giá TSCĐ đóng góp lớn nhất vào PC1 (36,1%), tiếp đến là Khấu hao TSCĐ (24,8%) và Chứng khoán đầu tư (22,6%). Trong khi đó, Chứng khoán kinh doanh (11,2%) và Mua nợ (5,3%) chỉ đóng góp nhỏ hơn, cho thấy mức ảnh hưởng hạn chế.

8.6 Phân tích tương đối các chỉ tiêu tài chính

8.6.1 Phân tích Hiệu quả huy động & nợ – Tăng trưởng tổng tài sản

1. library(ggplot2); library(scales); library(dplyr)
2. d %>%
3.   mutate(`Tổng tài sản` = as.numeric(gsub(",", "", `Tổng tài sản`))) %>%
4.   ggplot(aes(x = Năm, y = `Tổng tài sản`)) +
5.   geom_line(color = "steelblue", size = 1.2) +
6.   geom_point(color = "darkorange", size = 3) +
7.   geom_text(aes(label = comma(`Tổng tài sản`)), vjust = -0.8, size = 3) +
8.   labs(
9.     title = "Tăng trưởng Tổng tài sản của TCB (2014–2023)",
10.     subtitle = "Đơn vị: Tỷ đồng",
11.     x = "Năm", y = "Tổng tài sản"
12.   ) +
13.   theme_minimal(base_size = 13)

Ý nghĩa kỹ thuật:

mutate(…): chuyển cột Tổng tài sản từ chuỗi có dấu “,” sang dạng số để tính toán.

ggplot(aes(…)): khởi tạo biểu đồ với trục X = Năm, trục Y = Tổng tài sản.

geom_line(): vẽ đường nối thể hiện xu hướng tăng qua các năm.

geom_point(): thêm các điểm đánh dấu từng năm.

geom_text(): hiển thị giá trị cụ thể ngay trên mỗi điểm (dùng comma() để có dấu phẩy ngăn cách hàng nghìn).

labs(): đặt tiêu đề, phụ đề và nhãn trục.

theme_minimal(): chọn giao diện gọn, sáng và dễ đọc.

Nhận xét:

Biểu đồ cho thấy tổng tài sản của TCB tăng mạnh và liên tục trong giai đoạn 2014–2023. Mức tăng rõ rệt hơn từ sau năm 2019, phản ánh quy mô tài sản mở rộng nhanh và năng lực tăng trưởng ổn định của ngân hàng.

8.7 Hiệu quả sử dụng vốn nội bộ giữa các TCTD

1. library(dplyr); library(ggplot2); library(scales)
2. d %>%
3.   mutate(
4.     `Cấp tín dụng cho các TCTD khác` = as.numeric(gsub(",", "", `Cấp tín dụng cho các TCTD khác`)),
5.     `Tiền gửi và cấp tín dụng cho các TCTD khác` = as.numeric(gsub(",", "", `Tiền gửi và cấp tín dụng cho các TCTD khác`)),
6.     `Tỷ lệ sử dụng vốn nội bộ (%)` = (`Cấp tín dụng cho các TCTD khác` / `Tiền gửi và cấp tín dụng cho các TCTD khác`) * 100
7.   ) %>%
8.   ggplot(aes(x = Năm, y = `Tỷ lệ sử dụng vốn nội bộ (%)`)) +
9.   geom_line(color = "steelblue", size = 1.2) +
10.   geom_point(color = "darkorange", size = 3) +
11.   geom_text(aes(label = round(`Tỷ lệ sử dụng vốn nội bộ (%)`, 1)),
12.             vjust = -0.8, size = 3) +
13.   labs(
14.     title = "Hiệu quả sử dụng vốn nội bộ giữa các TCTD (2014–2023)",
15.     subtitle = "Tỷ lệ = Cấp tín dụng / (Tiền gửi và cấp tín dụng cho TCTD khác)",
16.     x = "Năm", y = "Tỷ lệ (%)"
17.   ) +
18.   theme_minimal(base_size = 13)

Ý nghĩa kỹ thuật:

mutate(…): chuyển cột Tổng tài sản từ chuỗi có dấu “,” sang dạng số để tính toán.

ggplot(aes(…)): khởi tạo biểu đồ với trục X = Năm, trục Y = Tổng tài sản.

geom_line(): vẽ đường nối thể hiện xu hướng tăng qua các năm.

geom_point(): thêm các điểm đánh dấu từng năm.

geom_text(): hiển thị giá trị cụ thể ngay trên mỗi điểm (dùng comma() để có dấu phẩy ngăn cách hàng nghìn).

labs(): đặt tiêu đề, phụ đề và nhãn trục.

theme_minimal(): chọn giao diện gọn, sáng và dễ đọc.

Nhận xét:

Tỷ lệ Cấp tín dụng/Tiền gửi & cấp tín dụng cho các TCTD khác biến động mạnh qua các năm, đạt đỉnh năm 2016 (~58%) rồi giảm sâu giai đoạn 2018–2019. Sau đó có phục hồi nhẹ nhưng nhìn chung xu hướng giảm, cho thấy hiệu quả sử dụng vốn nội bộ giữa các TCTD giảm dần trong giai đoạn 2014–2023.

8.8 Cấu trúc danh mục chứng khoán: Tỷ lệ chứng khoán kinh doanh trên chứng khoán đầu tư

1. library(dplyr); library(ggplot2); library(scales)
2. d %>%
3.   mutate(
4.     chung_khoan_kinh_doanh = as.numeric(gsub(",", "", `Chứng khoán kinh doanh`)),
5.     chung_khoan_dau_tu = as.numeric(gsub(",", "", `Chứng khoán đầu tư`)),
6.     `Tỷ lệ cơ cấu danh mục (%)` = (chung_khoan_kinh_doanh / chung_khoan_dau_tu) * 100
7.   ) %>%
8.   ggplot(aes(x = Năm, y = `Tỷ lệ cơ cấu danh mục (%)`)) +
9.   geom_line(color = "darkgreen", size = 1.2) +
10.   geom_point(color = "orange", size = 3) +
11.   geom_text(aes(label = round(`Tỷ lệ cơ cấu danh mục (%)`, 1)),
12.             vjust = -0.8, size = 3) +
13.   labs(
14.     title = "Cơ cấu danh mục chứng khoán của TCB (2014–2023)",
15.     subtitle = "Tỷ lệ = Chứng khoán kinh doanh / Chứng khoán đầu tư",
16.     x = "Năm", y = "Tỷ lệ (%)"
17.   ) +
18.   theme_minimal(base_size = 13) +
19.   theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Ý nghĩa kỹ thuật:

mutate(…): chuyển cột Tổng tài sản từ chuỗi có dấu “,” sang dạng số để tính toán.

ggplot(aes(…)): khởi tạo biểu đồ với trục X = Năm, trục Y = Tổng tài sản.

geom_line(): vẽ đường nối thể hiện xu hướng tăng qua các năm.

geom_point(): thêm các điểm đánh dấu từng năm.

geom_text(): hiển thị giá trị cụ thể ngay trên mỗi điểm (dùng comma() để có dấu phẩy ngăn cách hàng nghìn).

labs(): đặt tiêu đề, phụ đề và nhãn trục.

theme_minimal(): chọn giao diện gọn, sáng và dễ đọc.

Nhận xét:

Tỷ lệ chứng khoán kinh doanh trên chứng khoán đầu tư của TCB biến động mạnh giai đoạn 2014–2023. Sau khi tăng vọt lên 17,6% năm 2015, tỷ lệ này giảm nhanh và dao động không ổn định trong các năm tiếp theo. Từ 2020, xu hướng giảm rõ rệt và duy trì ở mức thấp, cho thấy ngân hàng thu hẹp hoạt động đầu tư ngắn hạn và chuyển hướng sang chiến lược an toàn, ổn định hơn.

8.9 Khả năng tự chủ tài chính: Tỷ lệ lợi nhuận giữ lại so với nợ phải trả.

1. library(dplyr)
2. library(ggplot2)
3. d %>%
4.   mutate(
5.     `Lợi nhuận chưa phân phối` = as.numeric(gsub(",", "", `Lợi nhuận chưa phân phối`)),
6.     `Tổng nợ phải trả` = as.numeric(gsub(",", "", `Tổng nợ phải trả`)),
7.     TyLe = (`Lợi nhuận chưa phân phối` / `Tổng nợ phải trả`) * 100
8.   ) %>%
9.   ggplot(aes(x = Năm, y = TyLe)) +
10.   geom_line(color = "darkred", size = 1.2) +
11.   geom_point(color = "gold", size = 3) +
12.   geom_text(aes(label = sprintf("%.2f%%", TyLe)), vjust = -0.8, size = 3) +
13.   labs(
14.     title = "Khả năng tự chủ tài chính của TCB (2014–2023)",
15.     x = "Năm", y = "Tỷ lệ (%)"
16.   ) +
17.   theme_minimal(base_size = 13) +
18.   theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Ý nghĩa kỹ thuật:

mutate(…): chuyển cột Tổng tài sản từ chuỗi có dấu “,” sang dạng số để tính toán.

ggplot(aes(…)): khởi tạo biểu đồ với trục X = Năm, trục Y = Tổng tài sản.

geom_line(): vẽ đường nối thể hiện xu hướng tăng qua các năm.

geom_point(): thêm các điểm đánh dấu từng năm.

geom_text(): hiển thị giá trị cụ thể ngay trên mỗi điểm (dùng comma() để có dấu phẩy ngăn cách hàng nghìn).

labs(): đặt tiêu đề, phụ đề và nhãn trục.

theme_minimal(): chọn giao diện gọn, sáng và dễ đọc.

Nhận xét:

Tỷ lệ lợi nhuận chưa phân phối trên tổng nợ phải trả của TCB tăng đều trong giai đoạn 2014–2022, từ mức dưới 1% lên đến đỉnh 11,01%, phản ánh khả năng tự chủ tài chính và tích lũy vốn nội bộ ngày càng cải thiện. Tuy nhiên, đến năm 2023, tỷ lệ này giảm còn 6,3%, cho thấy TCB có thể đã sử dụng một phần lợi nhuận tích lũy cho tái đầu tư hoặc chi trả cổ tức, làm giảm mức độ độc lập tài chính so với giai đoạn trước.

8.10 Phân tích tỷ trọng đóng góp của các khoản mục tài sản trong tổng tài sản

1. library(dplyr); library(tidyr); library(ggplot2)
2. tcb_10bien %>%
3.   pivot_longer(-Năm, names_to = "chi_tieu", values_to = "gia_tri") %>%
4.   mutate(gia_tri = as.numeric(gsub("[^0-9.-]", "", gia_tri))) %>%
5.   group_by(Năm) %>%
6.   mutate(ty_trong = gia_tri / sum(gia_tri, na.rm = TRUE) * 100) %>%
7.   ggplot(aes(x = Năm, y = ty_trong, fill = chi_tieu)) +
8.   geom_area(alpha = 0.8) +
9.   theme_minimal(base_size = 13) +
10.   labs(
11.     title = "Tỷ trọng đóng góp của từng chỉ tiêu tài chính TCB theo năm",
12.     x = "Năm",
13.     y = "Tỷ trọng (%)",
14.     fill = "Chỉ tiêu tài chính"
15.   )

Ý nghĩa kỹ thuật:

pivot_longer(): Chuyển dữ liệu từ dạng rộng sang dạng dài để dễ tính toán và vẽ biểu đồ.

gsub(): Loại bỏ ký tự không phải số (như dấu phẩy, chữ, ký hiệu) khỏi dữ liệu giá trị.

mutate(ty_trong = gia_tri / sum(gia_tri, na.rm = TRUE) * 100): Tính tỷ trọng đóng góp (%) của từng chỉ tiêu theo từng năm.

geom_area(): Tạo biểu đồ vùng chồng, thể hiện sự thay đổi tỷ trọng các chỉ tiêu qua các năm.

labs(): Đặt tiêu đề, tên trục và chú thích cho biểu đồ.

Nhận xét: Biểu đồ cho thấy “Tiền gửi của khách hàng” và “Tổng nợ phải trả” chiếm tỷ trọng lớn nhất, khoảng 45–55% tổng tài sản, phản ánh vai trò chủ đạo của nguồn vốn huy động.

Các khoản “Chứng khoán đầu tư” và “Cấp tín dụng cho các TCTD khác” duy trì quanh 10–15%, trong khi các chỉ tiêu khác như “Khấu hao TSCĐ” hay “Mua nợ” chỉ chiếm dưới 5%, cho thấy cơ cấu tài sản TCB ổn định qua các năm. Tổng thể, cơ cấu tài sản TCB giai đoạn này tương đối ổn định, với xu hướng duy trì tập trung vào hoạt động huy động vốn và tín dụng.