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
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. 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. 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ê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. 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. 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. 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. 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. 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()
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. 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()
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. 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. 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.
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.
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.
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ế.
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.
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.
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.
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.
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ơ.
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ê.
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).
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).
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.
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} \]
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.
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.
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.
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.
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.
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.
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ế.
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.
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.
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ể.
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.
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.
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ữ.
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.
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.
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.
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.
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.
1. library(ggplot2)
2. library(dplyr)
3. library(reshape2)
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.
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.
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ể.
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ể.
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ơ.
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ể.
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.
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.
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.
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.
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.
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
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.
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)
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>, …
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!
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
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.
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()
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
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.
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ị.
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.
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")
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.
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.
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.
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.
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.
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).
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ả.
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.
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.
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.
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.
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.
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.
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.
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.
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ư.
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.
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.
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.
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")
| 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.
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")
| 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.
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.
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.
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.
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ế.
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.
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.
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.
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.
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.
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.
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.
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%).
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ế.
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.
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.
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.
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.
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.