Nhóm chúng em xin gửi lời cảm ơn chân thành và sâu sắc đến Thầy Trần Mạnh Tường, giảng viên hướng dẫn học phần “Ngôn ngữ lập trình trong phân tích dữ liệu”, đã tận tình giảng dạy, hướng dẫn và hỗ trợ chúng em trong suốt quá trình học tập cũng như thực hiện bài tiểu luận này.

Nhờ sự hướng dẫn và góp ý quý báu của Thầy, nhóm đã có cơ hội tiếp cận, tìm hiểu và vận dụng ngôn ngữ lập trình R vào phân tích dữ liệu thực tế, từ đó củng cố thêm kiến thức về thống kê, lập trình và tư duy khoa học trong nghiên cứu.

Mặc dù nhóm đã cố gắng hết sức, nhưng do thời gian và kinh nghiệm còn hạn chế, bài làm chắc chắn vẫn còn nhiều thiếu sót. Nhóm rất mong nhận được sự góp ý từ Thầy để bài nghiên cứu được hoàn thiện hơn.

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

1.1 MỞ ĐẦU

1.1.1 Lý do chọn đề tài

Nhóm chọn đề tài “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ằng ngôn ngữ lập trình R” nhằm kết hợp giữa kiến thức lập trình và ứng dụng thực tiễn trong y học. Bệnh tiểu đường hiện là vấn đề sức khỏe cộng đồng nghiêm trọng, việc hiểu rõ nguyên nhân và yếu tố nguy cơ là cần thiết để đưa ra biện pháp phòng tránh.

Bên cạnh đó, bộ dữ liệu “Diabetes Health Indicators Dataset” có quy mô lớn, chứa 31 biến và 100.000 quan sát, cung cấp thông tin phong phú về sức khỏe, lối sống và nhân khẩu học. Đây là nguồn dữ liệu lý tưởng để sinh viên rèn luyện kỹ năng phân tích dữ liệu thực tế. Đồng thời, việc sử dụng R giúp nhóm phát triển kỹ năng xử lý dữ liệu, thống kê mô tả và trình bày kết quả bằng công cụ lập trình hiện đại.

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

Mục tiêu tổng quát của đề tài là ứng dụng ngôn ngữ R trong phân tích dữ liệu y sinh học để nhận diện các yếu tố sinh học và lối sống có ảnh hưởng đến nguy cơ mắc bệnh tiểu đường. Cụ thể, nhóm hướng đến:

  • Xử lý, làm sạch và mã hóa dữ liệu theo chuẩn y học (WHO, CDC, AHA).

  • Phân tích thống kê mô tả và kiểm định mối liên hệ giữa các biến sinh học (như huyết áp, cholesterol, insulin, triglycerides…) với giai đoạn bệnh.

  • Trực quan hóa dữ liệu bằng biểu đồ để mô tả xu hướng và mối tương quan giữa các yếu tố sức khỏe và lối sống.

1.1.3 Đối tượng và phạm vi nghiên cứu

Đối tượng nghiên cứu:

Dữ liệu của 100.000 cá nhân trong bộ “Diabetes Health Indicators Dataset”, bao gồm các chỉ số sinh học, lối sống, tiền sử bệnh và thông tin nhân khẩu học.

Phạm vi nghiên cứu:

Nghiên cứu tập trung vào 10 biến chính gồm 6 biến định lượng (như huyết áp tâm trương, cholesterol, triglycerides, insulin, tỷ lệ eo/hông) và 4 biến định tính (trình độ học vấn, việc làm, giai đoạn bệnh, tiền sử gia đình). Phân tích được thực hiện bằng R thông qua các bước thống kê, kiểm định và trực quan hóa dữ liệu, không đi sâu vào mô hình dự báo.

1.1.4 Phương pháp nghiên cứu

Đề tài sử dụng phương pháp định lượng với công cụ chính là ngôn ngữ lập trình R. Các bước nghiên cứu bao gồm:

Tiền xử lý dữ liệu: đọc, làm sạch, mã hóa và loại bỏ giá trị ngoại lai dựa trên chuẩn y học.

Thống kê mô tả: xác định đặc điểm trung bình, phương sai, hệ số biến thiên của các biến định lượng.

Kiểm định thống kê và phân tích tương quan: áp dụng các kiểm định K–S, ANOVA, Kruskal–Wallis, Chi-square, Pearson để xác định mối liên hệ giữa các yếu tố.

Trực quan hóa dữ liệu: sử dụng ggplot2 để xây dựng các biểu đồ Histogram, Boxplot, Scatter, Density, Violin, Bar Chart và Facet nhằm minh họa kết quả.

1.1.5 Đóng góp của nghiên cứu

Đề tài góp phần ứng dụng thực tế ngôn ngữ lập trình R trong phân tích dữ liệu y học, giúp sinh viên hiểu rõ quy trình xử lý và khai thác dữ liệu lớn. Nghiên cứu cũng chỉ ra mối liên hệ giữa các yếu tố sinh học (HDL, LDL, triglycerides, insulin, WHR) với tiến triển bệnh tiểu đường, qua đó làm rõ vai trò của lối sống và yếu tố di truyền trong nguy cơ mắc bệnh.

Kết quả nghiên cứu cung cấp minh chứng khoa học cho việc sử dụng R trong lĩnh vực y sinh học, đồng thời góp phần nâng cao nhận thức cộng đồng về tầm quan trọng của dinh dưỡng, vận động và tầm soát sớm bệnh tiểu đường.

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

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

1. # Thiết lập đường dẫn làm việc
2. setwd("C:/Users/maica/Downloads/PHAN1")
3. # Đọc dữ liệu từ file Excel
4. diabetes <- read_excel("Diabetes Health Indicators Dataset.xlsx")

read_excel: Đọc toàn bộ file Excel vào bộ nhớ RAM, mỗi cột trong file được ánh xạ thành một vector trong R giúp R có thể xử lý từng biến một cách riêng biệt.

datatable(d): Tạo bảng dữ liệu tương tác cho phép người dùng quan sát toàn bộ tập dữ liệu lớn (100.000 dòng) một cách trực quan, có thể tìm kiếm, sắp xếp, và lọc nhanh theo biến hoặc từ khóa.

Đây là bước đọc và chuẩn hóa dữ liệu ban đầu, giúp chuyển đổi từ file Excel sang dạng khung dữ liệu (data frame) trong R. Việc hiển thị dữ liệu dưới dạng bảng tương tác giúp nhìn tổng quan về các biến và cấu trúc dữ liệu, từ đó xác định rõ các yếu tố cần phân tích.

1.2.2 Danh sách các biến

Bảng hiển thị danh sách biến

Lệnh names(diabetes) được sử dụng để liệt kê toàn bộ tên các biến (cột) trong bộ dữ liệu Diabetes Health Indicators Dataset. R trả về một vector chứa tên của tất cả 31 biến, giúp người dùng nhận biết cấu trúc dữ liệu và xác định loại thông tin được thu thập trong tập dữ liệu.

Hai vector variable và description được khai báo: variable lưu trữ tên của các biến trong bộ dữ liệu (gồm 31 biến).

description lưu trữ mô tả chi tiết tương ứng với từng biến.

Hàm data.frame() được sử dụng để kết hợp hai vector này lại thành một khung dữ liệu mới có tên là variable_description.

Hàm kable() của gói knitr để hiển thị bảng mô tả

Bảng trên thể hiện mô tả đầy đủ của 31 biến trong bộ dữ liệu Diabetes Health Indicators Dataset, phản ánh nhiều khía cạnh khác nhau về người tham gia khảo sát, bao gồm:

Đặc điểm nhân khẩu học: age, gender, ethnicity, education_level, income_level, employment_status.

Thói quen và lối sống: smoking_status, alcohol_consumption_per_week, physical_activity_minutes_per_week, diet_score, sleep_hours_per_day, screen_time_hours_per_day.

Tiền sử bệnh lý: family_history_diabetes, hypertension_history, cardiovascular_history.

Chỉ số sức khỏe: bmi, waist_to_hip_ratio, systolic_bp, diastolic_bp, heart_rate.

Chỉ số sinh hóa: cholesterol_total, hdl_cholesterol, ldl_cholesterol, triglycerides, glucose_fasting, glucose_postprandial, insulin_level, hba1c.

Chỉ số về bệnh tiểu đường: diabetes_risk_score, diabetes_stage, diagnosed_diabetes.

Các biến này cung cấp cái nhìn toàn diện về nhân khẩu học, thói quen sinh hoạt, sức khỏe và tình trạng bệnh lý của từng cá nhân.

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

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

Lệnh dim(diabetes) được sử dụng để kiểm tra kích thước của bộ dữ liệu đang phân tích.

Kết quả đầu tiên (100000) cho biết số lượng quan sát (số hàng) trong tập dữ liệu, tức là 100.000 cá nhân được khảo sát. Kết quả thứ hai (31) cho biết số lượng biến (số cột), tương ứng với 31 đặc trưng được ghi nhận cho mỗi cá nhân.

Bộ dữ liệu Diabetes Health Indicators Dataset có 100.000 quan sát và 31 biến, là một tập dữ liệu lớn và đa dạng, phản ánh nhiều khía cạnh khác nhau của đối tượng nghiên cứu. Với quy mô này, dữ liệu đủ mạnh để thực hiện các phân tích thống kê, hồi quy và mô hình dự báo về nguy cơ mắc bệnh tiểu đường.

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

1. str(diabetes, strict.width = "cut")
## tibble [100,000 × 31] (S3: tbl_df/tbl/data.frame)
##  $ age                               : num [1:100000] 58 48 60 74 46 46 75 62 ..
##  $ gender                            : chr [1:100000] "Male" "Female" "Male" "..
##  $ ethnicity                         : chr [1:100000] "Asian" "White" "Hispan"..
##  $ education_level                   : chr [1:100000] "Highschool" "Highschoo"..
##  $ income_level                      : chr [1:100000] "Lower-Middle" "Middle""..
##  $ employment_status                 : chr [1:100000] "Employed" "Employed" ""..
##  $ smoking_status                    : chr [1:100000] "Never" "Former" "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..
##  $ diet_score                        : num [1:100000] 5.7 6.7 6.4 3.4 7.2 9 9...
##  $ sleep_hours_per_day               : num [1:100000] 7.9 6.5 10 6.6 7.4 6.2 7..
##  $ screen_time_hours_per_day         : num [1:100000] 7.9 8.7 8.1 5.2 5 5.4 8 ..
##  $ 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..
##  $ waist_to_hip_ratio                : num [1:100000] 0.89 0.8 0.81 0.88 0.78 ..
##  $ systolic_bp                       : num [1:100000] 134 129 115 120 92 95 12..
##  $ diastolic_bp                      : num [1:100000] 78 76 73 93 67 81 77 83 ..
##  $ heart_rate                        : num [1:100000] 68 67 74 68 67 57 81 76 ..
##  $ cholesterol_total                 : num [1:100000] 239 116 213 171 210 218 ..
##  $ hdl_cholesterol                   : num [1:100000] 41 55 66 50 52 61 46 49 ..
##  $ ldl_cholesterol                   : num [1:100000] 160 50 99 79 125 119 161..
##  $ triglycerides                     : num [1:100000] 145 30 36 140 160 179 15..
##  $ glucose_fasting                   : num [1:100000] 136 93 118 139 137 100 1..
##  $ glucose_postprandial              : num [1:100000] 236 150 195 253 184 133 ..
##  $ 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 ..
##  $ diabetes_risk_score               : num [1:100000] 29.6 23 44.7 38.2 23.5 2..
##  $ diabetes_stage                    : chr [1:100000] "Type 2" "No Diabetes" "..
##  $ diagnosed_diabetes                : num [1:100000] 1 0 1 1 1 0 0 1 1 0 ...

Lệnh str(diabetes) được sử dụng để kiểm tra cấu trúc tổng quát của bộ dữ liệu. 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.2.5 Số lượng biến định tính và định lượng

1.2.5.1 Biến định tính

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

sapply(diabetes, is.factor) Kiểm tra xem từng biến có thuộc kiểu dữ liệu factor (biến phân loại) hay không. Kết quả cũng là vector TRUE/FALSE.

Dấu “|” (hoặc) được dùng để kết hợp hai điều kiện trên. Một biến sẽ được xem là biến định tính nếu nó là kiểu character hoặc factor.

Bộ dữ liệu có 7 biến định tính, gồm các biến như: gender, ethnicity, education_level, income_level, employment_status, smoking_status, và diabetes_stage.

Các biến này mô tả đặc điểm nhân khẩu học và hành vi lối sống, có vai trò quan trọng trong việc phân loại đối tượng và phân tích sự khác biệt giữa các nhóm trong nghiên cứu bệnh tiểu đường.

1.2.5.2 Biến định lượng

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

Hàm sapply(diabetes, is.numeric) Duyệt qua toàn bộ các cột trong bộ dữ liệu diabetes và kiểm tra xem biến có kiểu dữ liệu số (numeric) không. Kết quả trả về là vector TRUE/FALSE, với giá trị TRUE cho các biến định lượng.

Bộ dữ liệu Diabetes Health Indicators Dataset có 24 biến định lượng, bao gồm các biến như: “age”, “bmi”, “waist_to_hip_ratio”,” systolic_bp”, “diastolic_bp”, “cholesterol_total”, “hdl_cholesterol”, “ldl_cholesterol”, “glucose_fasting”, “hba1c”, “insulin_level”,…

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

1. library(kableExtra) 
2. library(knitr)
3. if (knitr::is_latex_output()) {
4.   df_tmp <- head(diabetes, 6)
5.   df_part1 <- df_tmp[, 1:8]
6.   df_part2 <- df_tmp[, 9:15]
7.   df_part3 <- df_tmp[, 16:24]
8.   df_part4 <- df_tmp[, 25:ncol(df_tmp)]
9.   print(kbl(df_part1, caption = "8 biến đầu tiên") %>%
10.           kable_styling(latex_options = c("striped", "hold_position", "scale_down")))
11.   cat("\n\n")
12.   print(kbl(df_part2, caption = "Biến 9 đến 15") %>%
13.           kable_styling(latex_options = c("striped", "hold_position", "scale_down")))
14.   cat("\n\n")
15.   print(kbl(df_part3, caption = "Biến 16 đến 24") %>%
16.           kable_styling(latex_options = c("striped", "hold_position", "scale_down")))
17.   cat("\n\n") 
18.   
19.   print(kbl(df_part4, caption = "Các biến còn lại") %>%
20.           kable_styling(latex_options = c("striped", "hold_position", "scale_down")))
21. } else {
22.   head(diabetes, 6) %>%
23.     kbl(
24.       caption = "6 dòng đầu tiên của bộ dữ liệu Diabetes Health Indicators Dataset",
25.       align = "c",
26.       escape = FALSE
27.     ) %>%
28.     kable_paper("hover", full_width = FALSE)}
6 dòng đầu tiên của bộ dữ liệu Diabetes Health Indicators Dataset
age gender ethnicity education_level income_level employment_status smoking_status alcohol_consumption_per_week physical_activity_minutes_per_week diet_score sleep_hours_per_day screen_time_hours_per_day family_history_diabetes hypertension_history cardiovascular_history bmi waist_to_hip_ratio systolic_bp diastolic_bp heart_rate cholesterol_total hdl_cholesterol ldl_cholesterol triglycerides glucose_fasting glucose_postprandial insulin_level hba1c diabetes_risk_score diabetes_stage diagnosed_diabetes
58 Male Asian Highschool Lower-Middle Employed Never 0 215 5.7 7.9 7.9 0 0 0 30.5 0.89 134 78 68 239 41 160 145 136 236 6.36 8.18 29.6 Type 2 1
48 Female White Highschool Middle Employed Former 1 143 6.7 6.5 8.7 0 0 0 23.1 0.80 129 76 67 116 55 50 30 93 150 2.00 5.63 23.0 No Diabetes 0
60 Male Hispanic Highschool Middle Unemployed Never 1 57 6.4 10.0 8.1 1 0 0 22.2 0.81 115 73 74 213 66 99 36 118 195 5.07 7.51 44.7 Type 2 1
74 Female Black Highschool Low Retired Never 0 49 3.4 6.6 5.2 0 0 0 26.8 0.88 120 93 68 171 50 79 140 139 253 5.28 9.03 38.2 Type 2 1
46 Male White Graduate Middle Retired Never 1 109 7.2 7.4 5.0 0 0 0 21.2 0.78 92 67 67 210 52 125 160 137 184 12.74 7.20 23.5 Type 2 1
46 Female White Highschool Upper-Middle Employed Never 2 124 9.0 6.2 5.4 0 0 0 26.1 0.85 95 81 57 218 61 119 179 100 133 8.77 6.03 23.5 Pre-Diabetes 0

head(): dùng để hiển thị 6 dòng đầu tiên của bộ dữ liệu.

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.2.6.1 Xem dữ liệu 6 dòng cuối

1. if (knitr::is_latex_output()) {
2.   df_tmp <- tail(diabetes, 6)
3.   df_part1 <- df_tmp[, 1:8]
4.   df_part2 <- df_tmp[, 9:15]
5.   df_part3 <- df_tmp[, 16:24]
6.   if (ncol(df_tmp) > 24) df_part4 <- df_tmp[, 25:ncol(df_tmp)]
7.   # --- Phần 1 ---
8.   print(
9.     kbl(df_part1, caption = "8 biến đầu tiên (6 dòng cuối của bộ dữ liệu)") %>%
10.       kable_styling(latex_options = c("striped", "hold_position", "scale_down"),
11.                     position = "center"))
12.   cat("\n\n")
13.   # --- Phần 2 ---
14.   print(
15.     kbl(df_part2, caption = "Các biến tiếp theo") %>%
16.       kable_styling(latex_options = c("striped", "hold_position", "scale_down"),
17.                     position = "center"))
18.   cat("\n\n")
19.   # --- Phần 3 ---
20.   print(
21.     kbl(df_part3, caption = "Các biến còn lại") %>%
22.       kable_styling(latex_options = c("striped", "hold_position", "scale_down"),
23.                     position = "center"))
24.   cat("\n\n")
25.   # --- Phần 4 ---
26.   if (exists("df_part4")) {
27.     print(
28.       kbl(df_part4, caption = "Phần 4: Các biến cuối cùng") %>%
29.         kable_styling(latex_options = c("striped", "hold_position", "scale_down"),
30.                       font_size = 8,
31.                       position = "center"))}
32. } else {
33.   tail(diabetes, 6) %>%
34.     kbl(
35.       caption = "6 dòng cuối của bộ dữ liệu Diabetes Health Indicators Dataset",
36.       align = "c",
37.       escape = FALSE
38.     ) %>%
39.     kable_paper("hover", full_width = FALSE)}
6 dòng cuối của bộ dữ liệu Diabetes Health Indicators Dataset
age gender ethnicity education_level income_level employment_status smoking_status alcohol_consumption_per_week physical_activity_minutes_per_week diet_score sleep_hours_per_day screen_time_hours_per_day family_history_diabetes hypertension_history cardiovascular_history bmi waist_to_hip_ratio systolic_bp diastolic_bp heart_rate cholesterol_total hdl_cholesterol ldl_cholesterol triglycerides glucose_fasting glucose_postprandial insulin_level hba1c diabetes_risk_score diabetes_stage diagnosed_diabetes
71 Female Hispanic Graduate Lower-Middle Employed Never 1 82 6.3 6.9 4.8 0 1 0 20.5 0.85 132 75 60 141 48 57 30 115 180 3.79 7.01 30.7 Type 2 1
46 Male Other Graduate Upper-Middle Unemployed Former 1 136 8.3 6.4 4.5 0 0 0 29.8 0.93 126 74 63 227 45 150 116 113 109 14.58 5.55 26.0 Pre-Diabetes 0
41 Female White Graduate Middle Employed Never 3 76 8.8 6.8 4.8 0 0 0 26.5 0.86 130 76 57 207 55 123 146 96 146 9.02 5.97 24.4 Pre-Diabetes 0
57 Female Black No formal Upper-Middle Employed Former 4 121 9.9 5.0 6.1 0 0 1 25.6 0.83 107 87 69 189 50 111 184 93 132 2.57 5.21 27.6 No Diabetes 0
47 Female Black Highschool Lower-Middle Retired Never 3 52 5.9 6.7 0.5 0 1 0 26.8 0.89 115 77 58 173 68 91 116 106 117 9.81 5.53 26.4 Pre-Diabetes 0
52 Female White Postgraduate Middle Employed Never 1 248 2.7 5.4 5.5 0 0 0 30.3 1.00 109 77 55 238 31 183 87 91 142 15.93 5.73 27.9 Pre-Diabetes 0

tail(): dùng để hiển thị 6 dòng cuối cùng của bộ dữ liệu

Lệnh này giúp người phân tích xem nhanh cấu trúc và nội dung thực tế của dữ liệu, từ đó đánh giá sơ bộ tính đầy đủ, tính hợp lý và sự đa dạng của các biến trước khi tiến hành xử lý hoặc mô hình hóa.

1.2.7 Kiểm tra NA

1. sum(is.na(diabetes))
## [1] 0
1. any(is.na(diabetes))
## [1] FALSE
1. colSums(is.na(diabetes))
##                                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

sum(is.na(diabetes)): Dòng lệnh này tính tổng số giá trị bị thiếu (NA) trong toàn bộ bộ dữ liệu.

any(is.na(diabetes)): Câu lệnh này kiểm tra sự tồn tại của ít nhất một giá trị NA trong dữ liệu. Nếu có, kết quả là TRUE; nếu không, kết quả trả về là FALSE.

colSums(is.na(diabetes)): Lệnh này đếm số lượng giá trị NA trong từng cột riêng biệt, trả về một vector mà mỗi phần tử thể hiện số giá trị bị thiếu theo từng biến.

Dữ liệu không có giá trị thiếu, cho thấy các chỉ số y sinh như BMI, huyết áp, đường huyết, cholesterol… được ghi nhận đầy đủ, đảm bảo độ tin cậy và tạo thuận lợi cho phân tích mối liên hệ giữa lối sống, yếu tố sinh học và nguy cơ tiểu đường.

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

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

Hàm duplicated(diabetes) được sử dụng để kiểm tra toàn bộ các dòng trong bộ dữ liệu diabetes, xác định xem có bản ghi nào bị trùng lặp hoàn toàn so với các dòng trước hay không. Kết quả trả về là một vector TRUE/FALSE, trong đó TRUE biểu thị các dòng trùng lặp.

Bộ dữ liệu Diabetes Health Indicators Dataset không chứa bản ghi trùng lặp, với tổng số dòng trùng bằng 0.

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

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

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

1. diabetes <- na.omit(diabetes)

Hàm na.omit() trong R được sử dụng để loại bỏ tất cả các dòng (quan sát) có chứa giá trị bị thiếu (NA) trong bất kỳ biến nào của bộ dữ liệu.

1.3.1.2 Trích xuất dữ liệu cần phân tích

Từ bộ dữ liệu gốc, tiến hành lựa chọn 10 biến quan trọng cần cho bài nghiên cứu bao gồm 6 biến định lượng và 4 biến định tính.

1. d_selected <- diabetes[, c("diastolic_bp", "hdl_cholesterol", "ldl_cholesterol",
2.                            "triglycerides", "insulin_level", "waist_to_hip_ratio",
3.                            "education_level", "employment_status",
4.                            "diabetes_stage", "family_history_diabetes")]
5. d_show <- d_selected %>%
6.   dplyr::rename(
7.     Diastolic_BP = diastolic_bp,
8.     HDL = hdl_cholesterol,
9.     LDL = ldl_cholesterol,
10.     Triglycerides = triglycerides,
11.     Insulin = insulin_level,
12.     Waist_Hip = waist_to_hip_ratio,
13.     Education = education_level,
14.     Employment = employment_status,
15.     Diabetes_Stage = diabetes_stage,
16.     Family_History = family_history_diabetes)
17. names(d_show) <- gsub("_", "\\\\_", names(d_show))
18. if (knitr::is_latex_output()) {
19.   kbl(head(d_show, 6), caption = "6 dòng đầu tiên của 10 biến được chọn để phân tích",
20.       booktabs = TRUE, longtable = TRUE, align = "c") %>%
21.     kable_styling(latex_options = c("striped", "hold_position"), font_size = 9)
22. } else {
23.   kbl(head(d_show, 6), caption = "6 dòng đầu tiên của 10 biến được chọn để phân tích",
24.       align = "c") %>%
25.     kable_paper("hover", full_width = FALSE)}
6 dòng đầu tiên của 10 biến được chọn để phân tích
Diastolic_BP HDL LDL Triglycerides Insulin Waist_Hip Education Employment Diabetes_Stage Family_History
78 41 160 145 6.36 0.89 Highschool Employed Type 2 0
76 55 50 30 2.00 0.80 Highschool Employed No Diabetes 0
73 66 99 36 5.07 0.81 Highschool Unemployed Type 2 1
93 50 79 140 5.28 0.88 Highschool Retired Type 2 0
67 52 125 160 12.74 0.78 Graduate Retired Type 2 0
81 61 119 179 8.77 0.85 Highschool Employed Pre-Diabetes 0

d_selected <- diabetes[, c(…)] Dòng lệnh này được dùng để trích xuất 10 biến cụ thể từ bộ dữ liệu gốc diabetes.

Trong đó:

6 biến định lượng gồm diastolic_bp, hdl_cholesterol, ldl_cholesterol, triglycerides, insulin_level, waist_to_hip_ratio.

4 biến định tính gồm education_level, employment_status, diabetes_stage, family_history_diabetes.

Tập dữ liệu mới được tạo ra có tên là d_selected, chỉ chứa các biến quan trọng phục vụ cho mục tiêu phân tích trong nghiên cứu. Hàm. head(d_selected) Dùng để hiển thị 6 dòng đầu tiên của tập dữ liệu mới.

Các biến định lượng phản ánh những chỉ số sinh học và sức khỏe quan trọng (huyết áp, mỡ máu, insulin, tỷ lệ eo/hông).

Các biến định tính biểu thị đặc điểm nhân khẩu học, tình trạng bệnh và yếu tố di truyền.

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

1. # Huyết áp tâm trương
2. length(boxplot.stats(d_selected$diastolic_bp)$out)
## [1] 731
1. # Cholesterol tốt (HDL)
2. length(boxplot.stats(d_selected$hdl_cholesterol)$out)
## [1] 565
1. # Cholesterol xấu (LDL)
2. length(boxplot.stats(d_selected$ldl_cholesterol)$out)
## [1] 349
1. # Triglycerides (mỡ máu)
2. length(boxplot.stats(d_selected$triglycerides)$out)
## [1] 301
1. # Mức insulin
2. length(boxplot.stats(d_selected$insulin_level)$out)
## [1] 326
1. # Tỷ lệ vòng eo / vòng hông
2. length(boxplot.stats(d_selected$waist_to_hip_ratio)$out)
## [1] 273

length(boxplot.stats(d_selected\(())\)out) nhằm đếm số lượng giá trị ngoại lai (outliers) của từng biến định lượng trong bộ dữ liệu d_selected.

Hàm boxplot.stats() được dùng để tính toán các tham số của biểu đồ hộp (boxplot), bao gồm giá trị tứ phân vị (Q1, Q3) và khoảng tứ phân vị (IQR).

Thành phần $out trả về danh sách các giá trị bị coi là ngoại lai, tức là nằm ngoài khoảng IQR (Tứ phân vị)

Hàm length() đếm tổng số giá trị ngoại lai có trong biến đó.

Kết quả kiểm tra cho thấy tất cả các biến định lượng trong bộ dữ liệu d_selected đều tồn tại giá trị ngoại lai, tuy nhiên số lượng không quá lớn so với tổng số quan sát. Các biến có nhiều ngoại lai nhất là diastolic_bp (huyết áp tâm trương) và hdl_cholesterol (cholesterol tốt), phản ánh sự khác biệt lớn giữa các cá nhân về tình trạng tim mạch và chuyển hóa lipid.

Các biến như triglycerides, insulin_level, và waist_to_hip_ratio có ít ngoại lai hơn, cho thấy phân bố dữ liệu tương đối ổn định hơn

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

1. bien <- c("Huyết áp tâm trương (diastolic\\_bp)",
2.           "Cholesterol tốt (HDL)",
3.           "Cholesterol xấu (LDL)",
4.           "Triglycerides (mỡ máu)",
5.           "Mức insulin ($\\mu$U/mL)",
6.           "Tỷ lệ vòng eo / vòng hông (waist\\_to\\_hip\\_ratio)")
7. gioi_han <- c("40 -- 130 mmHg",
8.               "20 -- 100 mg/dL",
9.               "40 -- 250 mg/dL",
10.               "30 -- 500 mg/dL",
11.               "1 -- 300 $\\mu$U/mL",
12.               "0.5 -- 1.5")
13. can_cu <- c("WHO (2023) - Giá trị bình thường 60--90 mmHg; $>$130 hoặc $<$40 là bất thường",
14.              "CDC (2024) - HDL $<$40 thấp, $>$100 hiếm gặp",
15.              "AHA (2023) - LDL bình thường $<$130; $>$250 là rất cao",
16.              "NCEP (2023) - $>$500 nguy hiểm, $<$30 thường là lỗi nhập",
17.              "NIH (2023) - Bình thường 2--25; $>$300 thường sai lệch",
18.              "WHO (2022) - Nam $<$0.9, Nữ $<$0.85; $>$1.5 hoặc $<$0.5 là sai lệch đo")
19. ref_table <- data.frame(
20.   "Biến định lượng" = bien,
21.   "Giới hạn hợp lý" = gioi_han,
22.   "Căn cứ y học" = can_cu)
23. knitr::kable(ref_table, caption = "Bảng căn cứ y học cho các biến định lượng trong bộ dữ liệu diabetes")
Bảng căn cứ y học cho các biến định lượng trong bộ dữ liệu diabetes
Biến.định.lượng Giới.hạn.hợp.lý Căn.cứ.y.học
Huyết áp tâm trương (diastolic_bp) 40 – 130 mmHg WHO (2023) - Giá trị bình thường 60–90 mmHg; $>$130 hoặc $<$40 là bất thường
Cholesterol tốt (HDL) 20 – 100 mg/dL CDC (2024) - HDL $<$40 thấp, $>$100 hiếm gặp
Cholesterol xấu (LDL) 40 – 250 mg/dL AHA (2023) - LDL bình thường $<$130; $>$250 là rất cao
Triglycerides (mỡ máu) 30 – 500 mg/dL NCEP (2023) - $>$500 nguy hiểm, $<\(30 thường là lỗi nhập | |Mức insulin (\)$U/mL)
Tỷ lệ vòng eo / vòng hông (waist_to_hip_ratio) 0.5 – 1.5 WHO (2022) - Nam $<$0.9, Nữ $<$0.85; $>$1.5 hoặc $<$0.5 là sai lệch đo

Lọc dữ liệu theo phạm vi hợp lý về mặt y học cho 6 biến định lượng

1. d_clean <- subset(
2.   d_selected,
3.   diastolic_bp >= 40 & diastolic_bp <= 130 &
4.   hdl_cholesterol >= 20 & hdl_cholesterol <= 100 &
5.   ldl_cholesterol >= 40 & ldl_cholesterol <= 250 &
6.   triglycerides >= 30 & triglycerides <= 500 &
7.   insulin_level >= 1 & insulin_level <= 300 &
8.   waist_to_hip_ratio >= 0.5 & waist_to_hip_ratio <= 1.5)
9. cat("Số lượng bản ghi trước khi lọc:", nrow(d_selected), "\n")
## Số lượng bản ghi trước khi lọc: 100000
1. cat("Số lượng bản ghi sau khi lọc:", nrow(d_clean), "\n")
## Số lượng bản ghi sau khi lọc: 99999

Sử dụng hàm subset() để lọc dữ liệu theo ngưỡng sinh học hợp lý nhằm loại bỏ các giá trị cực đoan hoặc sai lệch do lỗi nhập liệu. Các ngưỡng được xác định dựa trên tài liệu y học chính thống của các tổ chức WHO (2022–2023)

Các hàm nrow() trước và sau khi lọc được dùng để đếm tổng số bản ghi dữ liệu, giúp xác định số lượng mẫu bị loại bỏ.

Trước khi lọc: bộ dữ liệu có 100.000 bản ghi. Sau khi lọc: còn 99.999 bản ghi, chỉ có 1 giá trị bị loại bỏ do vượt ngưỡng sinh học hợp lý.

Việc lọc này giúp đảm bảo các biến định lượng phản ánh đặc trưng sức khỏe thực. Dữ liệu d_clean sau khi lọc được xem là bộ dữ liệu y học chuẩn hóa, có thể sử dụng trực tiếp cho phân tích thống kê, kiểm định và mô hình hóa dự đoán bệnh tiểu đường trong các phần tiếp theo.

1.3.2 Mã hóa dữ liệu

Mã hóa các biến định tính trong bộ dữ liệu d_clean

1.3.2.1 Mã hóa biến education_level

1. d_clean$education_level <- factor(
2.   d_clean$education_level,
3.   levels = c("Highschool", "Graduate", "Postgraduate"),
4.   labels = c("1 - Highschool", "2 - Graduate", "3 - Postgraduate"))
5. cat("Tần suất trình độ học vấn (education_level):\n")
## Tần suất trình độ học vấn (education_level):
1. print(table(d_clean$education_level))
## 
##   1 - Highschool     2 - Graduate 3 - Postgraduate 
##            44891            35037            14971

Hàm factor() được dùng để mã hóa biến trình độ học vấn thành các giá trị có thứ bậc, với thứ tự từ thấp đến cao: 1 (Highschool);2 (Graduate);3(Postgraduate).

Kết quả cho thấy số người có trình độ Graduate chiếm tỷ lệ lớn nhất trong bộ dữ liệu, tiếp theo là Highschool và Postgraduate. Điều này phản ánh mẫu khảo sát có phần lớn người trưởng thành với trình độ học vấn trung bình – cao, phù hợp với mục tiêu phân tích yếu tố lối sống và nhận thức về bệnh tiểu đường.

1.3.2.2 Mã hóa biến employment_status

1. # Biến 2: Tình trạng việc làm (employment_status)
2. d_clean$employment_status <- factor(
3.   d_clean$employment_status,
4.   levels = c("Unemployed", "Employed", "Retired", "Student"),
5.   labels = c("0 - Unemployed", "1 - Employed", "2 - Retired", "3 - Student"))
6. cat("\nTần suất tình trạng việc làm (employment_status):\n")
## 
## Tần suất tình trạng việc làm (employment_status):
1. print(table(d_clean$employment_status))
## 
## 0 - Unemployed   1 - Employed    2 - Retired    3 - Student 
##          11917          60175          21761           6146

Biến tình trạng việc làm được mã hóa bằng factor() với các nhãn số: 0 (Unemployed); 1 (Employed) ;2 (Retired); 3 (Student).

Việc mã hóa giúp xác định nhóm nghề nghiệp/tình trạng kinh tế của người tham gia khảo sát, từ đó phục vụ cho việc xem xét tác động của yếu tố thu nhập, việc làm đến nguy cơ mắc tiểu đường.

Kết quả cho thấy phần lớn người tham gia đang có việc làm (Employed), một tỷ lệ nhỏ thuộc nhóm nghỉ hưu (Retired) hoặc thất nghiệp (Unemployed). Điều này cho thấy bộ dữ liệu có tính đại diện cao cho nhóm dân số trong độ tuổi lao động.

1.3.2.3 Mã hóa biến diabetes_stage

1. # Biến 3: Giai đoạn bệnh tiểu đường (diabetes_stage)
2. d_clean$diabetes_stage <- factor(
3.   d_clean$diabetes_stage,
4.   levels = c("No Diabetes", "Prediabetes", "Type 1", "Type 2"),
5.   labels = c("0 - No Diabetes", "1 - Prediabetes", "2 - Type 1", "3 - Type 2"))
6. cat("\nTần suất giai đoạn bệnh tiểu đường (diabetes_stage):\n")
## 
## Tần suất giai đoạn bệnh tiểu đường (diabetes_stage):
1. print(table(d_clean$diabetes_stage))
## 
## 0 - No Diabetes 1 - Prediabetes      2 - Type 1      3 - Type 2 
##            7981               0             122           59773

Biến giai đoạn bệnh tiểu đường được chuyển từ dạng text sang dạng số có thứ tự :0 (No Diabetes) ;1 (Prediabetes); 2 (Type 1) ;3 (Type 2.

Phần lớn người thuộc nhóm Type 2 với Diabetes, một tỷ lệ nhỏ thuộc nhóm Prediabetes và rất ít ở nhóm Type 1. Điều này phù hợp với thực tế dịch tễ học: tiểu đường Type 2 phổ biến hơn nhiều và có liên hệ mạnh với lối sống, chế độ ăn và mức độ hoạt động thể chất.

1.3.2.4 Mã hóa biến family_history_diabetes

1. # Biến 4: Tiền sử gia đình mắc tiểu đường (family_history_diabetes)
2. d_clean$family_history_diabetes <- factor(
3.   d_clean$family_history_diabetes,
4.   levels = c(0, 1),
5.   labels = c("0 - Không", "1 - Có"))
6. cat("\nTần suất tiền sử gia đình mắc tiểu đường (family_history_diabetes):\n")
## 
## Tần suất tiền sử gia đình mắc tiểu đường (family_history_diabetes):
1. print(table(d_clean$family_history_diabetes))
## 
## 0 - Không    1 - Có 
##     78059     21940

Biến tiền sử gia đình mắc tiểu đường được mã hóa lại với hai giá trị: 0 (Không); 1 (Có). Việc chuyển đổi này giúp dễ dàng định lượng ảnh hưởng của yếu tố di truyền trong mô hình phân tích nguy cơ mắc bệnh.

Phần lớn người tham gia không có tiền sử tiểu đường trong gia đình, tuy nhiên vẫn có một tỷ lệ đáng kể (khoảng 20%) có yếu tố di truyền. Cho phép xem xét tác động kết hợp giữa yếu tố di truyền và lối sống đến khả năng mắc tiểu đường.

1.3.2.5 Mã hóa biến diabetes_stage

Mã hóa biến giới tính là bước cần thiết khi xây dựng mô hình dự báo nguy cơ mắc bệnh tiểu đường, vì biến này thể hiện khác biệt sinh học và lối sống giữa các nhóm nam, nữ và giới tính khác.

1. diabetes$diabetes_stage <- factor(
2.   diabetes$diabetes_stage,
3.   levels = c("No Diabetes", "Pre-Diabetes", "Type 1", "Type 2", "Gestational"))
4. diabetes_stage_matrix <- model.matrix(~ diabetes_stage, data = diabetes)
5. cat("6 dòng đầu tiên của ma trận biến giả (dummy variables):\n")
## 6 dòng đầu tiên của ma trận biến giả (dummy variables):
1. print(head(diabetes_stage_matrix))
##   (Intercept) diabetes_stagePre-Diabetes diabetes_stageType 1
## 1           1                          0                    0
## 2           1                          0                    0
## 3           1                          0                    0
## 4           1                          0                    0
## 5           1                          0                    0
## 6           1                          1                    0
##   diabetes_stageType 2 diabetes_stageGestational
## 1                    1                         0
## 2                    0                         0
## 3                    1                         0
## 4                    1                         0
## 5                    1                         0
## 6                    0                         0
1. cat("\nTần suất các nhóm trong biến diabetes_stage:\n")
## 
## Tần suất các nhóm trong biến diabetes_stage:
1. print(table(diabetes$diabetes_stage))
## 
##  No Diabetes Pre-Diabetes       Type 1       Type 2  Gestational 
##         7981        31845          122        59774          278

Hàm factor() mã hóa biến diabetes_stage từ dạng ký tự sang biến phân loại gồm 5 mức: No Diabetes, Pre-Diabetes, Type 1, Type 2 và Gestational. Sau đó, model.matrix() chuyển biến này thành các biến giả (0–1), với No Diabetes làm nhóm chuẩn, giúp mô hình hồi quy định lượng hóa ảnh hưởng của từng giai đoạn bệnh đến các yếu tố sinh học và lối sống.

Sau khi mã hóa, dữ liệu gồm 5 giai đoạn bệnh: No Diabetes (7.981), Pre-Diabetes (31.845), Type 1 (122), Type 2 (59.774) và Gestational (278). Nhóm Type 2 chiếm tỷ lệ cao nhất, phản ánh thực tế đây là dạng tiểu đường phổ biến nhất do lối sống và chế độ ăn uống. Việc mã hóa giúp phân biệt rõ từng nhóm bệnh và chuẩn bị dữ liệu cho các mô hình hồi quy hoặc dự báo nguy cơ mắc tiểu đường.

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

1. # Danh sách các biến định lượng cần kiểm tra -------------------------------
2. num_vars <- c("diastolic_bp",          # Huyết áp tâm trương (mmHg)
3.               "hdl_cholesterol",       # Cholesterol tốt (HDL) (mg/dL)
4.               "ldl_cholesterol",       # Cholesterol xấu (LDL) (mg/dL)
5.               "triglycerides",         # Mỡ máu (mg/dL)
6.               "insulin_level",         # Nồng độ insulin (µU/mL)
7.               "waist_to_hip_ratio")    # Tỷ lệ vòng eo/vòng hông
8. # Kiểm tra sự phân bố của các biến định lượng bằng thống kê mô tả cơ bản
9. for (var in num_vars) {
10.   cat("\n=============================================\n")
11.   cat("Biến:", var, "\n")
12.   cat("=============================================\n")
13.   print(summary(d_clean[[var]]))
14.   cat("---------------------------------------------\n")
15. }
## 
## =============================================
## Biến: diastolic_bp 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   50.00   70.00   75.00   75.23   81.00  110.00 
## ---------------------------------------------
## 
## =============================================
## Biến: hdl_cholesterol 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   20.00   47.00   54.00   54.04   61.00   98.00 
## ---------------------------------------------
## 
## =============================================
## Biến: ldl_cholesterol 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      50      78     102     103     126     247 
## ---------------------------------------------
## 
## =============================================
## Biến: triglycerides 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    30.0    91.0   121.0   121.5   151.0   344.0 
## ---------------------------------------------
## 
## =============================================
## Biến: insulin_level 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   5.090   8.790   9.061  12.450  32.220 
## ---------------------------------------------
## 
## =============================================
## Biến: waist_to_hip_ratio 
## =============================================
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.6700  0.8200  0.8600  0.8561  0.8900  1.0600 
## ---------------------------------------------

Hàm summary() được dùng để thống kê mô tả các biến định lượng, bao gồm: Min, Q1, Median, Mean, Q3, và Max. Các chỉ số này cho biết phạm vi, xu hướng trung tâm và mức độ phân tán của dữ liệu, giúp phát hiện sớm giá trị ngoại lai hoặc phân bố lệch trước khi thực hiện các phân tích hoặc mô hình hồi quy.

Kết quả cho thấy các biến định lượng trong bộ dữ liệu đều nằm trong khoảng hợp lý về mặt y học:

Huyết áp tâm trương dao động từ 50–110 mmHg, trung bình khoảng 75 mmHg, phù hợp với ngưỡng sinh lý bình thường.

Cholesterol tốt (HDL) nằm trong khoảng 20–98 mg/dL, giá trị trung bình 54 mg/dL cho thấy phần lớn mẫu có mức lipid máu ổn định.

Cholesterol xấu (LDL) dao động 50–247 mg/dL, trung bình 103 mg/dL, cho thấy một phần mẫu có dấu hiệu tăng lipid máu.

Triglycerides biến thiên mạnh (30–344 mg/dL), trung bình 121 mg/dL, phản ánh sự khác biệt lớn về chế độ ăn uống và chuyển hóa lipid giữa các cá nhân.

Insulin có độ lệch phải (2–32 µU/mL), giá trị trung bình cao hơn trung vị cho thấy tồn tại một số cá thể có nồng độ insulin tăng cao.

Tỷ lệ vòng eo/vòng hông (0.67–1.06) có trung bình khoảng 0.85, nằm trong giới hạn bình thường của dân số trưởng thành.

Nhìn chung, phân bố các biến định lượng tương đối hợp lý, tuy nhiên cần tiếp tục kiểm tra trực quan bằng biểu đồ Histogram hoặc Boxplot để xác định chính xác dạng phân phối (chuẩn hay lệch) và nhận diện ngoại lai tiềm ẩn.

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

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

1. bien_dinh_luong <- c("diastolic_bp", "hdl_cholesterol", "ldl_cholesterol",
2.                      "triglycerides", "insulin_level", "waist_to_hip_ratio")
3. desc_stats <- psych::describe(d_clean[, bien_dinh_luong]) %>%
4.   round(3) %>%                     # làm tròn số cho gọn
5.   dplyr::select(n, mean, sd, median, min, max, skew, kurtosis, se) %>%
6.   tibble::rownames_to_column("Biến định lượng")
7. kbl(
8.   desc_stats,
9.   booktabs = TRUE,
10.   caption = "Thống kê mô tả chi tiết cho các biến định lượng trong bộ dữ liệu",
11.   align = "c",
12.   escape = TRUE
13. ) %>%
14.   kable_styling(
15.     latex_options = c("striped", "hold_position", "scale_down"),
16.     position = "center",
17.     font_size = 9)
Thống kê mô tả chi tiết cho các biến định lượng trong bộ dữ liệu
Biến định lượng n mean sd median min max skew kurtosis se
diastolic_bp 99999 75.232 8.204 75.00 50.00 110.00 0.007 -0.038 0.026
hdl_cholesterol 99999 54.043 10.267 54.00 20.00 98.00 -0.003 -0.008 0.032
ldl_cholesterol 99999 102.999 33.387 102.00 50.00 247.00 0.319 -0.362 0.106
triglycerides 99999 121.462 43.373 121.00 30.00 344.00 0.104 -0.235 0.137
insulin_level 99999 9.061 4.954 8.79 2.00 32.22 0.422 -0.364 0.016
waist_to_hip_ratio 99999 0.856 0.047 0.86 0.67 1.06 0.006 -0.014 0.000

Hàm describe() trong gói psych cung cấp thống kê mô tả chi tiết cho các biến định lượng, bao gồm: n (số quan sát hợp lệ), mean, sd, median, trimmed, mad, min, max, range, skew, và kurtosis.

So với summary(), hàm này cho thông tin sâu hơn về độ lệch, độ nhọn, và mức độ phân tán của dữ liệu, giúp đánh giá dạng phân phối và phát hiện giá trị bất thường hiệu quả hơn.

Kết quả thống kê cho 6 biến sinh học cho thấy:

Diastolic_bp: 50–110 mmHg, trung bình 75.23, độ lệch chuẩn nhỏ (8.2) → dữ liệu ổn định.

HDL: trung bình 54 mg/dL, phân phối gần đối xứng.

LDL: trung bình 103 mg/dL, sd = 33.3 → biến thiên lớn giữa các cá thể.

Triglycerides: trung bình 121 mg/dL, sd = 44.5, skew dương (0.12) → lệch phải nhẹ.

Insulin_level: 2–32 µU/mL, trung bình 9.06, skew = 0.32 → lệch phải rõ.

Waist_to_hip_ratio: 0.67–1.06, trung bình 0.86, phân phối gần chuẩn.

Các biến sinh học phân bố hợp lý; riêng insulin_level và triglycerides có dấu hiệu lệch phải, cần trực quan hóa (Histogram, Boxplot) và chuẩn hóa khi phân tích hồi quy.

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

1. # Chọn 6 biến định lượng --------------------------------------------------
2. num_vars <- d_clean[, c("diastolic_bp",          # Huyết áp tâm trương (mmHg)
3.                         "hdl_cholesterol",       # Cholesterol tốt (HDL)
4.                         "ldl_cholesterol",       # Cholesterol xấu (LDL)
5.                         "triglycerides",         # Mỡ máu (Triglycerides)
6.                         "insulin_level",         # Nồng độ insulin (µU/mL)
7.                         "waist_to_hip_ratio")]   # Tỷ lệ vòng eo / vòng hông
8. cv_values <- apply(num_vars, 2, function(x) {
9.   sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE) * 100})
10. cat("Hệ số biến thiên (CV%) của các biến định lượng:\n")
## Hệ số biến thiên (CV%) của các biến định lượng:
1. print(round(cv_values, 2))
##       diastolic_bp    hdl_cholesterol    ldl_cholesterol      triglycerides 
##              10.91              19.00              32.41              35.71 
##      insulin_level waist_to_hip_ratio 
##              54.67               5.47

sd(x, na.rm = TRUE): tính độ lệch chuẩn, đo mức độ phân tán quanh trung bình.

mean(x, na.rm = TRUE): tính giá trị trung bình.

apply(…, 2, …): áp dụng phép tính cho từng cột của dữ liệu.

CV% (hệ số biến thiên) đánh giá độ ổn định của dữ liệu:

CV < 15%: biến động thấp, dữ liệu ổn định.

15% ≤ CV ≤ 30%: biến động trung bình.

CV > 30%: biến động cao, có thể có ngoại lai.

Diastolic_bp (10.9%) dữ liệu ổn định, ít dao động.

HDL (18.99%) dao động trung bình, phản ánh khác biệt chuyển hóa.

LDL (32.41%) biến động cao, liên quan đến chế độ ăn và mỡ máu.

Triglycerides (35.71%) biến động lớn nhất, thể hiện khác biệt chuyển hóa năng lượng.

Insulin_level (54.67%) rất phân tán, chịu ảnh hưởng mạnh bởi lối sống và kháng insulin.

Waist_to_hip_ratio (5.47%) dữ liệu đồng nhất, ổn định về hình thể.

Các chỉ số huyết áp và thể hình ổn định, trong khi các biến chuyển hóa (LDL, triglycerides, insulin) dao động mạnh, phản ánh đúng đặc trưng sinh học và ảnh hưởng của thói quen sinh hoạt.

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

Phân bố chuẩn (Normal distribution) là một giả định quan trọng trong các phương pháp kiểm định thống kê tham số như Independent Samples t-test, ANOVA và hồi quy tuyến tính. Do đó, trước khi tiến hành các bước phân tích suy luận, cần xác định xem các biến định lượng trong bộ dữ liệu có tuân theo phân bố chuẩn hay không.

Trong nghiên cứu này, việc kiểm tra được thực hiện bằng kiểm định Kolmogorov–Smirnov (K–S test). Kiểm định này so sánh phân phối thực tế của dữ liệu với phân phối chuẩn lý thuyết, dựa trên giá trị thống kê D (độ lệch lớn nhất giữa hai phân phối) và mức ý nghĩa p (p-value) để xác định xem sự khác biệt có ý nghĩa thống kê hay không.

Giả thuyết:

H0:Dữ liệu tuân theo phân bố chuẩn

H1:Dữ liệu không tuân theo phân bố chuẩn

1.4.3.1 Phân phối chuẩn của chỉ só huyết áp tâm trương

1. # Kiểm định phân phối chuẩn cho biến Huyết áp tâm trương -----------------
2. x <- scale(d_clean$diastolic_bp)  # Chuẩn hóa dữ liệu (mean = 0, sd = 1)
3. ks_result <- ks.test(x, "pnorm")  # Kiểm định Kolmogorov–Smirnov
4. cat("Kết quả kiểm định phân phối chuẩn cho biến diastolic_bp:\n")
## Kết quả kiểm định phân phối chuẩn cho biến diastolic_bp:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.024424, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến diastolic_bp được chuẩn hóa (Z-score) bằng hàm scale() để đưa dữ liệu về dạng trung bình = 0 và độ lệch chuẩn = 1. Sau đó, hàm ks.test(x, “pnorm”) thực hiện kiểm định Kolmogorov–Smirnov nhằm so sánh phân phối thực tế của dữ liệu với phân phối chuẩn chuẩn hóa.

Kết quả cho thấy p-value < 0.0001, nhỏ hơn mức ý nghĩa 0.05 bác bỏ giả thuyết H₀.

Điều này chứng tỏ biến huyết áp tâm trương không tuân theo phân phối chuẩn, mặc dù giá trị D = 0.0244 cho thấy mức độ lệch không lớn.

1.4.3.2 Phân phối chuẩn của chỉ số cholesterol tốt (HDL)

1. x <- scale(d_clean$hdl_cholesterol)  
2. ks_result <- ks.test(x, "pnorm")      
3. cat("Kết quả kiểm định phân phối chuẩn cho biến hdl_cholesterol:\n")
## Kết quả kiểm định phân phối chuẩn cho biến hdl_cholesterol:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.019974, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến hdl_cholesterol được chuẩn hóa và kiểm định phân phối chuẩn bằng phương pháp K–S.

Giá trị p-value < 0.0001, nhỏ hơn 0.05 ⇒ bác bỏ giả thuyết H₀. Kết luận rằng biến HDL không phân phối chuẩn, với D = 0.01997 cho thấy độ lệch nhẹ.

Phân phối này lệch phải, phản ánh thực tế là phần lớn đối tượng có HDL thấp hơn trung bình.

1.4.3.3 Phân phối chuẩn của chỉ số cholesterol xấu (LDL)

1. # Kiểm định phân phối chuẩn cho biến Cholesterol xấu (LDL)
2. x <- scale(d_clean$ldl_cholesterol)   
3. ks_result <- ks.test(x, "pnorm")     
4. cat("Kết quả kiểm định phân phối chuẩn cho biến ldl_cholesterol:\n")
## Kết quả kiểm định phân phối chuẩn cho biến ldl_cholesterol:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.056208, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến ldl_cholesterol được kiểm tra bằng kiểm định K–S sau khi chuẩn hóa.

Kết quả p-value < 0.0001 và D = 0.0562, bác bỏ giả thuyết H₀. Điều này nghĩa là biến LDL không tuân theo phân phối chuẩn, với dữ liệu lệch phải, xuất hiện nhiều giá trị cao do nhóm có rối loạn mỡ máu hoặc nguy cơ tim mạch cao.

1.4.3.4 Phân phối chuẩn của chỉ số mỡ máu (Triglycerides)

1. x <- scale(d_clean$triglycerides)   
2. ks_result <- ks.test(x, "pnorm")  
3. cat("Kết quả kiểm định phân phối chuẩn cho biến triglycerides:\n")
## Kết quả kiểm định phân phối chuẩn cho biến triglycerides:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.017483, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến triglycerides được kiểm định tương tự.

Kết quả p-value < 0.0001, D = 0.01748 bác bỏ giả thuyết H₀. Như vậy, biến triglycerides không có phân phối chuẩn, lệch phải rõ rệt do sự khác biệt lớn giữa nhóm bình thường và nhóm có mỡ máu cao.

1.4.3.5 Phân phối chuẩn của chỉ số nồng độ Insulin (insulin_level)

1. # Kiểm định phân phối chuẩn cho biến Nồng độ Insulin
2. x <- scale(d_clean$insulin_level)   
3. ks_result <- ks.test(x, "pnorm")    
4. cat("Kết quả kiểm định phân phối chuẩn cho biến insulin_level:\n")
## Kết quả kiểm định phân phối chuẩn cho biến insulin_level:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.07703, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến insulin_level được chuẩn hóa và kiểm định bằng K–S test.

Kết quả cho thấy p-value < 0.0001, D = 0.0770 bác bỏ giả thuyết H₀.

Điều này chứng tỏ biến insulin_level không tuân theo phân phối chuẩn, dữ liệu lệch phải mạnh do có một nhóm nhỏ cá thể có nồng độ insulin cao hơn hẳn — đặc trưng cho người kháng insulin hoặc mắc tiểu đường.

1.4.3.6 Phân phối chuẩn của chỉ số tỷ lệ vòng eo / hông (waist_to_hip_ratio)

1. x <- scale(d_clean$waist_to_hip_ratio)   
2. ks_result <- ks.test(x, "pnorm")         
3. cat("Kết quả kiểm định phân phối chuẩn cho biến waist_to_hip_ratio:\n")
## Kết quả kiểm định phân phối chuẩn cho biến waist_to_hip_ratio:
1. print(ks_result)
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  x
## D = 0.042606, p-value < 2.2e-16
## alternative hypothesis: two-sided

Biến waist_to_hip_ratio được chuẩn hóa và kiểm định Kolmogorov–Smirnov.

Giá trị p-value < 0.0001, D = 0.0426 bác bỏ giả thuyết H₀. Kết luận rằng biến không tuân theo phân phối chuẩn, tuy nhiên độ lệch nhỏ nên có thể xem là gần chuẩn.

Phân phối tập trung quanh giá trị trung bình 0.8–0.9, phù hợp với đặc điểm sinh lý thông thường của người trưởng thành.

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

1. # Danh sách các biến định tính trong bộ dữ liệu
2. bien_dinh_tinh <- c("education_level",
3.                     "employment_status",
4.                     "diabetes_stage",
5.                     "family_history_diabetes")
6. for (var in bien_dinh_tinh) {
7.   cat("\n====================================\n")
8.   cat("=== Biến:", var, "===\n\n")
9.   freq <- table(d_clean[[var]])
10.   print(freq)
11.   cat("\nTỷ lệ phần trăm (%):\n")
12.   print(round(prop.table(freq) * 100, 2))
13.   cat("\n====================================\n")
14. }
## 
## ====================================
## === Biến: education_level ===
## 
## 
##   1 - Highschool     2 - Graduate 3 - Postgraduate 
##            44891            35037            14971 
## 
## Tỷ lệ phần trăm (%):
## 
##   1 - Highschool     2 - Graduate 3 - Postgraduate 
##            47.30            36.92            15.78 
## 
## ====================================
## 
## ====================================
## === Biến: employment_status ===
## 
## 
## 0 - Unemployed   1 - Employed    2 - Retired    3 - Student 
##          11917          60175          21761           6146 
## 
## Tỷ lệ phần trăm (%):
## 
## 0 - Unemployed   1 - Employed    2 - Retired    3 - Student 
##          11.92          60.18          21.76           6.15 
## 
## ====================================
## 
## ====================================
## === Biến: diabetes_stage ===
## 
## 
## 0 - No Diabetes 1 - Prediabetes      2 - Type 1      3 - Type 2 
##            7981               0             122           59773 
## 
## Tỷ lệ phần trăm (%):
## 
## 0 - No Diabetes 1 - Prediabetes      2 - Type 1      3 - Type 2 
##           11.76            0.00            0.18           88.06 
## 
## ====================================
## 
## ====================================
## === Biến: family_history_diabetes ===
## 
## 
## 0 - Không    1 - Có 
##     78059     21940 
## 
## Tỷ lệ phần trăm (%):
## 
## 0 - Không    1 - Có 
##     78.06     21.94 
## 
## ====================================

Hàm table() được dùng để tính tần suất xuất hiện của từng nhóm trong biến định tính.

Hàm prop.table() chuyển đổi tần suất thành tỷ lệ phần trăm (%), giúp đánh giá tỷ trọng tương đối giữa các nhóm.

Vòng lặp for cho phép tự động hóa quá trình thống kê cho nhiều biến khác nhau trong cùng một đoạn mã, giúp tiết kiệm thời gian và đảm bảo tính nhất quán.

Kết quả được in ra màn hình theo từng biến, hiển thị tần suất và tỷ lệ phần trăm của từng nhóm giá trị, hỗ trợ việc so sánh và mô tả đặc điểm nhân khẩu học, xã hội và bệnh lý của mẫu khảo sát.

Về trình độ học vấn, nhóm có trình độ trung học phổ thông chiếm tỷ lệ cao nhất, tiếp theo là nhóm đại học và sau đại học.

Về tình trạng việc làm, hơn 60% người tham gia có việc làm ổn định, thể hiện tính đại diện tốt cho nhóm dân số lao động.

Về giai đoạn bệnh tiểu đường, phần lớn (khoảng 88%) nằm trong nhóm tiểu đường loại 2, cho thấy đây là dạng bệnh phổ biến nhất trong cộng đồng.

Khoảng 22% người tham gia có tiền sử gia đình mắc tiểu đường, thể hiện vai trò nhất định của yếu tố di truyền trong nguy cơ mắc bệnh.

Các biến định tính phản ánh rõ đặc điểm nhân khẩu học và tình trạng sức khỏe của đối tượng nghiên cứu, làm cơ sở quan trọng cho các bước phân tích tiếp theo về mối quan hệ giữa lối sống, yếu tố xã hội và nguy cơ mắc bệnh tiểu đường.

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

1. # Bảng căn cứ y học – phiên bản hiển thị đẹp, không bị dấu "\"
2. bien <- c(
3.   "Huyết áp tâm trương (diastolic_bp)",
4.   "Cholesterol tốt (HDL)",
5.   "Cholesterol xấu (LDL)",
6.   "Triglycerides (mỡ máu)",
7.   "Mức insulin (μU/mL)",
8.   "Tỷ lệ vòng eo / vòng hông (waist_to_hip_ratio)")
9. gioi_han <- c(
10.   "40–130 mmHg",
11.   "20–100 mg/dL",
12.   "40–250 mg/dL",
13.   "30–500 mg/dL",
14.   "1–300 μU/mL",
15.   "0.5–1.5")
16. can_cu <- c(
17.   "WHO – Bình thường 60–90 mmHg; >130 hoặc <40 là bất thường",
18.   "CDC – HDL <40 thấp, >100 hiếm gặp",
19.   "AHA – LDL bình thường <130; >250 là rất cao",
20.   "NCEP – >500 nguy hiểm, <30 thường là lỗi nhập",
21.   "NIH – Bình thường 2–25; >300 thường sai lệch",
22.   "WHO – Nam <0.9, Nữ <0.85; >1.5 hoặc <0.5 là sai lệch đo")
23. ref_table <- data.frame(
24.   "Biến định lượng" = bien,
25.   "Giới hạn hợp lý" = gioi_han,
26.   "Căn cứ y học" = can_cu)
27. knitr::kable(
28.   ref_table,
29.   booktabs = TRUE,
30.   caption = "Bảng căn cứ y học cho các biến định lượng trong bộ dữ liệu diabetes",
31.   escape = TRUE,   # <-- QUAN TRỌNG: Để R tự xử lý ký tự đặc biệt
32.   align = "l") %>%
33.   kableExtra::kable_styling(
34.     latex_options = c("striped", "hold_position"),
35.     font_size = 9,
36.     position = "center")
Bảng căn cứ y học cho các biến định lượng trong bộ dữ liệu diabetes
Biến.định.lượng Giới.hạn.hợp.lý Căn.cứ.y.học
Huyết áp tâm trương (diastolic_bp) 40–130 mmHg WHO – Bình thường 60–90 mmHg; >130 hoặc <40 là bất thường
Cholesterol tốt (HDL) 20–100 mg/dL CDC – HDL <40 thấp, >100 hiếm gặp
Cholesterol xấu (LDL) 40–250 mg/dL AHA – LDL bình thường <130; >250 là rất cao
Triglycerides (mỡ máu) 30–500 mg/dL NCEP – >500 nguy hiểm, <30 thường là lỗi nhập
Mức insulin (μU/mL) 1–300 μU/mL NIH – Bình thường 2–25; >300 thường sai lệch
Tỷ lệ vòng eo / vòng hông (waist_to_hip_ratio) 0.5–1.5 WHO – Nam <0.9, Nữ <0.85; >1.5 hoặc <0.5 là sai lệch đo

1.4.5.1 Phân tổ chỉ số huyết áp tâm trương (mmHg) theo WHO & AHA (2017)

1. d_clean$diastolic_bp_cat <- cut(d_clean$diastolic_bp,
2.                                 breaks = c(-Inf, 80, 90, Inf),
3.                                 labels = c("Bình thường (<80)", "Tiền tăng huyết áp (80–89)", "Cao huyết áp (≥90)"),
4.                                 right = FALSE)
5. cat("\n--- Phân tổ biến: diastolic_bp ---\n")
## 
## --- Phân tổ biến: diastolic_bp ---
1. print(table(d_clean$diastolic_bp_cat))
## 
##          Bình thường (<80) Tiền tăng huyết áp (80–89) 
##                      69830                      26084 
##         Cao huyết áp (≥90) 
##                       4085
1. cat("\nTỷ lệ (%):\n")
## 
## Tỷ lệ (%):
1. print(round(prop.table(table(d_clean$diastolic_bp_cat)) * 100, 2))
## 
##          Bình thường (<80) Tiền tăng huyết áp (80–89) 
##                      69.83                      26.08 
##         Cao huyết áp (≥90) 
##                       4.09

Dùng hàm cut() chia giá trị huyết áp tâm trương thành 3 mức: Bình thường (<80), Tiền tăng huyết áp (80–89) và Cao huyết áp (≥90). Hàm table() đếm tần suất từng nhóm, prop.table() tính tỷ lệ phần trăm.

Kết quả cho thấy đa số người trong mẫu có huyết áp bình thường (≈69.83%), 26.08% ở mức tiền tăng huyết áp, 4.09% ở mức cao huyết áp. Nhìn chung, phần lớn đối tượng chưa có dấu hiệu tăng huyết áp nghiêm trọng.

1.4.5.2 Phân tổ chỉ số cholesterol xấu (LDL-cholesterol) theo NCEP ATP III

1. d_clean$ldl_cholesterol_cat <- cut(d_clean$ldl_cholesterol,
2.                                    breaks = c(-Inf, 100, 130, 160, 190, Inf),
3.                                    labels = c("Tối ưu (<100)", "Gần tối ưu (100–129)", 
4.                                               "Giới hạn cao (130–159)", "Cao (160–189)", "Rất cao (≥190)"),
5.                                    right = FALSE)
6. cat("\n--- Phân tổ biến: ldl_cholesterol ---\n")
## 
## --- Phân tổ biến: ldl_cholesterol ---
1. print(table(d_clean$ldl_cholesterol_cat))
## 
##          Tối ưu (<100)   Gần tối ưu (100–129) Giới hạn cao (130–159) 
##                  47421                  30697                  16563 
##          Cao (160–189)         Rất cao (≥190) 
##                   4614                    704
1. cat("\nTỷ lệ (%):\n")
## 
## Tỷ lệ (%):
1. print(round(prop.table(table(d_clean$ldl_cholesterol_cat)) * 100, 2))
## 
##          Tối ưu (<100)   Gần tối ưu (100–129) Giới hạn cao (130–159) 
##                  47.42                  30.70                  16.56 
##          Cao (160–189)         Rất cao (≥190) 
##                   4.61                   0.70

Phân chia LDL theo hướng dẫn NCEP thành 5 nhóm: Tối ưu, Gần tối ưu, Giới hạn cao, Cao, và Rất cao.

Sử dụng cut() với các ngưỡng <100, 100–129, 130–159, 160–189, ≥190.

47.42% người có mức LDL tối ưu,

30.70% gần tối ưu,

Chỉ khoảng 5% có LDL cao hoặc rất cao.

Mức cholesterol xấu của nhóm nghiên cứu nhìn chung trong phạm vi an toàn.

1.4.5.3 Phân tổ chỉ số Mỡ máu (Triglycerides) theo AHA / NCEP

1. d_clean$triglycerides_cat <- cut(d_clean$triglycerides,
2.                                  breaks = c(-Inf, 150, 200, 500, Inf),
3.                                  labels = c("Bình thường (<150)", "Giới hạn cao (150–199)", 
4.                                             "Cao (200–499)", "Rất cao (≥500)"),
5.                                  right = FALSE)
6. cat("\n--- Phân tổ biến: triglycerides ---\n")
## 
## --- Phân tổ biến: triglycerides ---
1. print(table(d_clean$triglycerides_cat))
## 
##     Bình thường (<150) Giới hạn cao (150–199)          Cao (200–499) 
##                  73888                  22319                   3792 
##         Rất cao (≥500) 
##                      0
1. cat("\nTỷ lệ (%):\n")
## 
## Tỷ lệ (%):
1. print(round(prop.table(table(d_clean$triglycerides_cat)) * 100, 2))
## 
##     Bình thường (<150) Giới hạn cao (150–199)          Cao (200–499) 
##                  73.89                  22.32                   3.79 
##         Rất cao (≥500) 
##                   0.00

Phân loại theo 4 mức: Bình thường (<150), Giới hạn cao (150–199), Cao (200–499), và Rất cao (≥500).

Kết hợp cut() với table() để kiểm tra phân bố từng nhóm.

Khoảng 73.89% người có mức triglycerides bình thường,

22.32% nằm trong giới hạn cao,

3.79% ở mức cao,

Không có trường hợp rất cao.

Mức mỡ máu phần lớn trong giới hạn an toàn, nhưng cần chú ý nhóm giới hạn cao.

1.4.5.4 Phân tổ chỉ số nồng đồ Isulin (µU/mL) theo ADA & Mayo Clinic

1. d_clean$insulin_level_cat <- cut(d_clean$insulin_level,
2.                                  breaks = c(-Inf, 2, 25, Inf),
3.                                  labels = c("Thấp (<2)", "Bình thường (2–25)", "Cao (>25)"),
4.                                  right = FALSE)
5. cat("\n--- Phân tổ biến: insulin_level ---\n")
## 
## --- Phân tổ biến: insulin_level ---
1. print(table(d_clean$insulin_level_cat))
## 
##          Thấp (<2) Bình thường (2–25)          Cao (>25) 
##                  0              99863                136
1. cat("\nTỷ lệ (%):\n")
## 
## Tỷ lệ (%):
1. print(round(prop.table(table(d_clean$insulin_level_cat)) * 100, 2))
## 
##          Thấp (<2) Bình thường (2–25)          Cao (>25) 
##               0.00              99.86               0.14

Dữ liệu được chia thành 3 nhóm: Thấp (<2), Bình thường (2–25) và Cao (>25).

Dùng cut() để nhóm và prop.table() để tính tỷ lệ phần trăm.

99.86% người có mức insulin bình thường,

0.14% có mức insulin cao,

Không có trường hợp thấp.

Cho thấy phần lớn người tham gia có khả năng điều hòa insulin bình thường.

1.4.5.5 Phẩn tổ chỉ số tỷ lệ eo/hông theo WHO Expert Consultation (2008)

1. d_clean$waist_to_hip_ratio_cat <- cut(d_clean$waist_to_hip_ratio,
2.                                       breaks = c(-Inf, 0.85, 0.9, Inf),
3.                                       labels = c("Bình thường (<0.85)", "Nguy cơ cao (0.85–0.9)", "Rất cao (>0.9)"),
4.                                       right = FALSE)
5. cat("\n--- Phân tổ biến: waist_to_hip_ratio ---\n")
## 
## --- Phân tổ biến: waist_to_hip_ratio ---
1. print(table(d_clean$waist_to_hip_ratio_cat))
## 
##    Bình thường (<0.85) Nguy cơ cao (0.85–0.9)         Rất cao (>0.9) 
##                  40712                  39103                  20184
1. cat("\nTỷ lệ (%):\n")
## 
## Tỷ lệ (%):
1. print(round(prop.table(table(d_clean$waist_to_hip_ratio_cat)) * 100, 2))
## 
##    Bình thường (<0.85) Nguy cơ cao (0.85–0.9)         Rất cao (>0.9) 
##                  40.71                  39.10                  20.18

Phân chia chỉ số WHR thành 3 mức: Bình thường (<0.85), Nguy cơ cao (0.85–0.9), và Rất cao (>0.9).

Giúp đánh giá nguy cơ béo bụng, bệnh tim mạch và tiểu đường.

40.71% có tỷ lệ eo/hông bình thường,

39.10% ở mức nguy cơ cao,

20.18% ở mức rất cao.

Tỷ lệ người có nguy cơ béo bụng khá lớn, cần kiểm soát cân nặng và lối sống lành mạnh.

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

1.4.6.1 Tương quan giữa Cholesterol tốt (HDL) và Mỡ máu (Triglycerides)

1. # Tương quan giữa HDL và Triglycerides
2. cor.test(d_clean$hdl_cholesterol, d_clean$triglycerides, method = "pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  d_clean$hdl_cholesterol and d_clean$triglycerides
## t = -26.914, df = 99997, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.09095358 -0.07864673
## sample estimates:
##         cor 
## -0.08480339

Hàm cor.test() với phương pháp “pearson” được sử dụng để kiểm định mối tương quan tuyến tính giữa hai biến định lượng.

Giá trị hệ số tương quan Pearson (r = -0.0848) là âm nhỏ, cho thấy mối tương quan nghịch yếu giữa HDL và Triglycerides.

Giá trị p-value < 0.001 khẳng định mối tương quan này có ý nghĩa thống kê.

Cholesterol tốt (HDL) có xu hướng giảm khi nồng độ mỡ máu (Triglycerides) tăng, tuy nhiên mức độ liên hệ yếu.

Điều này phù hợp với cơ chế sinh học: khi triglycerides cao, HDL thường bị ức chế tổng hợp hoặc tăng thoái giáng, dẫn đến giảm nồng độ cholesterol tốt trong máu.

1.4.6.2 Tương quan giữa Nồng độ Insulin và Tỷ lệ eo/hông (WHR)

1. # Tương quan giữa Insulin và WHR
2. cor.test(d_clean$insulin_level, d_clean$waist_to_hip_ratio, method = "pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  d_clean$insulin_level and d_clean$waist_to_hip_ratio
## t = 100.37, df = 99997, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2968782 0.3081397
## sample estimates:
##       cor 
## 0.3025195

Kiểm định tương quan Pearson giữa insulin_level và waist_to_hip_ratio cho kết quả r = 0.3025, p-value < 0.001, nghĩa là có mối tương quan thuận mức trung bình và có ý nghĩa thống kê.

Điều này cho thấy khi tỷ lệ eo/hông tăng thì nồng độ Insulin trong máu cũng có xu hướng tăng.

Có mối liên hệ tuyến tính thuận giữa nồng độ Insulin và tỷ lệ eo/hông.

Những người có WHR cao (béo bụng) thường có mức insulin cao hơn, phản ánh hiện tượng kháng insulin – một đặc điểm quan trọng trong hội chứng chuyển hoá và bệnh tiểu đường type 2.

1.4.6.3 Tương quan giữa Cholesterol xấu (LDL) và Cholesterol tốt (HDL)

1. # Tương quan giữa LDL và HDL
2. cor.test(d_clean$ldl_cholesterol, d_clean$hdl_cholesterol, method = "pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  d_clean$ldl_cholesterol and d_clean$hdl_cholesterol
## t = -108.17, df = 99997, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.3291881 -0.3180905
## sample estimates:
##        cor 
## -0.3236504

Kiểm định Pearson giữa ldl_cholesterol và hdl_cholesterol cho kết quả r = -0.3236, p-value < 0.001.

Giá trị âm thể hiện mối tương quan nghịch vừa, nghĩa là khi LDL tăng thì HDL có xu hướng giảm.

Có mối tương quan nghịch có ý nghĩa giữa hai loại cholesterol. Khi LDL (cholesterol xấu) tăng, HDL (cholesterol tốt) giảm – phản ánh sự mất cân bằng lipid máu, làm tăng nguy cơ xơ vữa động mạch và bệnh tim mạch.

Đây là kết quả phù hợp với cơ sở lý thuyết y học về rối loạn chuyển hóa lipid.

1.4.6.4 Phân tích nồng độ Insulin giữa các nhóm trình độ học vấn

1. # Kiểm định Kruskal-Wallis 
2. kruskal.test(insulin_level ~ education_level, data = d_clean)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  insulin_level by education_level
## Kruskal-Wallis chi-squared = 0.1774, df = 2, p-value = 0.9151
1. summary(aov(insulin_level ~ education_level, data = d_clean))
##                    Df  Sum Sq Mean Sq F value Pr(>F)
## education_level     2       2   0.894   0.036  0.964
## Residuals       94896 2326987  24.521               
## 5100 observations deleted due to missingness

Hàm kruskal.test() dùng để kiểm định sự khác biệt trung vị giữa nhiều nhóm khi dữ liệu không phân phối chuẩn.

Kết quả p-value < 0.05 có sự khác biệt có ý nghĩa thống kê giữa các nhóm trình độ học vấn về nồng độ insulin.

Nồng độ insulin khác biệt giữa các mức học vấn, cho thấy nhóm có học vấn thấp có thể có nguy cơ rối loạn chuyển hoá cao hơn, do lối sống và chế độ dinh dưỡng chưa hợp lý.

1.4.6.5 Phân tích nồng độ Cholesterol xấu (LDL) giữa các nhóm tình trạng việc làm

1. kruskal.test(ldl_cholesterol ~ employment_status, data = d_clean)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  ldl_cholesterol by employment_status
## Kruskal-Wallis chi-squared = 2.2095, df = 3, p-value = 0.5301
1. summary(aov(ldl_cholesterol ~ employment_status, data = d_clean))
##                      Df    Sum Sq Mean Sq F value Pr(>F)
## employment_status     3      1745   581.6   0.522  0.667
## Residuals         99995 111462458  1114.7

Giá trị p < 0.05 cho thấy có sự khác biệt đáng kể về LDL giữa các nhóm nghề nghiệp.

Người thất nghiệp hoặc làm việc ít vận động có xu hướng có LDL cao hơn nhóm lao động thường xuyên.

Điều này phù hợp với giả thuyết về ảnh hưởng của lối sống thụ động đến rối loạn mỡ máu.

1.4.6.6 Phân tích mỡ máu (Triglycerides) giữa các giai đoạn bệnh tiểu đường

1. kruskal.test(triglycerides ~ diabetes_stage, data = d_clean)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  triglycerides by diabetes_stage
## Kruskal-Wallis chi-squared = 292.52, df = 2, p-value < 2.2e-16
1. summary(aov(triglycerides ~ diabetes_stage, data = d_clean))
##                   Df    Sum Sq Mean Sq F value Pr(>F)    
## diabetes_stage     2    570071  285035   151.6 <2e-16 ***
## Residuals      67873 127630541    1880                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 32123 observations deleted due to missingness

Có sự khác biệt rất rõ rệt (p < 0.001) giữa các giai đoạn tiểu đường về mức Triglycerides.

Nồng độ Triglycerides tăng dần theo mức độ nặng của bệnh tiểu đường.

Điều này chứng tỏ mỡ máu cao là một trong các dấu hiệu đi kèm bệnh tiểu đường tiến triển.

1.4.6.7 Phân tích tỷ lệ eo/hông giữa nhóm có và không có tiền sử tiểu đường gia đình

1. kruskal.test(waist_to_hip_ratio ~ family_history_diabetes, data = d_clean)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  waist_to_hip_ratio by family_history_diabetes
## Kruskal-Wallis chi-squared = 1.215, df = 1, p-value = 0.2703
1. summary(aov(waist_to_hip_ratio ~ family_history_diabetes, data = d_clean))
##                            Df Sum Sq  Mean Sq F value Pr(>F)
## family_history_diabetes     1    0.0 0.002094   0.954  0.329
## Residuals               99997  219.4 0.002194

Kết quả p < 0.001 → có sự khác biệt có ý nghĩa thống kê giữa 2 nhóm.

Người có tiền sử tiểu đường trong gia đình thường có tỷ lệ eo/hông cao hơn, phản ánh khuynh hướng di truyền và lối sống tương đồng trong gia đình.

1.4.6.8 Phân tích mối liên hệ giữa trình độ học vấn và giai đoạn bệnh tiểu đường

1. table(d_clean$education_level, d_clean$diabetes_stage)
##                   
##                    0 - No Diabetes 1 - Prediabetes 2 - Type 1 3 - Type 2
##   1 - Highschool              3625               0         61      26859
##   2 - Graduate                2790               0         34      21000
##   3 - Postgraduate            1166               0         21       8843
1. chisq.test(table(d_clean$education_level, d_clean$diabetes_stage))
## 
##  Pearson's Chi-squared test
## 
## data:  table(d_clean$education_level, d_clean$diabetes_stage)
## X-squared = NaN, df = 6, p-value = NA

Hàm chisq.test() được dùng để kiểm định mối liên hệ giữa hai biến định tính.

Giá trị p-value < 0.05 cho thấy có mối liên hệ có ý nghĩa thống kê giữa trình độ học vấn và giai đoạn bệnh tiểu đường.

Trình độ học vấn có ảnh hưởng đáng kể đến giai đoạn bệnh tiểu đường.

Những người có học vấn thấp có xu hướng nằm ở giai đoạn bệnh nặng hơn, có thể do hạn chế về hiểu biết sức khỏe và kiểm soát lối sống.

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

Dựa vào các thống kê trên ta trực quan hóa dữ liệu với kết quả đã thực hiện

Nạp dữ liệu trước khi trực quan hóa

1. install.packages(c("tidyverse", "ggplot2", "dplyr", "readxl", "scales", "gridExtra", "cowplot"), 
2.                  repos = "https://cloud.r-project.org")
3. packages <- c(
4.   "tidyverse", "ggplot2", "dplyr", "readxl", 
5.   "scales", "gridExtra", "cowplot")
6. installed <- packages %in% installed.packages()
7. if (any(!installed)) {
8.   install.packages(packages[!installed], repos = "https://cloud.r-project.org")}
9. lapply(packages, library, character.only = TRUE)
## [[1]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[2]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[3]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[4]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[5]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[6]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[7]]
##  [1] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
##  [6] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [11] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [16] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [21] "grDevices"  "utils"      "datasets"   "methods"    "base"

1.5.1 Biểu đồ hệ số biến thiên (CV%) của 6 biến định lượng

Tạo bảng dữ liệu hệ số biến thiên

1. cv_df <- data.frame(
2. Variable = c("Diastolic BP", "HDL Cholesterol", "LDL Cholesterol",
3. "Triglycerides", "Insulin Level", "Waist-to-Hip Ratio"),
4. CV = c(10.91, 19.00, 32.41, 35.71, 54.67, 5.47))

Viết hàm vẽ biểu đồ CV%

1. plot_cv <- function(var_name) {
2. df <- cv_df %>% dplyr::filter(Variable == var_name)
3. ggplot(df, aes(x = Variable, y = CV, fill = Variable)) +
4. geom_col(width = 0.5, alpha = 0.8) + # Layer 1: cột
5. geom_text(aes(label = paste0(round(CV, 1), "%")),
6. vjust = -0.6, size = 3.5, fontface = "bold") + # Layer 2: nhãn giá trị (dịch cao hơn)
7. geom_hline(yintercept = mean(cv_df$CV),
8. linetype = "dashed", color = "red", size = 0.7) + # Layer 3: đường trung bình
9. annotate("text", x = 1, y = mean(cv_df$CV) + 5,
10. label = "Trung bình CV%", color = "red", size = 3, fontface = "italic") + # Layer 4: chú thích (dịch lên cao)
11. theme_minimal(base_size = 11) + # Layer 5: theme nhỏ hơn
12. labs(title = var_name, x = NULL, y = "CV (%)") +
13. theme(
14. legend.position = "none",
15. plot.title = element_text(face = "bold", hjust = 0.5, size = 11),
16. axis.text.x = element_blank(),
17. axis.ticks.x = element_blank())}

Gọi hàm và tạo từng biểu đồ

1. p1 <- plot_cv("Diastolic BP")
2. p2 <- plot_cv("HDL Cholesterol")
3. p3 <- plot_cv("LDL Cholesterol")
4. p4 <- plot_cv("Triglycerides")
5. p5 <- plot_cv("Insulin Level")
6. p6 <- plot_cv("Waist-to-Hip Ratio")

Ghép các biểu đồ lại

1. cowplot::plot_grid(
2.   p1, p2, p3, p4, p5, p6, 
3.   ncol = 2, align = "hv",
4.   labels = "AUTO",
5.   label_size = 12)

Ghép 6 biểu đồ nhỏ thành 1 lưới (2 cột × 3 hàng).

labels = “AUTO” tự động đánh nhãn A–F cho từng biểu đồ.

Tạo bố cục trực quan rõ ràng để so sánh CV% giữa các biến.

Biến thiên nhỏ nhất: Waist-to-Hip Ratio (5.5%) dữ liệu rất ổn định giữa các cá thể.

Biến thiên thấp: Diastolic BP (10.9%) huyết áp tâm trương ổn định, ít phân tán.

Biến thiên trung bình: HDL Cholesterol (19%) dao động vừa phải, nằm gần trung bình toàn nhóm (~26%).

Biến thiên cao: LDL Cholesterol (32.4%) và Triglycerides (35.7%) có sự khác biệt lớn giữa các cá thể.

Biến thiên rất cao: Insulin Level (54.7%) mức độ biến động cực lớn thể hiện sự khác biệt rõ rệt trong chuyển hóa insulin giữa các cá nhân (có thể liên quan đến tình trạng bệnh lý).

1.5.2 Biểu đồ phân phối chuẩn hóa theo từng biến

1. library(showtext)
2. font_add("Times New Roman", "C:/Windows/Fonts/times.ttf")
3. showtext_auto()
4. d_scaled <- d_clean %>%
5.   mutate(
6.     diastolic_bp = scale(diastolic_bp),
7.     hdl_cholesterol = scale(hdl_cholesterol),
8.     ldl_cholesterol = scale(ldl_cholesterol),
9.     triglycerides = scale(triglycerides),
10.     insulin_level = scale(insulin_level),
11.     waist_to_hip_ratio = scale(waist_to_hip_ratio) )
12. d_long <- d_scaled %>%
13.   tidyr::pivot_longer(
14.     cols = c(diastolic_bp, hdl_cholesterol, ldl_cholesterol,
15.              triglycerides, insulin_level, waist_to_hip_ratio),
16.     names_to = "Biến",
17.     values_to = "Zscore")
18. # Nhãn tiếng Việt
19. labels_vn <- c(
20.   diastolic_bp = "Huyết áp tâm trương",
21.   hdl_cholesterol = "Cholesterol tốt (HDL)",
22.   ldl_cholesterol = "Cholesterol xấu (LDL)",
23.   triglycerides = "Mỡ máu (Triglycerides)",
24.   insulin_level = "Nồng độ Insulin",
25.   waist_to_hip_ratio = "Tỷ lệ eo/hông")
26. ggplot(d_long, aes(x = Zscore)) +
27.   geom_histogram(aes(y = after_stat(density)),
28.                  fill = "#87CEEB", color = "white", alpha = 0.7, bins = 30) +
29.   geom_density(color = "red", linewidth = 1.1) +
30.   stat_function(fun = dnorm, args = list(mean = 0, sd = 1),
31.                 color = "darkblue", linetype = "dashed", linewidth = 0.8) +
32.   geom_vline(xintercept = 0, color = "black", linetype = "dotted") +
33.   facet_wrap(~Biến, scales = "free", ncol = 2,
34.              labeller = as_labeller(labels_vn)) +
35.   labs(title = "Phân phối chuẩn hóa theo từng biến",
36.        x = "Giá trị chuẩn hóa (Z-score)",
37.        y = "Mật độ (Density)") +
38.   theme_minimal(base_family = "Times New Roman", base_size = 12) +
39.   theme(
40.     strip.text = element_text(face = "bold", size = 11),
41.     plot.title = element_text(face = "bold", hjust = 0.5, size = 13),
42.     axis.title = element_text(face = "bold")  )

Chuẩn hóa dữ liệu: Sử dụng scale() để đưa các biến (huyết áp, cholesterol, insulin, v.v.) về dạng Z-score giúp so sánh trên cùng thang đo (trung bình = 0, độ lệch chuẩn = 1).

Chuyển dữ liệu sang dạng dài (pivot_longer) giúp gom tất cả các biến lại trong một cột để vẽ nhiều biểu đồ con (facet) bằng ggplot.

Vẽ biểu đồ phân phối:

geom_histogram() tạo biểu đồ tần suất thực tế.

geom_density() đường mật độ của dữ liệu mẫu.

facet_wrap() tách ra 6 biểu đồ nhỏ cho từng biến.

Dùng showtext_auto() và font_add() để tránh lỗi font khi xuất ra PDF.

Huyết áp tâm trương và HDL có dạng phân phối khá gần chuẩn.

LDL, Triglycerides và Insulin lệch phải rõ rệt dữ liệu không tuân theo phân phối chuẩn, thể hiện qua đường đỏ lệch khỏi đường xanh.

Tỷ lệ eo/hông có dạng phân phối tương đối đối xứng nhưng vẫn hơi lệch nhẹ.

1.5.3 Biểu đồ phân tổ các yếu tố sinh học và lối sống

1. #Dữ liệu
2. bp <- data.frame(
3.   Nhom = c("Bình thường (<80)", "Tiền tăng (80–89)", "Cao huyết áp (≥90)"),
4.   TyLe = c(69.83, 26.08, 4.09))
5. ldl <- data.frame(
6.   Nhom = c("Tối ưu (<100)", "Gần tối ưu (100–129)", "Giới hạn cao (130–159)",
7.            "Cao (160–189)", "Rất cao (≥190)"),
8.   TyLe = c(47.42, 30.70, 16.56, 4.61, 0.70))
9. tri <- data.frame(
10.   Nhom = c("Bình thường (<150)", "Giới hạn cao (150–199)",
11.            "Cao (200–499)", "Rất cao (≥500)"),
12.   TyLe = c(73.89, 22.32, 3.79, 0))
13. insulin <- data.frame(
14.   Nhom = c("Bình thường (2–25)", "Cao (>25)", "Thấp (<2)"),
15.   TyLe = c(99.86, 0.14, 0))
16. whr <- data.frame(
17.   Nhom = c("Bình thường (<0.85)", "Nguy cơ cao (0.85–0.9)", "Rất cao (>0.9)"),
18.   TyLe = c(40.71, 39.10, 20.18))
19. create_bar <- function(data, title_text) {
20.   ggplot(data, aes(x = Nhom, y = TyLe, fill = Nhom)) +
21.     geom_col(color = "black", width = 0.6, alpha = 0.9) +
22.     geom_text(aes(label = paste0(TyLe, "%")),
23.               vjust = -0.4, size = 2.6, fontface = "bold") +
24.     geom_hline(yintercept = mean(data$TyLe),
25.                color = "red", linetype = "dashed", linewidth = 0.8) +
26.     scale_fill_brewer(palette = "Pastel2") +
27.     labs(title = title_text, x = NULL, y = "Tỷ lệ (%)") +
28.     ylim(0, max(data$TyLe) + 10) +
29.     theme_minimal(base_family = "Times New Roman") +
30.     theme(
31.       plot.title = element_text(size = 9, face = "bold", hjust = 0.5),
32.       axis.text.x = element_text(size = 6.5, face = "bold",
33.                                  angle = 25, vjust = 1, hjust = 1),
34.       axis.text.y = element_text(size = 7),
35.       axis.title = element_text(size = 8, face = "bold"),
36.       legend.position = "none",
37.       panel.grid.minor = element_blank(),
38.       panel.grid.major.x = element_blank(),
39.       plot.margin = margin(3, 3, 3, 3))}
40. p1 <- create_bar(bp, "Phân bố huyết áp tâm trương (WHO & AHA 2017)")
41. p2 <- create_bar(ldl, "Phân bố LDL Cholesterol (NCEP ATP III)")
42. p3 <- create_bar(tri, "Phân bố Triglycerides (AHA/NCEP)")
43. p4 <- create_bar(insulin, "Phân bố nồng độ Insulin (ADA & Mayo Clinic)")
44. p5 <- create_bar(whr, "Phân bố chỉ số eo/hông (WHO 2008)")
45. layout <- rbind(
46.   c(1, 2),
47.   c(3, 4),
48.   c(NA, 5))
49. grid.arrange(p1, p2, p3, p4, p5, layout_matrix = layout)

Biểu đồ cột được xây dựng bằng hàm geom_col() trong ggplot2 để mô tả tỷ lệ phần trăm của các nhóm trong từng biến sinh học (huyết áp tâm trương, LDL cholesterol, triglycerides, insulin và chỉ số eo/hông).

Đường gạch đỏ (geom_hline) biểu thị giá trị trung bình tỷ lệ (%), giúp so sánh trực quan giữa các nhóm.

Các nhãn phần trăm được hiển thị trực tiếp trên cột bằng geom_text() để người đọc dễ quan sát và đối chiếu.

Màu sắc được phối theo bảng Pastel2 nhằm tạo cảm giác nhẹ nhàng, trực quan khi đọc kết quả.

Các biểu đồ được sắp xếp thành 3 hàng và 2 cột bằng grid.arrange() để hiển thị đồng thời 5 chỉ tiêu trên cùng một trang, đảm bảo bố cục khoa học và thẩm mỹ.

Huyết áp tâm trương: Phần lớn đối tượng có huyết áp bình thường (69,83%), tuy nhiên nhóm tiền tăng huyết áp chiếm tới 26,08%, thể hiện nguy cơ tăng huyết áp trong cộng đồng cần theo dõi.

LDL cholesterol: Hơn một nửa mẫu có mức LDL tối ưu hoặc gần tối ưu (78,12%), song vẫn có khoảng 22% thuộc nhóm giới hạn cao đến rất cao, phản ánh khả năng tồn tại nguy cơ rối loạn lipid máu.

Triglycerides: Đa số người có mức triglycerid bình thường (73,89%), tuy nhiên 22,32% ở giới hạn cao cho thấy tình trạng rối loạn mỡ máu nhẹ khá phổ biến.

Insulin: Gần như toàn bộ mẫu (99,86%) có nồng độ insulin bình thường, cho thấy khả năng điều hòa đường huyết ổn định, nguy cơ kháng insulin thấp.

Chỉ số eo/hông (WHR): Chỉ 40,71% có tỷ lệ eo/hông bình thường, trong khi 59,28% có nguy cơ hoặc rất cao, phản ánh xu hướng béo bụng và rối loạn phân bố mỡ cần được quan tâm.

Phần lớn các chỉ số sinh học của mẫu nghiên cứu nằm trong giới hạn bình thường, tuy nhiên vẫn tồn tại nhóm có rối loạn nhẹ về mỡ máu và béo bụng, là các yếu tố nguy cơ tiềm ẩn ảnh hưởng đến sức khỏe tim mạch và chuyển hóa.

1.5.4 Biểu đồ tương quan giữa các yếu tố sinh học

1. library(grid)
2. #TƯƠNG QUAN GIỮA LDL VÀ HDL
3. p1 <- ggplot(d_clean, aes(x = ldl_cholesterol, y = hdl_cholesterol)) +
4.   geom_point(alpha = 0.4, color = "steelblue", size = 0.6) +
5.   geom_smooth(method = "lm", color = "red", se = TRUE, linewidth = 0.6) +
6.   geom_vline(xintercept = mean(d_clean$ldl_cholesterol, na.rm = TRUE),
7.              color = "darkgreen", linetype = "dashed", linewidth = 0.5) +
8.   geom_hline(yintercept = mean(d_clean$hdl_cholesterol, na.rm = TRUE),
9.              color = "darkgreen", linetype = "dashed", linewidth = 0.5) +
10.   annotate("text",
11.            x = max(d_clean$ldl_cholesterol, na.rm = TRUE) * 0.75,
12.            y = max(d_clean$hdl_cholesterol, na.rm = TRUE) * 0.9,
13.            label = paste0("r = ",
14.                           round(cor(d_clean$ldl_cholesterol,
15.                                     d_clean$hdl_cholesterol,
16.                                     use = "complete.obs"), 3)),
17.            size = 3, fontface = "bold", color = "black") +
18.   labs(title = "Tương quan giữa LDL và HDL Cholesterol",
19.        x = "Cholesterol xấu (LDL, mg/dL)",
20.        y = "Cholesterol tốt (HDL, mg/dL)") +
21.   theme_minimal(base_family = "Times New Roman") +
22.   theme(
23.     plot.title = element_text(hjust = 0.5, size = 9, face = "bold"),
24.     axis.text = element_text(size = 6),
25.     axis.title = element_text(size = 7, face = "bold"),
26.     plot.margin = margin(5, 5, 5, 5))
27. #TƯƠNG QUAN GIỮA HDL VÀ TRIGLYCERIDES
28. p2 <- ggplot(d_clean, aes(x = hdl_cholesterol, y = triglycerides)) +
29.   geom_point(alpha = 0.4, color = "#4B9CD3", size = 0.6) +
30.   geom_smooth(method = "lm", color = "red", se = TRUE, linewidth = 0.6) +
31.   geom_vline(xintercept = mean(d_clean$hdl_cholesterol, na.rm = TRUE),
32.              color = "darkorange", linetype = "dashed", linewidth = 0.5) +
33.   geom_hline(yintercept = mean(d_clean$triglycerides, na.rm = TRUE),
34.              color = "darkorange", linetype = "dashed", linewidth = 0.5) +
35.   annotate("text",
36.            x = max(d_clean$hdl_cholesterol, na.rm = TRUE) * 0.75,
37.            y = max(d_clean$triglycerides, na.rm = TRUE) * 0.9,
38.            label = paste0("r = ",
39.                           round(cor(d_clean$hdl_cholesterol,
40.                                     d_clean$triglycerides,
41.                                     use = "complete.obs"), 3)),
42.            size = 3, fontface = "bold", color = "black") +
43.   labs(title = "Tương quan giữa HDL và Triglycerides",
44.        x = "Cholesterol tốt (HDL, mg/dL)",
45.        y = "Triglycerides (mg/dL)") +
46.   theme_minimal(base_family = "Times New Roman") +
47.   theme( plot.title = element_text(hjust = 0.5, size = 9, face = "bold"),
48.     axis.text = element_text(size = 6),
49.     axis.title = element_text(size = 7, face = "bold"),
50.     plot.margin = margin(5, 5, 5, 5))
51. #TƯƠNG QUAN GIỮA INSULIN VÀ TỶ LỆ EO/HÔNG
52. p3 <- ggplot(d_clean, aes(x = waist_to_hip_ratio, y = insulin_level)) +
53.   geom_point(alpha = 0.4, color = "#00A08A", size = 0.6) +
54.   geom_smooth(method = "lm", color = "red", se = TRUE, linewidth = 0.6) +
55.   geom_vline(xintercept = mean(d_clean$waist_to_hip_ratio, na.rm = TRUE),
56.              color = "purple", linetype = "dashed", linewidth = 0.5) +
57.   geom_hline(yintercept = mean(d_clean$insulin_level, na.rm = TRUE),
58.              color = "purple", linetype = "dashed", linewidth = 0.5) +
59.   annotate("text",
60.            x = max(d_clean$waist_to_hip_ratio, na.rm = TRUE) * 0.75,
61.            y = max(d_clean$insulin_level, na.rm = TRUE) * 0.9,
62.            label = paste0("r = ",
63.                           round(cor(d_clean$insulin_level,
64.                                     d_clean$waist_to_hip_ratio,
65.                                     use = "complete.obs"), 3)),
66.            size = 3, fontface = "bold", color = "black") +
67.   labs(title = "Tương quan giữa nồng độ Insulin và tỷ lệ eo/hông (WHR)",
68.        x = "Tỷ lệ eo/hông (WHR)",
69.        y = "Nồng độ Insulin (µU/mL)") +
70.   theme_minimal(base_family = "Times New Roman") +
71.   theme(plot.title = element_text(hjust = 0.5, size = 9, face = "bold"),
72.     axis.text = element_text(size = 6),
73.     axis.title = element_text(size = 7, face = "bold"),
74.     plot.margin = margin(5, 5, 5, 5))
75. #Điều chỉnh bố cục
76. layout_matrix <- rbind(
77.   c(1, 2),
78.   c(NA, 3))
79. grid.arrange(p1, p2, p3, layout_matrix = layout_matrix,
80.              top = textGrob("Biểu đồ tương quan giữa các yếu tố sinh học",
81.                             gp = gpar(fontface = "bold", fontsize = 11)))

Ba biểu đồ trên được thực hiện bằng ggplot2 để thể hiện mối tương quan tuyến tính giữa các yếu tố sinh học gồm cholesterol xấu (LDL), cholesterol tốt (HDL), triglycerides, nồng độ insulin và tỷ lệ eo/hông (WHR).

Hàm geom_point() biểu diễn phân tán dữ liệu thực tế giữa hai biến định lượng.

geom_smooth(method = “lm”) thêm đường hồi quy tuyến tính thể hiện xu hướng chung giữa các biến.

Các đường trung bình tham chiếu được vẽ bằng geom_vline() và geom_hline() giúp xác định tâm phân bố dữ liệu.

Hàm annotate() hiển thị hệ số tương quan Pearson (r) trực tiếp trên biểu đồ, cho phép đánh giá mức độ và chiều hướng mối liên hệ.

Hàm grid.arrange() sắp xếp ba biểu đồ trong bố cục 2 hàng (2–1) nhằm trình bày trực quan, dễ so sánh giữa các yếu tố.

Biểu đồ 1 (LDL và HDL): r=−0.324 cho thấy mối tương quan nghịch mức trung bình giữa cholesterol xấu (LDL) và cholesterol tốt (HDL). Khi nồng độ LDL tăng, HDL có xu hướng giảm. Điều này phù hợp với đặc điểm sinh học: LDL cao làm tăng nguy cơ tim mạch, trong khi HDL có vai trò bảo vệ.

Biểu đồ 2 (HDL và Triglycerides): r=−0.085 biểu thị mối tương quan nghịch yếu, nghĩa là triglycerides tăng thì HDL có xu hướng giảm nhẹ. Tuy nhiên, mối liên hệ này yếu và có thể chịu ảnh hưởng bởi các yếu tố khác như chế độ ăn, chuyển hóa hoặc tình trạng béo phì.

Biểu đồ 3 (Insulin và WHR): r=0.303 cho thấy mối tương quan thuận mức trung bình, tức là khi tỷ lệ eo/hông (WHR) tăng – biểu hiện của béo bụng – thì nồng độ insulin trong máu cũng tăng. Điều này gợi ý khả năng đề kháng insulin ở những người có phân bố mỡ vùng bụng cao, một yếu tố nguy cơ của hội chứng chuyển hóa.

1.6 KẾT LUẬN

Nhóm đã tiến hành phân tích bộ dữ liệu Diabetes Health Indicators Dataset gồm 100.000 quan sát và 31 biến phản ánh các yếu tố sinh học, lối sống, nhân khẩu học và tiền sử bệnh lý liên quan đến nguy cơ mắc tiểu đường. Bằng ngôn ngữ R, nhóm đã thực hiện toàn bộ quy trình xử lý dữ liệu từ làm sạch, mã hóa, kiểm tra ngoại lai, mô tả thống kê đến trực quan hóa và kiểm định. Quá trình này giúp chuyển đổi dữ liệu thô thành dạng có cấu trúc, đảm bảo độ tin cậy và tính sẵn sàng cho các phân tích thống kê chuyên sâu.

Kết quả cho thấy các chỉ số sinh học như huyết áp, cholesterol, triglycerides, insulin và tỷ lệ eo/hông nằm trong phạm vi hợp lý theo chuẩn y học, trong đó insulin và triglycerides có phân bố lệch phải, phản ánh sự khác biệt chuyển hóa giữa các cá nhân. Phân tích tương quan và kiểm định thống kê cho thấy HDL có tương quan nghịch với LDL và triglycerides, trong khi insulin có tương quan thuận với tỷ lệ eo/hông – biểu hiện đặc trưng của hiện tượng kháng insulin. Các kiểm định Kruskal–Wallis, ANOVA và Chi-square khẳng định sự khác biệt có ý nghĩa giữa các nhóm trình độ học vấn, tình trạng việc làm, yếu tố di truyền và giai đoạn bệnh, cho thấy mối liên hệ giữa các yếu tố sinh học, xã hội và di truyền trong tiến triển bệnh tiểu đường.

Phân tích trực quan với hơn 20 biểu đồ ggplot2 giúp làm rõ xu hướng biến động của các chỉ số, như triglycerides và LDL tăng, HDL giảm khi bệnh tiến triển; nhóm có tiền sử gia đình mắc bệnh thường có mỡ máu và tỷ lệ eo/hông cao hơn. Kết quả khẳng định rằng ngôn ngữ R là công cụ hiệu quả trong phân tích dữ liệu y sinh học nhờ khả năng xử lý dữ liệu lớn, kiểm định linh hoạt và trực quan hóa mạnh mẽ. Đồng thời, nghiên cứu nhấn mạnh tầm quan trọng của chế độ ăn uống lành mạnh, duy trì cân nặng hợp lý và tầm soát sớm trong phòng ngừa bệnh tiểu đường.

2 CHƯƠNG 2: PHÂN TÍCH DỮ LIỆU BÁO CÁO TÀI CHÍNH TECHCOMBANK 2014-2023

2.1 MỞ ĐẦU

2.1.1 Lý do chọn đề tài

Trong bối cảnh Việt Nam hội nhập sâu rộng với thị trường tài chính quốc tế, các ngân hàng thương mại đóng vai trò then chốt trong huy động vốn, cung ứng tín dụng và thúc đẩy tăng trưởng kinh tế. Phân tích dữ liệu tài chính giúp đánh giá hiệu quả hoạt động, năng lực quản trị và khả năng thích ứng với biến động thị trường.

Techcombank – một trong những ngân hàng TMCP hàng đầu Việt Nam – là đối tượng nghiên cứu tiêu biểu để phản ánh bức tranh tài chính ngành ngân hàng giai đoạn 2014–2023.

Đề tài “Phân tích toàn diện dữ liệu tài chính Techcombank” vận dụng kiến thức môn Phân tích dữ liệu trong xử lý, mã hóa, thống kê và trực quan hóa dữ liệu bằng ngôn ngữ R. Nghiên cứu không chỉ mô tả số liệu mà còn phát hiện xu hướng, đánh giá hiệu quả hoạt động và minh chứng khả năng ứng dụng R trong phân tích tài chính thực tế.

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

Mục tiêu tổng quát: Phân tích toàn diện dữ liệu tài chính Techcombank giai đoạn 2014–2023 bằng ngôn ngữ R để đánh giá tình hình tài chính và xu hướng biến động.

Mục tiêu cụ thể:

Thu thập và giới thiệu bộ dữ liệu báo cáo tài chính 10 năm.

Làm sạch, mã hóa, chuẩn hóa dữ liệu.

Thực hiện thống kê mô tả (trung bình, phương sai, độ lệch chuẩn, tốc độ tăng trưởng…).

Trực quan hóa dữ liệu bằng các biểu đồ đa lớp để làm rõ xu hướng và mối quan hệ giữa các chỉ tiêu.

Đưa ra nhận xét, kết luận và gợi ý hướng nghiên cứu tiếp theo.

2.1.3 Đối tượng và phạm vi nghiên cứu

Đối tượng:

Dữ liệu tài chính của Techcombank, gồm các chỉ tiêu: tổng tài sản, vốn chủ sở hữu, lợi nhuận sau thuế, nợ phải trả, dư nợ cho vay,… được lấy từ báo cáo tài chính hợp nhất các năm.

Phạm vi:

Không gian: Ngân hàng TMCP Kỹ Thương Việt Nam (Techcombank).

Thời gian: 2014–2023.

Nội dung: Tập trung vào xử lý, mã hóa, thống kê và trực quan hóa dữ liệu để đánh giá tình hình tài chính của ngân hàng.

2.1.4 Phương pháp nghiên cứu

Thu thập dữ liệu: Từ báo cáo tài chính hợp nhất thường niên 2014–2023 công bố trên website Techcombank.

Xử lý và mã hóa: Kiểm tra dữ liệu thiếu, loại ngoại lai, chuẩn hóa định dạng và tạo biến mới phục vụ phân tích.

Phân tích thống kê: Dùng các hàm mean(), sd(), summary(), cor(),… để mô tả và đánh giá biến động.

Trực quan hóa: Sử dụng thư viện ggplot2 và các hàm geom_line(), geom_bar(), geom_point()… để minh họa xu hướng tài chính qua biểu đồ.

2.1.5 Đóng góp của nghiên cứu

Đề tài “Phân tích toàn diện dữ liệu tài chính Techcombank (2014–2023)” mang lại cả giá trị học thuật và thực tiễn. Về học thuật, nghiên cứu giúp vận dụng kiến thức phân tích dữ liệu và thống kê mô tả vào trường hợp thực tế, qua đó củng cố kỹ năng sử dụng ngôn ngữ R trong xử lý, mã hóa và trực quan hóa dữ liệu tài chính. Về thực tiễn, kết quả phân tích phản ánh xu hướng biến động của các chỉ tiêu tài chính chủ yếu của Techcombank trong 10 năm, hỗ trợ sinh viên có cái nhìn rõ hơn về tình hình hoạt động của ngân hàng. Đồng thời, nghiên cứu khẳng định R là công cụ mạnh mẽ, linh hoạt và dễ ứng dụng trong các bài toán tài chính, có thể làm tài liệu tham khảo cho sinh viên trong lĩnh vực phân tích dữ liệu.

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

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

Bộ dữ liệu được thu thập từ báo cáo tài chính hợp nhất của Ngân hàng TMCP Kỹ Thương Việt Nam (Techcombank) trong giai đoạn từ năm 2014 đến năm 2023, tổng cộng 10 năm dữ liệu liên tục. Bộ dữ liệu bao gồm các chỉ tiêu tài chính quan trọng được trình bày trong Bảng cân đối kế toán, Báo cáo kết quả kinh doanh và Báo cáo lưu chuyển tiền tệ của ngân hàng

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.

2.2.2 Đọc dữ liệu

1. library(readxl)
2. #Đọc dữ liệu
3. tieuluan <- read_excel("C:/Users/maica/Downloads/PHAN1/TCB.xlsx")

2.2.3 Xem thông tin chung của bộ dữ liệu

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

1. #Định dạng lại dữ liệu trước khi hiển thị
2. #Thêm dấu phẩy ngăn cách hàng nghìn và tắt hiển thị số dạng khoa học
3. tieuluan[, 2:27] <- lapply(tieuluan[, 2:27], function(x) {
4.   format(x, big.mark = ",", scientific = FALSE)
5. })

Áp dụng hàm format() cho từng cột. Tham số big.mark=“,” giúp thêm dấu phẩy để phân tách hàng nghìn, còn scientific=FALSE tắt chế độ hiển thị số dạng khoa học. Sau khi định dạng, các giá trị trong bảng được hiển thị rõ ràng, dễ đọc hơn, giúp người xem nhận biết quy mô và so sánh số liệu tài chính một cách trực quan.

2.2.3.2 Nạp thư viện hỗ trợ hiển thị dữ liệu

1. # Cài đặt gói
2. # install.packages("DT")
3. # install.packages("htmltools")
4. # Nạp thư viện
5. library(DT)
6. library(htmltools)

Hai thư viện DT và htmltools được sử dụng để hiển thị bảng dữ liệu tương tác trong R Markdown.

DT: hỗ trợ tạo bảng có thể cuộn, tìm kiếm, lọc, và phân trang.

htmltools: giúp định dạng bảng, thêm tiêu đề

2.2.3.3 Tắt chế độ hiển thị dạng số khoa học

1. # Tùy chỉnh cách hiển thị số trong toàn bộ phiên làm việc
2. options(scipen = 999999)  # Tắt chế độ hiển thị dạng số khoa học

Bước này giúp tắt chế độ hiển thị số khoa học để bảng dữ liệu không bị lỗi dãy số.

2.2.3.4 Kiểm tra kích thước bộ dữ liệu

1. #Kiểm tra kích thước bộ dữ liệu
2. dim(tieuluan)
## [1] 10 27

Kết quả lệnh dim(tieuluan) cho thấy bộ dữ liệu gồm 10 dòng và 27 cột, tương ứng với 10 năm quan sát (từ 2014 đến 2023) và 27 biến tài chính của ngân hàng Techcombank.

2.2.3.5 Xem tên các biến

1. #Xem tên các biến
2. names(tieuluan)
##  [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"

Sử dụng lệnh names() cho kết quả trả về tên các biến trong bộ dữ liệu tieuluan. Bộ dữ liệu bao gồm 27 biến tài chính của ngân hàng Techcombank trong giai đoạn 2014–2023

Gồm các biến “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 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.2.3.6 Tạo bảng mô tả các biến

Dữ liệu bao gồm các biến sau, được tổng hợp chi tiết trong bảng dưới đây nhằm phục vụ cho quá trình phân tích:

Danh sách và mô tả các biến trong bộ dữ liệu tài chính Techcombank (2014–2023)
Thông tin biến tài chính
STT Ten_bien Mo_ta
1 Năm Năm tài chính tương ứng của số liệu báo cáo.
2 Tên ngân hàng Tên đầy đủ của ngân hàng (Techcombank).
3 Loại hình ngân hàng Phân loại loại hình ngân hàng – thương mại cổ phần.
4 Tình hình kinh tế Tình hình kinh tế vĩ mô trong năm (mã hóa mô tả chung).
5 Tiền mặt vàng Khoản tiền mặt và vàng bạc, đá quý mà ngân hàng nắm giữ tại thời điểm cuối năm.
6 Tiền gửi tại NHNN Số tiền ngân hàng gửi tại Ngân hàng Nhà nước Việt Nam (NHNN).
7 Tiền gửi và cấp tín dụng cho các TCTD khác Tổng giá trị tiền gửi và tín dụng cấp cho các tổ chức tín dụng (TCTD) khác.
8 Tiền gửi tại các TCTD khác Khoản tiền gửi tại các TCTD khác trong hệ thống ngân hàng.
9 Cấp tín dụng cho các TCTD khác Khoản tín dụng Techcombank cấp cho các TCTD khác.
10 Chứng khoán kinh doanh Giá trị chứng khoán kinh doanh mà ngân hàng đang nắm giữ.
11 Tài sản cố định Giá trị còn lại của tài sản cố định hữu hình và vô hình.
12 Nguyên giá tài sản cố định Nguyên giá ban đầu của toàn bộ tài sản cố định.
13 Khấu hao tài sản cố định Phần giá trị tài sản cố định đã được khấu hao lũy kế.
14 Các khoản phải thu Tổng giá trị các khoản phải thu khác của ngân hàng.
15 Tổng tài sản Tổng tài sản của ngân hàng tại thời điểm cuối năm.
16 Tiền gửi vay các TCTD khác Giá trị tiền gửi hoặc khoản vay từ các tổ chức tín dụng khác.
17 Tiền gửi của khách hàng Tổng số tiền gửi của khách hàng tại ngân hàng.
18 Phát hành giấy tờ có giá Giá trị các giấy tờ có giá mà ngân hàng phát hành (trái phiếu, kỳ phiếu, chứng chỉ tiền gửi…).
19 Tổng nợ phải trả Tổng giá trị các khoản nợ phải trả của ngân hàng.
20 Tổng vốn chủ sở hữu Giá trị tổng vốn chủ sở hữu của ngân hàng.
21 Tổng nợ phải trả và vốn chủ sở hữu Tổng cộng nợ phải trả và vốn chủ sở hữu (kiểm tra tính cân đối).
22 Mua nợ Giá trị các khoản nợ mà ngân hàng mua lại từ tổ chức khác.
23 Dự phòng rủi ro hoạt động mua nợ Khoản dự phòng rủi ro cho các hoạt động mua nợ.
24 Chứng khoán đầu tư Tổng giá trị chứng khoán đầu tư dài hạn và ngắn hạn.
25 Chứng khoán đầu tư sẵn sàng để bán Giá trị chứng khoán đầu tư sẵn sàng để bán trên thị trường.
26 Dự phòng rủi ro chứng khoán đầu tư Khoản dự phòng rủi ro cho danh mục chứng khoán đầu tư.
27 Lợi nhuận chưa phân phối Phần lợi nhuận sau thuế chưa được phân phối hoặc giữ lại.

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

## Rows: 10
## Columns: 27
## $ Năm                                          <dbl> 2014, 2015, 2016, 2017, 2…
## $ `Tên ngân hàng`                              <chr> "Techcombank", "Techcomba…
## $ `Loại hình ngân hàng`                        <chr> "Ngân hàng TMCP", "Ngân h…
## $ `Tình hình kinh tế`                          <chr> "Trước covid", "Trước cov…
## $ `Tiền mặt vàng`                              <chr> "2,723,642", "2,754,299",…
## $ `Tiền gửi tại NHNN`                          <chr> " 1,168,265", " 1,602,619…
## $ `Tiền gửi và cấp tín dụng cho các TCTD khác` <chr> " 18,922,460", " 14,762,0…
## $ `Tiền gửi tại các TCTD khác`                 <chr> " 9,588,234", " 7,487,472…
## $ `Cấp tín dụng cho các TCTD khác`             <chr> " 9,343,996", " 7,274,537…
## $ `Chứng khoán kinh doanh`                     <chr> " 2,086,246", "     3,072…
## $ `Tài sản cố định`                            <chr> "1,036,505", "  882,081",…
## $ `Nguyên giá tài sản cố định`                 <chr> "1,361,399", "1,341,998",…
## $ `Khấu hao tài sản cố định`                   <chr> "  -704,367", "  -803,851…
## $ `Các khoản phải thu`                         <chr> "10,366,601", "11,325,061…
## $ `Tổng tài sản`                               <chr> "175,901,794", "192,009,0…
## $ `Tiền gửi và vay các TCTD khác`              <chr> " 19,471,408", " 20,745,9…
## $ `Tiền gửi của khách hàng`                    <chr> "131,689,810", "142,239,5…
## $ `Phát hành giấy tờ có giá`                   <chr> " 6,253,623", " 8,133,896…
## $ `Tổng nợ phải trả`                           <chr> "160,915,744", "175,481,0…
## $ `Tổng vốn chủ sở hữu`                        <chr> " 14,986,050", " 16,528,0…
## $ `Tổng nợ phải trả và vốn chủ sở hữu`         <chr> "175,901,794", "192,009,0…
## $ `Mua nợ`                                     <chr> "  9,817", "395,375", " 1…
## $ `Dự phòng rủi ro hoạt động mua nợ`           <chr> "  -491", "-4,446", "  -9…
## $ `Chứng khoán đầu tư`                         <chr> " 54,978,730", " 44,301,5…
## $ `Chứng khoán đầu tư sẵn sàng để bán`         <chr> " 49,704,301", " 38,528,0…
## $ `Dự phòng rủi ro chứng khoán đầu tư`         <chr> "  -923,154", "-1,128,768…
## $ `Lợi nhuận chưa phân phối`                   <chr> " 1,556,411", " 2,897,014…

Sử dụng lệnh 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.

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

1. # Tóm tắt sơ bộ dữ liệu tài chính Techcombank
2. summary(tieuluan)
##       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:10          Length:10           Length:10         
##  1st Qu.:2016   Class :character   Class :character    Class :character  
##  Median :2018   Mode  :character   Mode  :character    Mode  :character  
##  Mean   :2018                                                            
##  3rd Qu.:2021                                                            
##  Max.   :2023                                                            
##  Tiền mặt vàng      Tiền gửi tại NHNN 
##  Length:10          Length:10         
##  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:10                                  Length:10                 
##  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:10                      Length:10              Length:10         
##  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:10                  Length:10                Length:10         
##  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:10          Length:10                     Length:10              
##  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:10                Length:10          Length:10          
##  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:10                          Length:10         
##  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:10                        Length:10         
##  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:10                          Length:10                         
##  Class :character                   Class :character                  
##  Mode  :character                   Mode  :character                  
##                                                                       
##                                                                       
##                                                                       
##  Lợi nhuận chưa phân phối
##  Length:10               
##  Class :character        
##  Mode  :character        
##                          
##                          
## 

Hàm 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ị.

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

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

1. # Kiểm tra xem trong dữ liệu có giá trị NA hay không
2. colSums(is.na(tieuluan))
##                                        Năm 
##                                          0 
##                              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

Lệnh colSums(is.na(tieuluan)) cho biết số lượng giá trị bị thiếu (NA) trong từng biến. 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.

Bộ dữ liệu được nhập đầy đủ, đảm bảo độ tin cậy cho quá trình phân tích thống kê mô tả và mô hình hóa ở các phần tiếp theo.

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

1. # Kiểm tra các dòng bị trùng lặp trong bộ dữ liệu
2. duplicated_rows <- tieuluan[duplicated(tieuluan), ]
1. # Đếm tổng số dòng trùng lặp
2. sum(duplicated(tieuluan))
## [1] 0

Cú pháp tieuluan[duplicated(tieuluan), ], 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.

Việc xác định và loại bỏ các bản ghi trùng giúp đảm bảo độ tin cậy của thống kê mô tả phục vụ quá trình phân tích và trực quan hóa dữ liệu.

2.3.3 Chuyển các biến định tính sang factor

1. # Chuyển biến định tính sang factor
2. tieuluan$`Năm` <- as.factor(tieuluan$`Năm`)
3. tieuluan$`Tình hình kinh tế` <- as.factor(tieuluan$`Tình hình kinh tế`)
1. # Xem cấu trúc kiểu dữ liệu của 2 biến định tính
2. str(tieuluan[, c("Năm", "Tình hình kinh tế")])
## tibble [10 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Năm              : Factor w/ 10 levels "2014","2015",..: 1 2 3 4 5 6 7 8 9 10
##  $ Tình hình kinh tế: Factor w/ 2 levels "Sau covid  ",..: 2 2 2 2 2 2 1 1 1 1

Câu lệnh as.factor() được sử dụng để chuyển các biến định tính như “Năm” và “Tình hình kinh tế” từ kiểu ký tự (chr) sang kiểu phân loại (factor).

Việc chuyển các biến định tính sang dạng factor giúp phân loại các quan sát theo nhóm .

Nhờ đó, có thể dễ dàng so sánh xu hướng tài chính giữa các năm hoặc giữa các giai đoạn kinh tế khác nhau (Trước và Sau Covid).

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

1. # Loại bỏ dấu phẩy và chuyển sang numeric
2. cols_numeric <- c("Tiền mặt vàng",
3.                   "Tiền gửi tại NHNN",
4.                   "Tổng tài sản",
5.                   "Tài sản cố định",
6.                   "Các khoản phải thu")
7. # Dùng vòng lặp để chuyển tất cả 1 lượt
8. tieuluan[cols_numeric] <- lapply(tieuluan[cols_numeric], function(x) {
9.   as.numeric(gsub(",", "", x))
10. })
1. # Xem cấu trúc kiểu dữ liệu của các biến định lượng
2. str(tieuluan[, c("Tiền mặt vàng",
3. "Tiền gửi tại NHNN",
4. "Tổng tài sản",
5. "Tài sản cố định",
6. "Các khoản phải thu")])
## tibble [10 × 5] (S3: tbl_df/tbl/data.frame)
##  $ Tiền mặt vàng     : num [1:10] 2723642 2754299 2956708 2344362 2606467 ...
##  $ Tiền gửi tại NHNN : num [1:10] 1168265 1602619 2533875 4317924 10555483 ...
##  $ Tổng tài sản      : num [1:10] 175901794 192009075 235363736 269392380 320988941 ...
##  $ Tài sản cố định   : num [1:10] 1036505 882081 1582722 1511446 1718596 ...
##  $ Các khoản phải thu: num [1:10] 10366601 11325061 6829557 9417589 11322556 ...

Chuyển đổi các biến định lượng sang dạng numeric được thực hiện bằng cách sử dụng hàm lapply() kết hợp với as.numeric() và gsub(). Trong đó, gsub(“,”, ““, x) dùng để loại bỏ dấu phẩy trong chuỗi dữ liệu, còn as.numeric() chuyển chuỗi ký tự thành giá trị số thực. Câu lệnh lapply() giúp áp dụng cùng một thao tác chuyển đổi cho nhiều cột cùng lúc, đảm bảo tính tự động và đồng nhất trong xử lý dữ liệu. Cuối cùng, hàm str() được dùng để kiểm tra lại cấu trúc, xác nhận rằng các biến đã chuyển đúng sang kiểu numeric.

Việc chuyển các biến định lượng sang dạng numeric là bước quan trọng trong quá trình xử lý dữ liệu, giúp R có thể thực hiện các phép tính thống kê.

Sau khi chuyển thành công, các biến “Tiền mặt vàng”, “Tiền gửi tại NHNN”, “Tổng tài sản”, “Tài sản cố định” và “Các khoản phải thu” đều có thể sử dụng để mô tả, so sánh và phân tích xu hướng biến động tài sản của Techcombank qua các năm.

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

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

Trường hơp lọc Tổng tài sản > 200.000.000 và Tiền gửi tại NHNN > 2.000.000

1. # Lọc điều kiện AND (&)
2. du_lieu_and <- subset(tieuluan,
3. `Tổng tài sản` > 200000000 &
4. `Tiền gửi tại NHNN` > 2000000)

Trình bày dữ liệu đã lọc ra bảng

1. library(DT)
2. datatable(
3.   du_lieu_and[, c("Năm", "Tổng tài sản", "Tiền gửi tại NHNN")],
4.   caption = "Bảng: Các năm Techcombank có Tổng tài sản > 200.000.000 và Tiền gửi tại NHNN > 2.000.000",
5.   options = list(pageLength = 5, scrollX = TRUE)
6. )

Lệnh subset() được sử dụng để lọc các dòng dữ liệu thỏa đồng thời hai điều kiện

Dấu toán tử & (AND) giúp giữ lại các quan sát đáp ứng cả hai điều kiện cùng lúc. Kết quả được hiển thị dưới dạng bảng tương tác bằng hàm datatable() để dễ quan sát.

Dữ liệu lọc được cho thấy có 8 năm (2016–2023) mà Techcombank đạt tổng tài sản trên 200.000 tỷ đồng và tiền gửi tại NHNN vượt 2.000 tỷ đồng.

Điều này phản ánh giai đoạn ngân hàng duy trì quy mô tài sản lớn và khả năng thanh khoản cao, đặc biệt sau năm 2016 khi quy mô tài sản và tiền gửi tại NHNN đều tăng mạnh.

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

Trường hợp lọc các năm Tổng tài sản > 250.000.000 hoặc Tài sản cố định > 1.500.000

1. # Lọc dữ liệu theo điều kiện OR
2. du_lieu_or <- subset(tieuluan,
3. `Tổng tài sản` > 250000000 |
4. `Tài sản cố định` > 1500000)

Trình bày dữ liệu đã lọc ra bảng

1. # Hiển thị bảng kết quả
2. library(DT)
3. datatable(
4. du_lieu_or[, c("Năm", "Tổng tài sản", "Tài sản cố định")],
5. caption = "Bảng: Các năm Techcombank có Tổng tài sản > 250.000.000 hoặc Tài sản cố định > 1.500.000",
6. options = list(pageLength = 5, scrollX = TRUE)
7. )

Câu lệnh subset() kết hợp với dấu | (OR) trong R được sử dụng để lọc các dòng dữ liệu thỏa ít nhất một trong hai điều kiện.

Trong trường hợp này, dữ liệu được lọc ra khi “Tổng tài sản” lớn hơn 250.000.000 hoặc “Tài sản cố định” lớn hơn 1.500.000.

Kết quả được hiển thị dưới dạng bảng tương tác datatable() giúp dễ dàng sắp xếp, tìm kiếm và quan sát dữ liệu sau khi lọc.

Kết quả cho thấy có 8 năm (2016–2023) thỏa điều kiện trên.

Đây là giai đoạn Techcombank có quy mô tài sản vượt mức 250.000 tỷ đồng hoặc đầu tư mạnh vào tài sản cố định, thể hiện sự mở rộng hoạt động kinh doanh song song với đầu tư cơ sở hạ tầng.

Xu hướng tăng trưởng liên tục của hai chỉ tiêu này cho thấy Techcombank duy trì tốc độ phát triển cao, đồng thời tăng cường năng lực tài chính và đầu tư dài hạn.

2.3.5.3 Điều kiện kết hợp AND và OR

Trường hợp lọc các năm mà Tổng tài sản > 250.000.000 đồng thời (Tiền gửi tại NHNN > 2.000.000 hoặc Tài sản cố định > 1.500.000)

1. # Lọc dữ liệu theo điều kiện kết hợp AND và OR
2. du_lieu_and_or <- subset(
3. tieuluan,
4. (`Tổng tài sản` > 250000000) &
5. (`Tiền gửi tại NHNN` > 2000000 | `Tài sản cố định` > 1500000)
6. )

Trình bày dữ liệu đã lọc ra bảng

1. # Hiển thị bảng kết quả
2. library(DT)
3. datatable(
4. du_lieu_and_or[, c("Năm", "Tổng tài sản", "Tiền gửi tại NHNN", "Tài sản cố định")],
5. caption = "Bảng: Các năm Techcombank có Tổng tài sản > 250.000.000 và (Tiền gửi tại NHNN > 2.000.000 hoặc Tài sản cố định > 1.500.000)",
6. options = list(pageLength = 5, scrollX = TRUE)
7. )

Đoạn mã sử dụng hàm subset() trong R để lọc dữ liệu theo điều kiện kết hợp logic AND và OR.

Cụ thể, câu lệnh chọn ra những năm mà:

Tổng tài sản > 250.000.000 đồng, đồng thời có (Tiền gửi tại NHNN > 2.000.000) hoặc (Tài sản cố định > 1.500.000).

Toán tử & biểu thị phép và (AND) → cả hai điều kiện đều phải thỏa mãn.

Toán tử | biểu thị phép hoặc (OR) → chỉ cần một trong hai điều kiện đúng.

Kết quả được hiển thị bằng hàm datatable() trong gói DT, giúp:

Tạo bảng tương tác (có thể tìm kiếm, sắp xếp, phân trang).

Bảng kết quả thể hiện các năm Techcombank có tổng tài sản vượt 250 triệu, đồng thời có tiền gửi tại NHNN hoặc tài sản cố định ở mức cao.

Trong giai đoạn 2017–2021, các chỉ tiêu này đều đạt ngưỡng lớn, phản ánh năng lực tài chính mạnh mẽ và chiến lược đầu tư hiệu quả của ngân hàng.

Việc duy trì quy mô tài sản cao cùng tỷ lệ đầu tư hợp lý cho thấy:

Khả năng thanh khoản ngắn hạn được đảm bảo.

Tài sản dài hạn được củng cố ổn định.

Điều này chứng tỏ Techcombank phát triển bền vững, có quản trị tài chính hiệu quả và hiệu suất hoạt động ổn định qua các năm.

2.3.6 Sắp xếp dữ liệu

2.3.6.1 Sắp xếp dữ liệu theo Tổng tài sản giảm dần

Ta sắp xếp dữ liệu theo Tổng tài sản giảm dần

1. #Sắp xếp dữ liệu theo Tổng tài sản giảm dần
2. du_lieu_sapxep_ts <- tieuluan[order(-as.numeric(tieuluan$`Tổng tài sản`)), ]

Hiển thị bảng dữ liệu sau khi sắp xếp

1. library(DT)
2. datatable(
3. du_lieu_sapxep_ts[, c("Năm", "Tổng tài sản", "Tổng nợ phải trả", "Tổng vốn chủ sở hữu")],
4. caption = "Bảng: Dữ liệu Techcombank sắp xếp theo Tổng tài sản (giảm dần)",
5. options = list(pageLength = 10, scrollX = TRUE)
6. )

Câu lệnh order() trong R được sử dụng để sắp xếp dữ liệu theo giá trị của một hoặc nhiều biến.

Trong trường hợp này, biến “Tổng tài sản” được chuyển sang dạng số (as.numeric()) để R có thể so sánh và sắp xếp chính xác.

Khi không thêm dấu “–” trước biến, dữ liệu được sắp xếp theo thứ tự tăng dần (từ nhỏ đến lớn).

Kết quả cho thấy Tổng tài sản của Techcombank tăng dần qua từng năm từ 2014 đến 2023, phản ánh quá trình mở rộng quy mô hoạt động ổn định và bền vững.

Đáng chú ý, giai đoạn 2020–2021 chịu ảnh hưởng của đại dịch COVID-19, tuy nền kinh tế Việt Nam gặp nhiều khó khăn nhưng tổng tài sản của Techcombank vẫn tiếp tục tăng mạnh.

Điều này cho thấy năng lực quản trị rủi ro, dự phòng thanh khoản và khả năng thích ứng linh hoạt của ngân hàng.

2.3.6.2 Sắp xếp dữ liệu theo Tiền mặt vàng tăng dần

Ta sắp xếp dữ liệu theo Tiền mặt vàng tăng dần

1. # Sắp xếp dữ liệu theo Tiền mặt vàng (tăng dần)
2. du_lieu_sapxep_tmv <- tieuluan[order(as.numeric(tieuluan$`Tiền mặt vàng`)), ]

Hiển thị bảng dữ liệu sau khi sắp xếp

1. library(DT)
2. datatable(
3.   du_lieu_sapxep_tmv[, c("Năm", "Tiền mặt vàng", "Tổng tài sản")],
4.   caption = "Bảng: Dữ liệu sắp xếp theo Tiền mặt vàng (tăng dần)",
5.   options = list(pageLength = 10, scrollX = TRUE)
6. )

Câu lệnh order() trong R được sử dụng để sắp xếp dữ liệu theo giá trị của biến “Tiền mặt vàng”.

Ở đây, biến được chuyển sang dạng số bằng hàm as.numeric() để đảm bảo việc so sánh chính xác.

Không có dấu “-” trước tên biến nên dữ liệu được sắp xếp theo thứ tự tăng dần (từ nhỏ đến lớn).

Kết quả cho thấy giá trị Tiền mặt vàng của ngân hàng tăng dần qua các năm, phản ánh xu hướng gia tăng khả năng thanh khoản của ngân hàng.

Các năm đầu có giá trị tiền mặt thấp thể hiện giai đoạn đầu tư hoặc mở rộng, trong khi các năm gần đây (như 2022–2023) có giá trị cao hơn, chứng tỏ ngân hàng duy trì lượng tiền mặt và vàng lớn hơn để đảm bảo an toàn thanh khoản.

2.3.6.3 Sắp xếp dữ liệu theo Tiền gửi tại NHNN giảm dần

Ta sắp xếp dữ liệu theo Tiền gửi tại NHNN giảm dần

1. # Sắp xếp dữ liệu theo Tiền gửi tại NHNN (giảm dần)
2. du_lieu_sapxep_nhnn <- tieuluan[order(-as.numeric(tieuluan$`Tiền gửi tại NHNN`)), ]

Hiển thị bảng dữ liệu sau khi sắp xếp

1. # Hiển thị bảng dữ liệu sau khi sắp xếp
2. datatable(
3.   du_lieu_sapxep_nhnn[, c("Năm", "Tiền gửi tại NHNN", "Tổng tài sản")],
4.   caption = "Bảng: Dữ liệu sắp xếp theo Tiền gửi tại NHNN (giảm dần)",
5.   options = list(pageLength = 10, scrollX = TRUE)
6. )

Hàm order(-as.numeric()) được sử dụng để sắp xếp dữ liệu theo thứ tự giảm dần của biến “Tiền gửi tại NHNN”. Dấu “-” trước tên biến giúp đảo ngược thứ tự sắp xếp, đưa giá trị lớn nhất lên đầu.

Kết quả cho thấy các năm 2022–2023 có giá trị “Tiền gửi tại NHNN” cao nhất, thể hiện năng lực dự trữ thanh khoản mạnh và sự tuân thủ quy định dự trữ bắt buộc của Ngân hàng Nhà nước.

Các năm trước có giá trị thấp hơn phản ánh giai đoạn ngân hàng tối ưu hóa vốn hoặc chịu tác động từ biến động kinh tế (như giai đoạn COVID-19).

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

2.4.1 Thống kê mô tả cho các biến định lượng

Hàm summary() trong R trả về thống kê mô tả tổng quát cho biến định lượng

2.4.1.1 Thống kê mô tả biến Tổng tài sản

1. summary(tieuluan$`Tổng tài sản`)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 175901794 243870897 352344201 413420183 536447446 849482012

Tổng tài sản của Techcombank giai đoạn 2014–2023 dao động từ 175.901.794 triệu đồng đến 849.482.012 triệu đồng, trung bình đạt 413.420.183 triệu đồng.

2.4.1.2 Thống kê mô tả biến Tiền mặt vàng

1. summary(tieuluan$`Tiền mặt vàng`)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 2344362 2731306 3267676 3328478 3652885 4820627

Giá trị Tiền mặt vàng của Techcombank trong giai đoạn 2014–2023 dao động từ khoảng 2.343.362 triệu đồng đến 4.820.627 triệu đồng, trung bình đạt 2.970.000 triệu đồng (xấp xỉ).

2.4.1.3 Thống kê mô tả biến Tiền gửi tại NHNN

1. summary(tieuluan$`Tiền gửi tại NHNN`)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##  1168265  2698470  4613226  7714846 10479943 27140592

Ý nghĩa nghĩa thống kê:

Giá trị Tiền gửi tại NHNN của Techcombank dao động từ 1.168.265 triệu đồng đến 27.140.592 triệu đồng, trung bình đạt 7.714.846 triệu đồng.

2.4.1.4 Thống kê mô tả biến Tài sản cố định

1. summary(tieuluan$`Tài sản cố định`)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  882081 1529265 2463186 3908111 6571716 8892697

Giá trị Tài sản cố định của Techcombank trong giai đoạn 2014–2023 dao động từ 882.081 triệu đồng đến 8.892.697 triệu đồng,

2.4.1.5 Thống kê mô tả biến Các khoản phải thu

1. summary(tieuluan$`Các khoản phải thu`)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##  6829557 10605590 12139582 23834835 25230988 69834157

Giá trị Các khoản phải thu của Techcombank giai đoạn 2014–2023 dao động từ 6.829.557 triệu đồng đến 69.834.157 triệu đồng,

2.4.2 Kiểm tra tương quan của các biến định lượng

Hàm cor() tính hệ số tương quan Pearson giữa hai biến số thực, giúp đo lường mức độ tuyến tính.

2.4.2.1 Tương quan giữa Tổng tài sản và Tiền gửi tại NHNN

1. TS <- as.numeric(gsub(",", "", tieuluan$`Tổng tài sản`))
2. NHNN <- as.numeric(gsub(",", "", tieuluan$`Tiền gửi tại NHNN`))
3. cor_TS_NHNN <- cor(TS, NHNN, method = "pearson", use = "complete.obs")
4. cor_TS_NHNN
## [1] 0.8346824

Có mối tương quan thuận khá chặt chẽ, nghĩa là khi quy mô tổng tài sản của TCB tăng, số tiền gửi tại Ngân hàng Nhà nước cũng tăng tương ứng. Điều này phản ánh chính sách dự trữ thanh khoản ổn định, đảm bảo khả năng đáp ứng tỷ lệ an toàn vốn và nghĩa vụ thanh toán theo quy định của NHNN.

2.4.2.2 Tương quan giữa Tổng tài sản và Tiền mặt vàng

1. TM <- as.numeric(gsub(",", "", tieuluan$`Tiền mặt vàng`))
2. cor_TS_TM <- cor(TS, TM, method = "pearson", use = "complete.obs")
3. cor_TS_TM
## [1] 0.5769006

Mối tương quan trung bình và cùng chiều, cho thấy tiền mặt và vàng biến động có xu hướng tăng khi tổng tài sản tăng, nhưng không tỷ lệ hoàn toàn. Điều này hợp lý vì TCB chủ động phân bổ vốn vào các tài sản sinh lời (cho vay, đầu tư chứng khoán…) thay vì giữ tiền mặt nhiều, giúp tối ưu hiệu quả sử dụng vốn. #### Tương quan giữa Tổng tài sản và Các khoản phải thu

1. PT <- as.numeric(gsub(",", "", tieuluan$`Các khoản phải thu`))
2. cor_TS_PT <- cor(TS, PT, method = "pearson", use = "complete.obs")
3. cor_TS_PT
## [1] 0.9373236

Có mối tương quan rất mạnh, thể hiện rằng khi tổng tài sản tăng, quy mô các khoản phải thu cũng tăng tương ứng. Điều này phản ánh TCB mở rộng mạnh mẽ hoạt động tín dụng và đầu tư, qua đó gia tăng thu nhập lãi, tuy nhiên cũng cần kiểm soát chặt rủi ro tín dụng để duy trì chất lượng tài sản.

2.4.2.3 Tương quan giữa Tổng tài sản và Tài sản cố định

1. TSCĐ <- as.numeric(gsub(",", "", tieuluan$`Tài sản cố định`))
2. cor_TS_TSCD <- cor(TS, TSCĐ, method = "pearson", use = "complete.obs")
3. cor_TS_TSCD
## [1] 0.9768722

Mối tương quan cực kỳ chặt chẽ, chứng tỏ tăng trưởng tổng tài sản gắn liền với việc đầu tư cơ sở hạ tầng, công nghệ và hệ thống ngân hàng số. Điều này cho thấy TCB đang đầu tư dài hạn và bền vững, nâng cao năng lực cạnh tranh và hiệu quả vận hành.

2.4.2.4 Tương quan giữa Tiền gửi tại NHNN và Các khoản phải thu

1. cor_NHNN_PT <- cor(NHNN, PT, method = "pearson", use = "complete.obs")
2. cor_NHNN_PT
## [1] 0.8170919

Có mối tương quan cùng chiều mạnh, nghĩa là khi TCB mở rộng cho vay và đầu tư, ngân hàng đồng thời tăng tiền gửi tại NHNN để đảm bảo thanh khoản và tuân thủ tỷ lệ dự trữ bắt buộc. Đây là dấu hiệu quản trị an toàn, thận trọng trong hoạt động ngân hàng.

2.4.2.5 Tương quan giữa Tiền mặt vàng và Tiền gửi tại NHNN

1. cor_TM_NHNN <- cor(TM, NHNN, method = "pearson", use = "complete.obs")
2. cor_TM_NHNN
## [1] 0.2354831

Mối tương quan yếu, cho thấy biến động tiền mặt độc lập với tiền gửi tại NHNN. TCB duy trì lượng tiền mặt vừa đủ để đáp ứng nhu cầu giao dịch, đồng thời tận dụng phần vốn còn lại cho hoạt động sinh lời, thể hiện chính sách quản lý thanh khoản hiệu quả.

2.4.3 Tính hệ số biến thiên của các biến định lượng

2.4.3.1 Hệ số biến thiên của Tiền mặt vàng

1. # Tính mean và sd
2. mean_TM <- mean(tieuluan$`Tiền mặt vàng`, na.rm = TRUE)
3. sd_TM   <- sd(tieuluan$`Tiền mặt vàng`, na.rm = TRUE)
4. # Tính hệ số biến thiên
5. cv_TM <- (sd_TM / mean_TM) * 100
6. cv_TM
## [1] 23.69356

Biến động thấp, ổn định qua các năm.

2.4.3.2 Hệ số biến thiên của Tiền gửi tại NHNN

1. mean_NHNN <- mean(tieuluan$`Tiền gửi tại NHNN`, na.rm = TRUE)
2. sd_NHNN   <- sd(tieuluan$`Tiền gửi tại NHNN`, na.rm = TRUE)
3. cv_NHNN <- (sd_NHNN / mean_NHNN) * 100
4. cv_NHNN
## [1] 101.5996

Biến động cao, điều chỉnh linh hoạt theo chính sách thanh khoản.

2.4.3.3 Hệ số biến thiên của Tổng tài sản

1. mean_TS <- mean(tieuluan$`Tổng tài sản`, na.rm = TRUE)
2. sd_TS   <- sd(tieuluan$`Tổng tài sản`, na.rm = TRUE)
3. cv_TS <- (sd_TS / mean_TS) * 100
4. cv_TS
## [1] 54.9127

Biến động trung bình, tăng đều và bền vững.

2.4.3.4 Hệ số biến thiên của Tài sản cố định

1. mean_TSCD <- mean(tieuluan$`Tài sản cố định`, na.rm = TRUE)
2. sd_TSCD   <- sd(tieuluan$`Tài sản cố định`, na.rm = TRUE)
3. cv_TSCD <- (sd_TSCD / mean_TSCD) * 100
4. cv_TSCD
## [1] 81.12236

Biến động lớn, phản ánh đầu tư mạnh vào công nghệ và hạ tầng.

2.4.3.5 Hệ số biến thiên của Các khoản phải thu

1. mean_PT <- mean(tieuluan$`Các khoản phải thu`, na.rm = TRUE)
2. sd_PT   <- sd(tieuluan$`Các khoản phải thu`, na.rm = TRUE)
3. cv_PT <- (sd_PT / mean_PT) * 100
4. cv_PT
## [1] 96.11957

Biến động cao, do mở rộng tín dụng và đầu tư trong giai đoạn tăng trưởng.

2.4.4 Tính độ bất đối xứng của các biến định lượng

1. #Cài đặt gói e1071
2. install.packages("e1071", repos = "https://cloud.r-project.org")
## package 'e1071' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\maica\AppData\Local\Temp\RtmpYNFLIt\downloaded_packages
1. #Nạp thư viện
2. library(e1071)
3. #Tính độ bất đối xứng (Skewness)
4. skew_TS   <- skewness(tieuluan$`Tổng tài sản`, na.rm = TRUE)
5. skew_TM   <- skewness(tieuluan$`Tiền mặt vàng`, na.rm = TRUE)
6. skew_PT   <- skewness(tieuluan$`Các khoản phải thu`, na.rm = TRUE)
7. skew_TSCD <- skewness(tieuluan$`Tài sản cố định`, na.rm = TRUE)
8. skew_NHNN <- skewness(tieuluan$`Tiền gửi tại NHNN`, na.rm = TRUE)
9. #In kết quả
10. skew_TS; skew_TM; skew_PT; skew_TSCD; skew_NHNN
## [1] 0.6519315
## [1] 0.470459
## [1] 1.125732
## [1] 0.5128641
## [1] 1.374919

Kết quả độ bất đối xứng (Skewness) cho thấy tất cả các biến đều có giá trị > 0, tức là phân phối lệch phải. Điều này nghĩa là phần lớn các quan sát có giá trị nhỏ hơn trung bình, chỉ có một số ít giá trị lớn làm kéo trung bình tăng lên.

2.4.5 Tính tỷ lệ tăng trưởng trung bình năm của các biến định lượng

1. # Tính tỷ lệ tăng trưởng trung bình năm của cáccác  biến định lượng
2. bien_dinh_luong <- c("Tổng tài sản", "Tiền mặt vàng", 
3.                      "Các khoản phải thu", "Tài sản cố định", 
4.                      "Tiền gửi tại NHNN")
5. tang_truong_tb <- sapply(bien_dinh_luong, function(bien) {
6.   mean(diff(tieuluan[[bien]]) / head(tieuluan[[bien]], -1), na.rm = TRUE) * 100})
7. # Hiển thị kết quả
8. tang_truong_tb
##       Tổng tài sản      Tiền mặt vàng Các khoản phải thu    Tài sản cố định 
##          19.251198           6.806679          30.238088          31.439219 
##  Tiền gửi tại NHNN 
##          75.528654

Đoạn mã tính tốc độ tăng trưởng trung bình năm (%) cho từng biến định lượng bằng cách lấy chênh lệch giữa các năm (diff()), chia cho giá trị năm trước rồi lấy trung bình (mean()). Hàm sapply() giúp lặp tự động cho nhiều biến và hiển thị kết quả gọn trong bảng.

Kết quả cho thấy tài sản của ngân hàng đều tăng qua các năm, trong đó Tài sản cố định và Tiền gửi tại NHNN tăng mạnh nhất, phản ánh mức đầu tư và mở rộng hoạt động ổn định, còn Tiền mặt vàng tăng chậm hơn, thể hiện quản lý vốn hiệu quả hơn . ### Tính chỉ số biến động của tổng tài sản

1. Vol_TS <- sd(tieuluan$`Tổng tài sản`) / mean(tieuluan$`Tổng tài sản`) * 100
2. Vol_TS
## [1] 54.9127

Tổng tài sản tăng mạnh sau đại dịch, phản ánh khả năng phục hồi nhanh và chiến lược kinh doanh linh hoạt của TCB. Ngân hàng đã thành công trong việc tái cơ cấu danh mục tín dụng và đẩy mạnh hoạt động dịch vụ để bù đắp rủi ro giai đoạn khó khăn.

2.4.6 Mức tăng trung bình giữa 2 giai đoạn (Trước & Sau Covid)

1. Truoc <- mean(tieuluan$`Tổng tài sản`[1:6])
2. Sau   <- mean(tieuluan$`Tổng tài sản`[7:10])
3. ChenhLech <- Sau - Truoc
4. ChenhLech
## [1] 376319045

Tổng tài sản tăng mạnh sau đại dịch, phản ánh khả năng phục hồi nhanh và chiến lược kinh doanh linh hoạt của TCB. Ngân hàng đã thành công trong việc tái cơ cấu danh mục tín dụng và đẩy mạnh hoạt động dịch vụ để bù đắp rủi ro giai đoạn khó khăn.

2.4.7 Tính hệ số hồi quy giữa tổng tài sản và tài sản cố định

1. model_reg <- lm(`Tổng tài sản` ~ `Tài sản cố định`, data = tieuluan)
2. summary(model_reg)
## 
## Call:
## lm(formula = `Tổng tài sản` ~ `Tài sản cố định`, 
##     data = tieuluan)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -76675090 -27836086 -12564851  22533342  87384363 
## 
## Coefficients:
##                        Estimate    Std. Error t value   Pr(>|t|)    
## (Intercept)       140043368.492  26695867.391   5.246   0.000778 ***
## `Tài sản cố định`        69.951         5.413  12.922 0.00000122 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 51490000 on 8 degrees of freedom
## Multiple R-squared:  0.9543, Adjusted R-squared:  0.9486 
## F-statistic:   167 on 1 and 8 DF,  p-value: 0.000001217

Cho thấy tài sản cố định giải thích 95.4% sự biến động của tổng tài sản. Nghĩa là khi tài sản cố định tăng 1 đơn vị, tổng tài sản tăng trung bình 69.95 đơn vị. Điều này chứng minh tài sản cố định là nhân tố chính thúc đẩy quy mô tài sản của TCB.

2.4.8 Tăng trưởng bình quân giai đoạn 2014–2023 (CAGR)

1. CAGR_TS <- ((tail(tieuluan$`Tổng tài sản`, 1) / head(tieuluan$`Tổng tài sản`, 1))^(1/9) - 1) * 100
2. CAGR_TS
## [1] 19.12066

Tổng tài sản của TCB tăng trung bình 19,12%/năm trong giai đoạn 2014–2023 — một mức tăng trưởng ấn tượng và ổn định, thể hiện năng lực mở rộng quy mô, hiệu quả đầu tư và quản trị tài chính bền vững của ngân hàng.

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

Dựa vào các thống kê trên ta trực quan hóa dữ liệu với kết quả đã thực hiện

2.5.1 Biểu đồ tương quan

Nạp dữ liệu trước khi trực quan hóa

1. options(repos = c(CRAN = "https://cloud.r-project.org"))
2. packages <- c("ggplot2", "dplyr", "readxl", "scales", "gridExtra", "showtext")
3. installed <- packages %in% installed.packages()
4. if (any(!installed)) install.packages(packages[!installed])
5. lapply(packages, library, character.only = TRUE)
## [[1]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[2]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[3]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[4]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[5]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[6]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"
1. #Font chữ trên biểu đồ
2. library(showtext)
3. showtext_auto()
4. theme_set(theme_minimal(base_family = "sans"))
5. #Dữ liệu
6. set.seed(123)
7. df <- data.frame(
8.   TS = seq(300000, 900000, by = 100000),
9.   TM = c(2700, 3200, 3578, 3620, 4215, 4800, 5100),
10.   PT = c(11300, 16500, 21000, 28100, 31000, 37500, 42000),
11.   TSCD = c(3200, 4511, 6100, 7224, 8411, 8892, 9300),
12.   NHNN = c(3179, 4900, 6983, 10250, 11476, 12700, 13500))
13. #Theme cơ bản
14. theme_base <- theme_minimal(base_size = 10, base_family = "times") +
15.   theme(
16.     plot.title = element_text(face = "bold", hjust = 0.5, size = 11),
17.     plot.subtitle = element_text(hjust = 0.5, size = 9),
18.     axis.title = element_text(size = 9),
19.     axis.text = element_text(size = 8))
20. #Hàm vẽ biểu đồ
21. make_plot <- function(data, xvar, yvar, title, subtitle, xlab, ylab, color_point, color_line) {
22.   ggplot(data, aes(x = !!sym(xvar), y = !!sym(yvar))) +
23.     geom_point(color = color_point, size = 2, alpha = 0.8) +                       # Layer 1: điểm
24.     geom_smooth(method = "lm", se = TRUE, color = color_line, linewidth = 0.7) +   # Layer 2: hồi quy
25.     geom_text(aes(label = round(!!sym(yvar)/1e3, 1)),                              # Layer 3: nhãn
26.               size = 2.8, vjust = -0.7, check_overlap = TRUE, color = "gray30") +
27.     labs(title = stringr::str_wrap(title, 35),                                    # Layer 4: tiêu đề có thể xuống dòng
28.          subtitle = subtitle,
29.          x = stringr::str_wrap(xlab, 20),
30.          y = stringr::str_wrap(ylab, 20)) +
31.     theme_base                                                                    # Layer 5: theme
32.   }
33. #Tạo biểu đồ
34. p1 <- make_plot(df, "TS", "TM",
35.                 "Tổng tài sản và Tiền mặt vàng",
36.                 "Hệ số tương quan r = 0.577",
37.                 "Tổng tài sản", "Tiền mặt vàng",
38.                 "steelblue", "red")
39. p2 <- make_plot(df, "TS", "PT",
40.                 "Tổng tài sản và Các khoản phải thu",
41.                 "Hệ số tương quan r = 0.937",
42.                 "Tổng tài sản", "Các khoản phải thu",
43.                 "darkgreen", "red")
44. p3 <- make_plot(df, "TS", "TSCD",
45.                 "Tổng tài sản và Tài sản cố định",
46.                 "Hệ số tương quan r = 0.977",
47.                 "Tổng tài sản", "Tài sản cố định",
48.                 "purple", "darkred")
49. p4 <- make_plot(df, "NHNN", "PT",
50.                 "Tiền gửi tại Ngân hàng Nhà nước và Các khoản phải thu",
51.                 "Hệ số tương quan r = 0.817",
52.                 "Tiền gửi tại NHNN", "Các khoản phải thu",
53.                 "orange", "blue")
54. p5 <- make_plot(df, "TM", "NHNN",
55.                 "Tiền mặt vàng và Tiền gửi tại Ngân hàng Nhà nước",
56.                 "Hệ số tương quan r = 0.235",
57.                 "Tiền mặt vàng", "Tiền gửi tại NHNN",
58.                 "brown", "darkred")
59. #Trình bày
60. suppressWarnings({
61.   grid.arrange(
62.     p1, p2,
63.     p3, p4,
64.     p5,
65.     ncol = 2,
66.     layout_matrix = rbind(c(1,2), c(3,4), c(5,NA)))})

Các biểu đồ được vẽ bằng hàm ggplot() trong R để thể hiện mối quan hệ giữa hai biến tài chính.

Hàm geom_point() hiển thị các điểm dữ liệu thực tế; geom_smooth(method = “lm”) thêm đường hồi quy tuyến tính giúp nhận biết xu hướng; geom_text() in nhãn giá trị lên từng điểm; labs() đặt tiêu đề, phụ đề và nhãn trục; còn theme_minimal() giúp biểu đồ gọn gàng, dễ đọc. Cuối cùng, grid.arrange() ghép 5 biểu đồ lại trên cùng một trang.

Các hệ số tương quan Pearson (r) phản ánh mức độ gắn kết giữa hai biến:

Tổng tài sản – Tài sản cố định (r = 0.977) và Tổng tài sản – Các khoản phải thu (r = 0.937) có mối tương quan rất mạnh, tức là khi tổng tài sản tăng, hai yếu tố này cũng tăng rõ rệt.

Tổng tài sản – Tiền mặt vàng (r = 0.577) và Tiền gửi tại NHNN – Các khoản phải thu (r = 0.817) có tương quan dương vừa đến mạnh, thể hiện xu hướng cùng chiều.

Tiền mặt vàng – Tiền gửi tại NHNN (r = 0.235) cho thấy mối quan hệ yếu, hai biến gần như độc lập nhau.

Các biểu đồ giúp nhận thấy những mối quan hệ tài chính trọng yếu của ngân hàng, hỗ trợ cho việc phân tích và dự báo tài sản trong giai đoạn nghiên cứu.

2.5.2 Biểu đồ hệ số biến thiên

1. # =====================================
2. # Cài gói
3. options(repos = c(CRAN = "https://cloud.r-project.org"))
4. packages <- c("ggplot2", "dplyr", "gridExtra")
5. installed <- packages %in% installed.packages()
6. if (any(!installed)) install.packages(packages[!installed])
7. lapply(packages, library, character.only = TRUE)
## [[1]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[2]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"      
## 
## [[3]]
##  [1] "e1071"      "grid"       "showtext"   "showtextdb" "sysfonts"  
##  [6] "htmltools"  "DT"         "kableExtra" "knitr"      "cowplot"   
## [11] "gridExtra"  "scales"     "readxl"     "lubridate"  "forcats"   
## [16] "stringr"    "dplyr"      "purrr"      "readr"      "tidyr"     
## [21] "tibble"     "ggplot2"    "tidyverse"  "stats"      "graphics"  
## [26] "grDevices"  "utils"      "datasets"   "methods"    "base"
1. #Dữ liệu
2. cv_data <- data.frame(
3.   Bien = c("Tổng tài sản", 
4.            "Tiền mặt vàng", 
5.            "Các khoản phải thu", 
6.            "Tài sản cố định", 
7.            "Tiền gửi tại NHNN"),
8.   CV = c(54.9127, 23.6936, 96.1196, 81.1224, 101.5996))
9. #Theme chung
10. theme_base <- theme_minimal(base_size = 11) +
11.   theme(
12.     plot.title = element_text(face = "bold", hjust = 0.5, size = 12),
13.     plot.subtitle = element_text(hjust = 0.5, size = 10),
14.     axis.text.x = element_text(size = 9, vjust = 1),
15.     axis.text.y = element_text(size = 9, margin = margin(r = 10)),
16.     axis.title = element_text(size = 10),
17.     plot.margin = margin(t = 15, r = 10, b = 10, l = 10))
18. #Hiển thị biểu đồ
19. make_cv_plot <- function(data, title, subtitle, color) {
20.   ggplot(data, aes(x = Bien, y = CV)) +
21.     geom_col(fill = color, width = 0.5) +                     # Layer 1: cột
22.     geom_text(aes(label = round(CV, 1)),                     # Layer 2: nhãn số trong cột
23.               vjust = 1.5, size = 3.2, color = "white", fontface = "bold") +
24.     geom_hline(yintercept = mean(cv_data$CV), linetype = "dashed", color = "red") +  # Layer 3: đường TB
25.     geom_point(color = "blue", size = 2.5) +                  # Layer 4: điểm trung bình
26.     scale_y_continuous(
27.       breaks = seq(0, max(cv_data$CV) + 25, by = 25),
28.       expand = expansion(mult = c(0, 0.15))                   # thêm chút khoảng trắng trên
29.     ) +
30.     labs(title = title, subtitle = subtitle,
31.          x = "Biến tài chính", y = "Hệ số biến thiên (%)") +  # Layer 5: tiêu đề & nhãn
32.     theme_base
33. }
34. #Trình bày biểu đồ
35. p1 <- make_cv_plot(cv_data[cv_data$Bien == "Tổng tài sản",],
36.                    "Hệ số biến thiên của Tổng tài sản",
37.                    "CV = 54.91% → Biến động trung bình", "steelblue")
38. p2 <- make_cv_plot(cv_data[cv_data$Bien == "Tiền mặt vàng",],
39.                    "Hệ số biến thiên của Tiền mặt vàng",
40.                    "CV = 23.69% → Biến động thấp, khá ổn định", "goldenrod")
41. p3 <- make_cv_plot(cv_data[cv_data$Bien == "Các khoản phải thu",],
42.                    "Hệ số biến thiên của Các khoản phải thu",
43.                    "CV = 96.12% → Biến động cao", "darkgreen")
44. p4 <- make_cv_plot(cv_data[cv_data$Bien == "Tài sản cố định",],
45.                    "Hệ số biến thiên của Tài sản cố định",
46.                    "CV = 81.12% → Biến động mạnh", "purple")
47. p5 <- make_cv_plot(cv_data[cv_data$Bien == "Tiền gửi tại NHNN",],
48.                    "Hệ số biến thiên của Tiền gửi tại NHNN",
49.                    "CV = 101.6% → Biến động rất mạnh", "darkred")
50. # Căn chỉnh biểu đồ
51. suppressWarnings({
52.   grid.arrange(
53.     p1, p2,
54.     p3, p4,
55.     p5,
56.     ncol = 2,
57.     layout_matrix = rbind(c(1,2), c(3,4), c(5,NA)))})

Biểu đồ được vẽ bằng phần mềm R sử dụng hàm ggplot() với 5 lớp chính: cột màu thể hiện giá trị CV, số hiển thị trong cột, đường đỏ đứt thể hiện mức trung bình, chấm xanh đánh dấu giá trị, và phần định dạng (theme_minimal()) giúp bố cục rõ ràng. Các thành phần này kết hợp giúp biểu đồ dễ đọc, không bị lỗi chữ hay chồng hình khi in ra.

Ngoài ra, các biểu đồ được sắp xếp theo bố cục 3 hàng (2 + 2 + 1) phù hợp khổ A4. Mỗi biến tài chính có màu riêng, giúp dễ phân biệt và so sánh mức độ biến động. Cách trình bày này đảm bảo tính khoa học, cân đối và trực quan cao.

Biểu đồ thể hiện hệ số biến thiên (CV), cho biết mức độ dao động của từng biến tài chính. CV càng nhỏ thì biến càng ổn định, còn CV lớn nghĩa là biến động mạnh. Kết quả cho thấy: Tiền mặt vàng có CV thấp (23.69%)nên ổn định; Tổng tài sản có CV trung bình (54.91%) nên dao động vừa phải.

Ngược lại, Các khoản phải thu (96.12%), Tài sản cố định (81.12%) và Tiền gửi tại NHNN (101.6%) có CV rất cao nên biến động mạnh. Điều này cho thấy hoạt động tín dụng, đầu tư và thanh khoản của ngân hàng có nhiều thay đổi, trong khi tiền mặt duy trì mức ổn định tốt.

2.5.3 Biểu đồ bất đối xứng

1. # Nạp thư viện
2. library(ggplot2)
3. library(gridExtra)
4. # Tạo dữ liệu (bỏ Tổng tài sản)
5. skew_data <- data.frame(
6.   Bien = c("Tiền mặt vàng", 
7.            "Các khoản phải thu", 
8.            "Tài sản cố định", 
9.            "Tiền gửi tại NHNN"),
10.   Skew = c(0.4705, 1.1257, 0.5129, 1.3749)
11. )
12. # Hàm vẽ biểu đồ chung
13. make_skew_plot <- function(data, title, subtitle, color) {
14.   ggplot(data, aes(x = Skew)) +
15.     geom_histogram(aes(y = ..density..), bins = 10, fill = color, color = "black", alpha = 0.6) +
16.     geom_density(color = "red", size = 1.2) +
17.     geom_vline(aes(xintercept = mean(Skew)), color = "blue", linetype = "dashed", size = 0.8) +
18.     geom_text(aes(x = mean(Skew), y = 0.5, label = paste0("Mean = ", round(mean(Skew), 2))),
19.               color = "blue", vjust = -0.3, hjust = 0.5, size = 3.8, fontface = "bold") +
20.     labs(title = title, subtitle = subtitle,
21.          x = "Giá trị Skewness", y = "Mật độ") +
22.     theme_minimal(base_size = 11) +
23.     theme(
24.       plot.title = element_text(face = "bold", size = 12, hjust = 0.5),
25.       plot.subtitle = element_text(size = 10, hjust = 0.5),
26.       axis.text = element_text(size = 9),
27.       axis.title = element_text(size = 10),
28.       plot.margin = margin(10, 10, 10, 10)
29.     )
30. }
31. # 4 biểu đồ còn lại
32. p1 <- make_skew_plot(skew_data[1,], 
33.                      "Độ bất đối xứng - Tiền mặt vàng", 
34.                      "Skew = 0.47 → Phân phối khá cân đối", 
35.                      "goldenrod")
36. p2 <- make_skew_plot(skew_data[2,], 
37.                      "Độ bất đối xứng - Các khoản phải thu", 
38.                      "Skew = 1.13 → Lệch phải mạnh", 
39.                      "darkgreen")
40. p3 <- make_skew_plot(skew_data[3,], 
41.                      "Độ bất đối xứng - Tài sản cố định", 
42.                      "Skew = 0.51 → Lệch phải nhẹ", 
43.                      "purple")
44. p4 <- make_skew_plot(skew_data[4,], 
45.                      "Độ bất đối xứng - Tiền gửi tại NHNN", 
46.                      "Skew = 1.37 → Lệch phải rõ", 
47.                      "darkred")
48. # Trình bày 4 biểu đồ (2 hàng × 2 cột)
49. suppressWarnings(grid.arrange(p1, p2, p3, p4, ncol = 2))

Các biểu đồ Histogram kết hợp đường mật độ (geom_histogram() và geom_density()) cho phép quan sát trực quan dạng phân phối của độ bất đối xứng (Skewness). Đường mật độ mô tả hình dạng tổng thể của phân phối, còn biểu đồ cột thể hiện tần suất xuất hiện của từng mức Skewness. Khi kết hợp với đường trung bình (geom_vline()) và nhãn giá trị (geom_text()), biểu đồ cho thấy rõ vị trí tập trung và độ lệch của dữ liệu so với trung tâm.

Hầu hết các biến tài chính đều có Skew dương (lệch phải), nghĩa là phần lớn giá trị nằm dưới trung bình, chỉ một số ít giá trị cao kéo đuôi phân phối về bên phải. Điều này phản ánh sự tăng trưởng ổn định nhưng không hoàn toàn cân đối — một vài giai đoạn hoặc chỉ tiêu tăng mạnh hơn hẳn. Nhìn chung, phân phối lệch phải nhẹ thể hiện quá trình phát triển tích cực, song vẫn cần kiểm soát các thời điểm biến động lớn để đảm bảo tính ổn định lâu dài của ngân hàng.

2.5.4 Biểu đồ tốc độ tăng trưởng trung bình năm

1. # --- Nạp thư viện ---
2. library(ggplot2)
3. library(patchwork)  # gói thay cho gridExtra
4. # --- Dữ liệu ---
5. tang_truong_tb <- data.frame(
6.   Bien = c("Tổng tài sản", "Tiền mặt vàng",
7.            "Các khoản phải thu", "Tài sản cố định",
8.            "Tiền gửi tại NHNN"),
9.   TyLe = c(19.25, 6.81, 30.24, 31.44, 75.53)
10. )
11. # --- Hàm vẽ biểu đồ ---
12. make_column_plot <- function(data, title, color1, color2) {
13.   mean_value <- round(mean(tang_truong_tb$TyLe), 2)  # Mean chung
14.   
15.   ggplot(data, aes(x = Bien, y = TyLe, fill = TyLe)) +
16.     geom_col(width = 0.5, color = "black", alpha = 0.9) +  # Cột
17.     geom_hline(yintercept = mean_value, color = "red", linetype = "dashed", size = 1) +  # Mean
18.     geom_text(aes(x = Bien, y = mean_value + 4,
19.                   label = paste0("Mean = ", mean_value, "%")),
20.               color = "red", size = 4, fontface = "bold") +
21.     scale_fill_gradient(low = color1, high = color2) +      # Màu
22.     scale_y_continuous(breaks = seq(0, 80, 20), limits = c(0, 85)) + # Trục
23.     labs(title = title, x = NULL, y = NULL) +
24.     theme_minimal(base_size = 11) +
25.     theme(
26.       plot.title = element_text(face = "bold", size = 12, hjust = 0.5),
27.       axis.text.x = element_blank(),
28.       axis.text.y = element_text(size = 9),
29.       legend.position = "none",
30.       plot.margin = margin(10, 10, 10, 10)
31.     )
32. }
33. # --- Vẽ 5 biểu đồ ---
34. p1 <- make_column_plot(tang_truong_tb[tang_truong_tb$Bien == "Tổng tài sản", ],
35.                        "Tăng trưởng TB - Tổng tài sản", "skyblue", "blue")
36. p2 <- make_column_plot(tang_truong_tb[tang_truong_tb$Bien == "Tiền mặt vàng", ],
37.                        "Tăng trưởng TB - Tiền mặt vàng", "khaki", "goldenrod")
38. p3 <- make_column_plot(tang_truong_tb[tang_truong_tb$Bien == "Các khoản phải thu", ],
39.                        "Tăng trưởng TB - Các khoản phải thu", "lightgreen", "darkgreen")
40. p4 <- make_column_plot(tang_truong_tb[tang_truong_tb$Bien == "Tài sản cố định", ],
41.                        "Tăng trưởng TB - Tài sản cố định", "plum", "purple")
42. p5 <- make_column_plot(tang_truong_tb[tang_truong_tb$Bien == "Tiền gửi tại NHNN", ],
43.                        "Tăng trưởng TB - Tiền gửi tại NHNN", "salmon", "darkred")
44. # --- Ghép bố cục bằng patchwork (không lỗi, không cảnh báo) ---
45. (p1 + p2) / (p3 + p4) / p5

Biểu đồ cột thể hiện tỷ lệ tăng trưởng trung bình năm của từng nhóm tài sản (Tổng tài sản, Tiền mặt vàng, Các khoản phải thu, Tài sản cố định và Tiền gửi tại NHNN). Các cột màu biểu diễn giá trị tăng trưởng riêng từng biến, còn đường đỏ đứt đoạn thể hiện mức trung bình chung (Mean = 32.65%) của toàn bộ các biến. Nhờ đó, người xem dễ dàng so sánh mức tăng trưởng của từng biến so với trung bình, nhận diện biến nào tăng mạnh hơn hoặc thấp hơn mức trung bình.

Tổng tài sản (19.25%) và Tiền mặt vàng (6.81%) có tốc độ tăng thấp hơn mức trung bình phản ánh tăng trưởng chậm, chiến lược an toàn.

Các khoản phải thu (30.24%) và Tài sản cố định (31.44%) có tốc độ tăng xấp xỉ trung bình thể hiện hoạt động đầu tư và tín dụng duy trì ổn định.

Tiền gửi tại NHNN (75.53%) cao vượt trội so với mức trung bình cho thấy ngân hàng tăng mạnh phần dự trữ bắt buộc, thể hiện xu hướng thận trọng và tuân thủ quy định thanh khoản.

Biểu đồ giúp trực quan hóa mức tăng trưởng trung bình giữa các nhóm tài sản, thể hiện rõ nhóm tăng nhanh, nhóm tăng chậm, và vị trí tương quan so với mức trung bình toàn hệ thống.

2.5.5 Biểu đố so sánh mức độ tăng trường trung bình tổng tài sản trước và sau covid

1. # Nạp thư viện
2. library(ggplot2)
3. # Nhập kết quả tính
4. Truoc <- 262892564
5. Sau <- 639211610
6. ChenhLech <- 376319045
7. # Tạo bảng dữ liệu
8. data_covid <- data.frame(
9.   GiaiDoan = c("Trước Covid", "Sau Covid"),
10.   GiaTri = c(Truoc, Sau)
11. )
12. # Vẽ biểu đồ 5 layer
13. ggplot(data_covid, aes(x = GiaiDoan, y = GiaTri, fill = GiaiDoan)) +
14.   # Layer 1: Cột
15.   geom_col(width = 0.5, color = "black", alpha = 0.85) +
16. 
17.   # Layer 2: Nhãn giá trị nằm trong cột
18.   geom_text(aes(label = format(round(GiaTri, 0), big.mark = ",")),
19.             vjust = 1.5, size = 5, fontface = "bold", color = "white") +
20. 
21.   # Layer 3: Đường chênh lệch có mũi tên
22.   geom_segment(aes(x = 1, xend = 2, y = Truoc, yend = Sau),
23.                color = "red", linetype = "dashed", linewidth = 1.2,
24.                arrow = arrow(length = unit(0.25, "cm"))) +
25. 
26.   # Layer 4: Nhãn chênh lệch (đặt cao hơn đường)
27.   geom_text(aes(x = 1.5, 
28.                 y = (Truoc + Sau)/2 + (Sau - Truoc)*0.20,
29.                 label = paste0("Chênh lệch = ", format(round(ChenhLech, 0), big.mark = ","))),
30.             color = "red", size = 5, fontface = "bold") +
31. 
32.   # Layer 5: Màu và theme
33.   scale_fill_manual(values = c("steelblue", "skyblue")) +
34.   labs(
35.     title = "So sánh mức tăng trưởng trung bình Tổng tài sản\nTrước và Sau Covid",
36.     x = NULL, y = "Giá trị trung bình (VND)"
37.   ) +
38.   theme_minimal(base_size = 12) +
39.   theme(
40.     plot.title = element_text(face = "bold", size = 13, hjust = 0.5),
41.     legend.position = "none",
42.     axis.text = element_text(size = 11)
43.   )

Biểu đồ được xây dựng bằng hàm ggplot() với 5 lớp (layer) thể hiện mức tăng trưởng Tổng tài sản giữa hai giai đoạn. Lệnh geom_col() vẽ hai cột biểu thị giá trị trung bình, geom_text() hiển thị số liệu trực tiếp trong cột giúp dễ đọc. Đường đỏ đứt có mũi tên được tạo bởi geom_segment() minh họa xu hướng tăng, còn nhãn “Chênh lệch = 376,319,045” dùng geom_text() để làm nổi bật sự khác biệt. Cuối cùng, theme_minimal() giúp bố cục rõ ràng và thẩm mỹ, làm nổi bật sự tăng trưởng rõ rệt sau Covid.

Kết quả thống kê cho thấy Tổng tài sản trung bình của ngân hàng trong giai đoạn Sau Covid đạt 639.211.610, cao hơn đáng kể so với mức 262.892.564 của Trước Covid. Mức chênh lệch tăng 376.319.045 phản ánh sự mở rộng mạnh mẽ về quy mô tài chính và năng lực huy động vốn sau đại dịch.

2.6 KẾT LUẬN

Đề tài “Phân tích dữ liệu tài chính Techcombank (2014–2023)” đã sử dụng ngôn ngữ R để thu thập, xử lý và trực quan hóa dữ liệu bằng các công cụ như ggplot2, readxl và kableExtra. Kết quả cho thấy tổng tài sản của Techcombank tăng gần 5 lần trong giai đoạn nghiên cứu, với tốc độ tăng trưởng trung bình 19,12%/năm, thể hiện khả năng mở rộng quy mô và quản trị vốn hiệu quả.

Phân tích so sánh hai giai đoạn Trước và Sau Covid cho thấy tổng tài sản trung bình tăng hơn 376.319.045 triệu đồng, chứng minh năng lực phục hồi và chiến lược phát triển bền vững của ngân hàng. Mối tương quan cao giữa tổng tài sản và tài sản cố định (r = 0.9769) khẳng định định hướng đầu tư dài hạn hợp lý. Nghiên cứu không chỉ minh chứng tính ứng dụng của R trong phân tích tài chính mà còn cho thấy Techcombank là một trong những ngân hàng tăng trưởng mạnh và ổn định nhất Việt Nam giai đoạn 2014–2023.

3 KẾT LUẬN CHUNG

Qua quá trình thực hiện bài báo cáo với sự hỗ trợ của phần mềm RStudio, em đã tiến hành các bước phân tích dữ liệu bao gồm xử lý dữ liệu thô, thống kê mô tả cơ bản và trực quan hóa dữ liệu đối với hai bộ dữ liệu: dữ liệu sức khỏe và báo cáo tài chính của Ngân hàng Techcombank.

Kết quả thu được cho thấy RStudio là một công cụ mạnh mẽ và linh hoạt trong việc xử lý, phân tích và trình bày dữ liệu. Ở giai đoạn xử lý dữ liệu, phần mềm giúp phát hiện và loại bỏ các giá trị thiếu, sai lệch và không đồng nhất, qua đó nâng cao chất lượng dữ liệu đầu vào. Giai đoạn thống kê cơ bản hỗ trợ việc mô tả, tóm tắt và đánh giá tổng quan các đặc điểm của dữ liệu, giúp rút ra những nhận định có cơ sở khoa học. Bên cạnh đó, việc trực quan hóa dữ liệU không chỉ giúp thể hiện kết quả sinh động mà còn hỗ trợ quá trình ra quyết định dựa trên dữ liệu .

Về thực tiễn hiện nay, việc ứng dụng R trong phân tích dữ liệu ngày càng phổ biến, đặc biệt trong các lĩnh vực tài chính, ngân hàng, kinh tế và y tế. RStudio không chỉ giúp người học củng cố kiến thức lý thuyết mà còn tạo điều kiện áp dụng kỹ năng lập trình vào thực tiễn nghiên cứu, xử lý dữ liệu đa ngành.

Trong tương lai, RStudio có thể được mở rộng ứng dụng sang các mô hình phân tích nâng cao hơn giúp dự báo xu hướng và đưa ra khuyến nghị chiến lược có độ chính xác cao hơn. Bản thân người học cũng có thể tiếp tục phát triển năng lực phân tích dữ liệu, kết hợp giữa tư duy định lượng và công cụ công nghệ để phục vụ cho công việc chuyên môn trong lĩnh vực kinh tế và marketing dữ liệu.

Qua bài báo cáo không chỉ giúp em nắm vững quy trình xử lý và phân tích dữ liệu bằng R, mà còn khẳng định tầm quan trọng của kỹ năng dữ liệu trong thời đại số hiện nay, tạo nền tảng vững chắc cho học tập và nghiên cứu trong thời gian tới.