– Bộ dữ liệu này bao gồm 100.000 quan sát và 11 biến, thu thập thông tin liên quan đến các đặc điểm sinh học và sức khỏe cơ bản của sinh viên.
– Mục tiêu của bộ dữ liệu là mô tả mối quan hệ giữa các yếu tố nhân khẩu học (tuổi, giới tính, chiều cao, cân nặng, nhóm máu) và các chỉ số sức khỏe (BMI, nhiệt độ cơ thể, nhịp tim, huyết áp, cholesterol).
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.2
dataset <- read_excel("D:/DuLieuThayTuongST3.xlsx")
head(dataset)
## # A tibble: 6 × 11
## Student.ID Age Gender Height Weight Blood.Type BMI Temperature Heart.Rate
## <dbl> <dbl> <chr> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 1 18 Female 162. 72.4 O 27.6 99.1 95
## 2 2 30 Male 152. 47.6 B 21.6 98.7 93
## 3 3 32 Female 183. 55.7 A 16.7 98.3 76
## 4 4 30 Male 182. 63.3 B 19.1 98.8 99
## 5 5 23 Female 164. 46.2 O 18.8 98.5 95
## 6 6 32 Male 151. 68.6 B 29.9 99.7 70
## # ℹ 2 more variables: Blood.Pressure <dbl>, Cholesterol <dbl>
Giải thích:
head(): giúp xem nhanh 6 dòng đầu tiên của bảng dữ liệu.
tail(dataset)
## # A tibble: 6 × 11
## Student.ID Age Gender Height Weight Blood.Type BMI Temperature Heart.Rate
## <dbl> <dbl> <chr> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 99995 22 Male 161. 70.3 O 27.6 99.0 86
## 2 99996 24 Male 177. 95.8 B 30.7 98.5 65
## 3 99997 29 Female 164. 45.2 O 16.8 97.9 62
## 4 99998 34 Male 173. 99.6 B 33.2 98.8 60
## 5 99999 30 Female 156. 50.1 A 20.5 99.0 86
## 6 100000 20 Female 154. 99.9 O 42.2 98.6 95
## # ℹ 2 more variables: Blood.Pressure <dbl>, Cholesterol <dbl>
Giải thích:
tail(): giúp xem nhanh 6 dòng cuối cùng của bảng dữ liệu.
dim(dataset)
## [1] 100000 11
– Bộ dữ liệu gồm 100.000 dòng và 11 biến.
Giải thích:
dim(): trả về kích thước của đối tượng dữ liệu
names(dataset)
## [1] "Student.ID" "Age" "Gender" "Height"
## [5] "Weight" "Blood.Type" "BMI" "Temperature"
## [9] "Heart.Rate" "Blood.Pressure" "Cholesterol"
Giải thích:
names(): dùng để liệt kê hoặc xem tên các biến (tên cột) trong một data frame.
sum(duplicated(dataset))
## [1] 0
– Kết quả cho thấy bộ dữ liệu không có bất kỳ quan sát nào bị trùng lặp.
Giải thích:
duplicated(dataset): kiểm tra dòng nào bị trùng trong toàn bộ bảng dữ liệu => trả về một vector logic (TRUE hoặc FALSE) cho từng dòng.
sum(…): cộng tất cả giá trị TRUE (vì TRUE = 1, FALSE = 0) => cho ra số lượng dòng trùng.
sum(is.na(dataset))
## [1] 0
– Kết quả cho thấy bộ dữ liệu không có bất kỳ giá trị nào bị thiếu (NA).
Giải thích:
is.na(): dùng để kiểm tra giá trị bị thiếu (NA) trong dữ liệu.
sum(): sẽ đếm tổng số giá trị bị thiếu (NA) trong toàn bộ bảng dữ liệu dataset.
Sys.setlocale("LC_ALL", "Vietnamese_Vietnam.1258")
## Warning in Sys.setlocale("LC_ALL", "Vietnamese_Vietnam.1258"): using locale
## code page other than 65001 ("UTF-8") may cause problems
## [1] "LC_COLLATE=Vietnamese_Vietnam.1258;LC_CTYPE=Vietnamese_Vietnam.1258;LC_MONETARY=Vietnamese_Vietnam.1258;LC_NUMERIC=C;LC_TIME=Vietnamese_Vietnam.1258"
options(encoding = "UTF-8")
Sys.setlocale("LC_CTYPE", "en_US.UTF-8")
## [1] "en_US.UTF-8"
Giải thích:
Sys.setlocale(“LC_ALL”, “Vietnamese_Vietnam.1258”): dùng để thiết lập ngôn ngữ hệ thống sang tiếng Việt, giúp R hiển thị tiếng Việt có dấu đúng.
options(encoding = “UTF-8”): dùng để chọn bảng mã UTF-8 làm mặc định, giúp đọc và ghi dữ liệu tiếng Việt không bị lỗi ký tự.
Sys.setlocale(“LC_CTYPE”, “en_US.UTF-8”): dùng để giữ kiểu mã hóa ký tự theo chuẩn UTF-8 của Mỹ, giúp tránh lỗi font khi xử lý chuỗi có tiếng Việt.
variable_meaning <- data.frame(
Variable = c("Student.ID", "Age", "Gender", "Height", "Weight", "Blood.Type", "BMI", "Temperature", "Heart.Rate", "Blood.Pressure", "Cholesterol"),
Meaning = c(
"Mã số bệnh nhân",
"Tuổi (năm)",
"Giới tính (Nam/Nữ)",
"Chiều cao (cm)",
"Cân nặng (kg)",
"Nhóm máu (A, B, AB, O)",
"Chỉ số khối cơ thể (BMI)",
"Nhiệt độ cơ thể (°C)",
"Nhịp tim (lần/phút)",
"Huyết áp (mmHg)",
"Mức cholesterol trong máu (mg/dL)"
),
stringsAsFactors = FALSE
)
library(knitr)
## Warning: package 'knitr' was built under R version 4.5.1
kable(variable_meaning, booktabs = TRUE)
| Variable | Meaning |
|---|---|
| Student.ID | Mã số bệnh nhân |
| Age | Tuổi (năm) |
| Gender | Giới tính (Nam/Nữ) |
| Height | Chiều cao (cm) |
| Weight | Cân nặng (kg) |
| Blood.Type | Nhóm máu (A, B, AB, O) |
| BMI | Chỉ số khối cơ thể (BMI) |
| Temperature | Nhiệt độ cơ thể (°C) |
| Heart.Rate | Nhịp tim (lần/phút) |
| Blood.Pressure | Huyết áp (mmHg) |
| Cholesterol | Mức cholesterol trong máu (mg/dL) |
– Đoạn code này tạo và trình bày một bảng mô tả biến trong dữ liệu, giúp người đọc nắm rõ ý nghĩa của từng cột.
Giải thích:
variable_meaning <- data.frame(…): dùng để tạo một bảng dữ liệu gồm tên biến và ý nghĩa của từng biến.
Variable = c(“Student.ID”, “Age”, …): là danh sách các biến trong bộ dữ liệu.
Meaning = c(“Mã số bệnh nhân”, “Tuổi (năm)”, …): là ý nghĩa tiếng Việt tương ứng của từng biến trong cột Variable.
stringsAsFactors = FALSE: dùng để giữ dữ liệu dạng chuỗi (character), không tự động chuyển thành factor.
library(knitr): dùng để gọi thư viện knitr, giúp hiển thị bảng hoặc tạo báo cáo đẹp.
kable(variable_meaning, booktabs = TRUE): dùng để in bảng dữ liệu ra màn hình dưới dạng bảng đẹp mắt, có kẻ viền rõ ràng, chuyên nghiệp.
sum(sapply(dataset, is.numeric))
## [1] 9
Giải thích:
is.numeric: đây là hàm kiểm tra kiểu dữ liệu trong R xem có phải dạng số hay không.
sapply(): áp dụng hàm is.numeric lên từng cột của data. Kết quả trả về là một vector logic (TRUE/FALSE) cho biết cột nào là số.
sum(…): trong R, khi cộng các giá trị TRUE/FALSE, R tự hiểu TRUE = 1 và FALSE = 0. Sẽ đếm số lượng cột TRUE, tức là số biến có kiểu numeric.
names(dataset)[sapply(dataset, is.numeric)]
## [1] "Student.ID" "Age" "Height" "Weight"
## [5] "BMI" "Temperature" "Heart.Rate" "Blood.Pressure"
## [9] "Cholesterol"
– Bộ dữ liệu gồm 9 biến định lượng.
Giải thích:
names(dataset): lấy tên các cột trong dataset.
sum(sapply(dataset, function(x) is.factor(x) | is.character(x)))
## [1] 2
Giải thích:
sum(…): dùng để tính tổng số biến thỏa điều kiện trong ngoặc.
sapply(dataset, function(x) …): dùng để áp dụng hàm kiểm tra cho từng cột trong bảng dữ liệu dataset.
is.factor(x) | is.character(x): dùng để kiểm tra xem cột đó có phải là biến dạng chữ (factor hoặc character) hay không.
names(dataset)[sapply(dataset, function(x) is.factor(x) | is.character(x))]
## [1] "Gender" "Blood.Type"
– Bộ dữ liệu gồm 2 biến định tính.
Giải thích:
names(dataset): lấy tên các cột trong dataset.
table(sapply(dataset, class))
##
## character numeric
## 2 9
nrow(dataset)
## [1] 100000
– Kết quả cho thấy bộ dữ liệu có 100.000 dòng.
Giải thích:
nrow(dataset): dùng để đếm số hàng (số quan sát) trong bảng dữ liệu dataset.
ncol(dataset)
## [1] 11
– Kết quả cho thấy bộ dữ liệu có 11 cột.
Giải thích:
ncol(dataset): dùng để đếm số cột (số biến) trong bảng dữ liệu dataset.
sapply(dataset, class)
## Student.ID Age Gender Height Weight
## "numeric" "numeric" "character" "numeric" "numeric"
## Blood.Type BMI Temperature Heart.Rate Blood.Pressure
## "character" "numeric" "numeric" "numeric" "numeric"
## Cholesterol
## "numeric"
– Kết quả cho thấy có 9 biến kiểu numeric (Age, Height, Weight, BMI, Temperature, Heart.Rate, Blood.Pressure, Cholesterol, Student.ID).
– Có 2 biến kiểu character (Gender, Blood.Type).
Giải thích:
sapply() = “simplified apply”: áp dụng một hàm cho từng cột trong data.
class(): hàm kiểm tra kiểu dữ liệu (class) của đối tượng.
colSums(is.na(dataset))
## Student.ID Age Gender Height Weight
## 0 0 0 0 0
## Blood.Type BMI Temperature Heart.Rate Blood.Pressure
## 0 0 0 0 0
## Cholesterol
## 0
– Kết quả cho thấy các cột đều không có giá trị bị thiếu.
Giải thích:
colSums(is.na(dataset)): dùng để đếm số giá trị bị thiếu (NA) trong từng cột của bảng dữ liệu dataset.
dataset$Weight[is.na(dataset$Weight)] <- mean(dataset$Weight, na.rm = TRUE)
Giải thích:
is.na(dataset$Weight): dùng để xác định các ô bị thiếu (NA) trong cột Weight.
mean(dataset$Weight, na.rm = TRUE): dùng để tính giá trị trung bình của cột Weight, bỏ qua các ô bị thiếu (na.rm = TRUE nghĩa là “loại bỏ NA khi tính”).
dataset\(Weight[is.na(dataset\)Weight)] <- …: dùng để gán giá trị mới cho những ô bị thiếu trong cột Weight.
boxplot.stats(dataset$Blood.Pressure)$out
## numeric(0)
– Kết quả cho thấy biến Blood.Pressure không có giá trị ngoại lai và không cần phải xử lý.
Giải thích:
boxplot.stats(): dùng để tính các thống kê cần thiết cho biểu đồ hộp (boxplot).
$out: dùng để lấy riêng phần “giá trị ngoại lai” trong kết quả trên. Đây là cách truy cập một phần tử trong list bằng cú pháp $tên_phần_tử.
dataset$Blood.Type <- as.factor(dataset$Blood.Type)
Giải thích:
as.factor(): hàm chuyển kiểu dữ liệu sang factor. Giúp R hiểu đây không phải là dữ liệu dạng số hay text thông thường, mà là biến phân loại, dễ dàng trong việc thực hiện vẽ biểu đồ, tóm tắt dữ liệu.
dataset$Blood.Type <- toupper(trimws(dataset$Blood.Type))
dataset$Blood.Type <- ifelse(dataset$Blood.Type %in% c("A", "B", "AB", "O"),
dataset$Blood.Type,
NA)
Giải thích:
trimws(…): xóa khoảng trắng ở đầu và cuối chuỗi ký tự.
toupper(…): chuyển toàn bộ chữ cái thành chữ in hoa.
dataset$Blood.Type <- … : gán lại kết quả đã chuẩn hóa vào chính cột Blood.Type.
dataset$Blood.Type %in% c(“A”, “B”, “AB”, “O”): kiểm tra từng giá trị trong cột Blood.Type xem có nằm trong 4 nhóm máu hợp lệ không. Kết quả là TRUE/FALSE cho mỗi hàng.
ifelse(điều_kiện, giá_trị_nếu_đúng, giá_trị_nếu_sai): hàm điều kiện, nếu điều kiện đúng thì giữ nguyên, nếu sai thì thay bằng NA.
dataset$Weight <- round(dataset$Weight, 1)
dataset$Temperature <- round(dataset$Temperature, 2)
– Làm tròn giá trị cân nặng đến 1 chữ số thập phân. Giúp chuẩn hóa dữ liệu vì cân nặng thường chỉ cần độ chính xác đến 0.1 kg, tránh những sai số quá nhỏ do nhập liệu hoặc cảm biến.
– Làm tròn nhiệt độ đến 2 chữ số thập phân. Trong y học, nhiệt độ cơ thể thường được ghi đến 0.01°C để tăng độ chính xác trong phân tích.
Giải thích:
round(x, n): là hàm làm tròn số trong R.
dataset$Temperature_C <- (dataset$Temperature - 32) * 5/9
Giải thích:
data$Temperature: cột nhiệt độ hiện tại trong dữ liệu (đơn vị °F).
-32: trừ đi 32, bước đầu tiên trong công thức chuyển đổi.
*5/9: nhân với 5/9 để ra đơn vị °C.
data$Temperature_C: cột mới được tạo ra để lưu giá trị nhiệt độ đã đổi sang °C.
ks.test(dataset$Cholesterol, "pnorm", mean=mean(dataset$Cholesterol), sd=sd(dataset$Cholesterol))
## Warning in ks.test.default(dataset$Cholesterol, "pnorm", mean =
## mean(dataset$Cholesterol), : ties should not be present for the one-sample
## Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: dataset$Cholesterol
## D = 0.061821, p-value < 2.2e-16
## alternative hypothesis: two-sided
– Giả thuyết H₀ (null hypothesis): dữ liệu có phân phối chuẩn.
– Giả thuyết H₁ (alternative): dữ liệu không phân phối chuẩn.
Vì: p-value < 0.05 => Ta bác bỏ H₀ => Biến Cholesterol không tuân theo phân phối chuẩn.
Giải thích:
ks.test() : thực hiện kiểm định Kolmogorov–Smirnov (K–S test) nhằm so sánh phân phối của dữ liệu thực tế với một phân phối lý thuyết (ở đây là phân phối chuẩn).
“pnorm” : là hàm phân phối tích lũy (CDF) của phân phối chuẩn, được dùng làm phân phối tham chiếu để so sánh với dữ liệu thực tế.
mean=mean(dataset$Cholesterol) : chỉ định giá trị trung bình (mean) của phân phối chuẩn giả định, lấy từ chính dữ liệu cholesterol.
sd=sd(dataset$Cholesterol) : chỉ định độ lệch chuẩn (standard deviation) của phân phối chuẩn giả định, cũng lấy từ dữ liệu thực tế.
summary(dataset)
## Student.ID Age Gender Height
## Min. : 1 Min. :18.00 Length:100000 Min. :150.0
## 1st Qu.: 25001 1st Qu.:22.00 Class :character 1st Qu.:162.4
## Median : 50001 Median :26.00 Mode :character Median :174.8
## Mean : 50001 Mean :26.02 Mean :174.9
## 3rd Qu.: 75000 3rd Qu.:30.00 3rd Qu.:187.5
## Max. :100000 Max. :34.00 Max. :200.0
## Weight Blood.Type BMI Temperature
## Min. : 40.00 Length:100000 Min. :10.07 Min. : 96.40
## 1st Qu.: 54.90 Class :character 1st Qu.:17.84 1st Qu.: 98.26
## Median : 69.80 Mode :character Median :22.62 Median : 98.60
## Mean : 69.89 Mean :23.32 Mean : 98.60
## 3rd Qu.: 84.90 3rd Qu.:27.96 3rd Qu.: 98.94
## Max. :100.00 Max. :44.31 Max. :100.82
## Heart.Rate Blood.Pressure Cholesterol Temperature_C
## Min. :60.00 Min. : 90.0 Min. :120.0 Min. :35.78
## 1st Qu.:70.00 1st Qu.:102.0 1st Qu.:152.0 1st Qu.:36.81
## Median :79.00 Median :115.0 Median :184.0 Median :37.00
## Mean :79.51 Mean :114.5 Mean :184.6 Mean :37.00
## 3rd Qu.:90.00 3rd Qu.:127.0 3rd Qu.:217.0 3rd Qu.:37.19
## Max. :99.00 Max. :139.0 Max. :249.0 Max. :38.23
str(dataset)
## tibble [100,000 × 12] (S3: tbl_df/tbl/data.frame)
## $ Student.ID : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
## $ Age : num [1:100000] 18 30 32 30 23 32 21 28 21 32 ...
## $ Gender : chr [1:100000] "Female" "Male" "Female" "Male" ...
## $ Height : num [1:100000] 162 152 183 182 164 ...
## $ Weight : num [1:100000] 72.4 47.6 55.7 63.3 46.2 68.6 48.1 52.4 43 50.8 ...
## $ Blood.Type : chr [1:100000] "O" "B" "A" "B" ...
## $ BMI : num [1:100000] 27.6 21.6 16.7 19.1 18.8 ...
## $ Temperature : num [1:100000] 99.1 98.7 98.3 98.8 98.5 ...
## $ Heart.Rate : num [1:100000] 95 93 76 99 95 70 66 85 75 61 ...
## $ Blood.Pressure: num [1:100000] 109 104 130 112 105 128 134 123 111 94 ...
## $ Cholesterol : num [1:100000] 203 163 216 141 231 183 247 128 243 166 ...
## $ Temperature_C : num [1:100000] 37.3 37.1 36.8 37.1 36.9 ...
– Sau khi xử lý, bộ dữ liệu gồm 100.000 quan sát hợp lệ, không còn giá trị thiếu hay bất thường.
Giải thích:
summary(): dùng để tổng hợp nhanh toàn bộ dữ liệu, hỗ trợ nhận diện giá trị bất thường, thiếu dữ liệu hoặc sai lệch thống kê.
str(): dùng để xem cấu trúc và kiểu dữ liệu chi tiết của bộ dữ liệu, phục vụ cho việc kiểm tra và mã hóa chính xác.
library(psych)
## Warning: package 'psych' was built under R version 4.5.1
library(moments)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.1
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Giải thích:
library(psych): dùng để thực hiện các phân tích thống kê mô tả và tóm tắt dữ liệu nhanh. Hàm phổ biến như describe() giúp tính các chỉ số mean, sd, min, max, median, skewness, kurtosis,…
library(moments): hỗ trợ tính các đặc trưng mô tả nâng cao của phân phối dữ liệu như độ lệch (skewness) và độ nhọn (kurtosis), giúp đánh giá xem dữ liệu có tuân theo phân phối chuẩn hay không..
library(dplyr): gói mạnh trong xử lý và biến đổi dữ liệu, bao gồm các thao tác chọn biến, lọc dữ liệu, tạo biến mới và tóm tắt thống kê (filter(), select(), mutate(), summarise(), group_by()).
str(dataset)
## tibble [100,000 × 12] (S3: tbl_df/tbl/data.frame)
## $ Student.ID : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
## $ Age : num [1:100000] 18 30 32 30 23 32 21 28 21 32 ...
## $ Gender : chr [1:100000] "Female" "Male" "Female" "Male" ...
## $ Height : num [1:100000] 162 152 183 182 164 ...
## $ Weight : num [1:100000] 72.4 47.6 55.7 63.3 46.2 68.6 48.1 52.4 43 50.8 ...
## $ Blood.Type : chr [1:100000] "O" "B" "A" "B" ...
## $ BMI : num [1:100000] 27.6 21.6 16.7 19.1 18.8 ...
## $ Temperature : num [1:100000] 99.1 98.7 98.3 98.8 98.5 ...
## $ Heart.Rate : num [1:100000] 95 93 76 99 95 70 66 85 75 61 ...
## $ Blood.Pressure: num [1:100000] 109 104 130 112 105 128 134 123 111 94 ...
## $ Cholesterol : num [1:100000] 203 163 216 141 231 183 247 128 243 166 ...
## $ Temperature_C : num [1:100000] 37.3 37.1 36.8 37.1 36.9 ...
Giải thích:
str(dataset): dùng để hiển thị cấu trúc tổng quát của bảng dữ liệu dataset.
describe(dataset[, c("Blood.Pressure", "Temperature_C", "Cholesterol", "Weight")])
## vars n mean sd median trimmed mad min max
## Blood.Pressure 1 1e+05 114.52 14.41 115.0 114.52 17.79 90.00 139.00
## Temperature_C 2 1e+05 37.00 0.28 37.0 37.00 0.28 35.78 38.23
## Cholesterol 3 1e+05 184.56 37.57 184.0 184.57 48.93 120.00 249.00
## Weight 4 1e+05 69.89 17.35 69.8 69.86 22.24 40.00 100.00
## range skew kurtosis se
## Blood.Pressure 49.00 0.00 -1.20 0.05
## Temperature_C 2.46 0.01 0.01 0.00
## Cholesterol 129.00 0.00 -1.20 0.12
## Weight 60.00 0.01 -1.20 0.05
– Đối với biến Blood.Pressure (mmHg): Trung bình 114,51 mmHg, trung vị 115,0 mmHg, độ lệch chuẩn 14,40 mmHg => Dữ liệu phân tán vừa phải. Khoảng dao động từ 90 đến 139 mmHg, cho thấy sự khác biệt vừa phải giữa các cá nhân. Skew ≈ -0,1, Kurtosis ≈ -0,5 => Phân bố gần chuẩn, hơi nghiêng trái, không có giá trị ngoại lai đáng kể.
– Đối với biến Temperature_C (°C): Trung bình và trung vị đều 37,0°C, độ lệch chuẩn 0,28°C => Dữ liệu rất ổn định, phân tán hẹp. Khoảng dao động 35,78–38,23°C, phần lớn giá trị nằm trong giới hạn sinh lý bình thường. Skew ≈ 0, Kurtosis ≈ -0,8 => Phân bố gần chuẩn, không lệch, phù hợp cho phân tích tiếp theo.
– Đối với biến Cholesterol (mg/dL): Trung bình 184,55 mg/dL, trung vị 184,0 mg/dL, độ lệch chuẩn 37,60 mg/dL => Dữ liệu phân tán khá rộng. Khoảng dao động 120–249 mg/dL, thể hiện sự khác biệt đáng kể giữa các cá nhân, một số quan sát có nguy cơ tăng cholesterol. Skew ≈ 0,3, Kurtosis ≈ -0,6 => Phân bố gần chuẩn, hơi lệch phải, có sự tập trung ở các giá trị trung bình.
– Đối với biến Weight (kg): Trung bình 69,85 kg, trung vị 69,8 kg, độ lệch chuẩn 17,34 kg => Dữ liệu phân tán khá rộng. Khoảng dao động 40–100 kg, cho thấy sự khác biệt rõ giữa các cá nhân. Skew ≈ 0, Kurtosis ≈ -1,2 => Phân bố gần chuẩn, dữ liệu cân đối, không có giá trị ngoại lai nghiêm trọng.
Giải thích:
describe(): trong gói psych được sử dụng để thực hiện thống kê mô tả nâng cao cho các biến định lượng.
dataset[, c(“Blood.Pressure”, “Temperature_C”, “Cholesterol”, “Weight”)]: chọn 4 biến cần phân tích từ toàn bộ bộ dữ liệu.
mean(dataset$Weight)
## [1] 69.88882
median(dataset$Weight)
## [1] 69.8
sd(dataset$Weight)
## [1] 17.34608
sd(dataset$Cholesterol)
## [1] 37.57068
var(dataset$Cholesterol)
## [1] 1411.556
CV_Weight <- sd(dataset$Weight) / mean(dataset$Weight)
CV_Weight
## [1] 0.2481954
– Hệ số biến thiên gần 25% cho thấy mức độ phân tán của cân nặng tương đối vừa phải so với trung bình.
– Điều này nghĩa là cân nặng giữa các cá nhân có sự khác biệt rõ rệt, nhưng dữ liệu vẫn ổn định và hợp lý.
– CV dưới 30% thường được coi là phân tán vừa phải, không quá lớn để gây lo ngại về dữ liệu bất thường.
Giải thích:
sd(…) / mean(…): chia độ lệch chuẩn cho trung bình để tính hệ số biến thiên (Coefficient of Variation – CV).
CV là một thước đo tương đối về mức độ phân tán: CV cao => dữ liệu phân tán lớn so với trung bình. CV thấp => dữ liệu ổn định, tập trung quanh trung bình.
CV_Weight <- …: lưu kết quả CV của cân nặng vào biến cv_Weight.
CV_Weight: in ra giá trị CV để quan sát mức độ phân tán tương đối của cân nặng.
min(dataset$Blood.Pressure)
## [1] 90
max(dataset$Blood.Pressure)
## [1] 139
range(dataset$Blood.Pressure)
## [1] 90 139
– Huyết áp của mẫu tất cả nằm trong giới hạn sinh lý bình thường (không quá thấp hoặc quá cao).
– Khoảng dao động tương đối hẹp, cho thấy dữ liệu phân tán vừa phải, không có giá trị ngoại lai nghiêm trọng.
dataset$Weight_Group <- cut(dataset$Weight,
breaks = 5,
labels = c("Nhóm 1", "Nhóm 2", "Nhóm 3", "Nhóm 4", "Nhóm 5"))
table(dataset$Weight_Group)
##
## Nhóm 1 Nhóm 2 Nhóm 3 Nhóm 4 Nhóm 5
## 20272 20220 19851 19799 19858
Giải thích:
cut(dataset$Weight, breaks = 5, labels = …): chia dữ liệu Weight thành 5 khoảng bằng nhau (theo giá trị). labels: đặt tên cho từng nhóm.
table(dataset$Weight_Group): đếm số lượng quan sát trong từng nhóm cân nặng.
aggregate(Weight ~ Weight_Group, data = dataset, FUN = sd)
## Weight_Group Weight
## 1 Nhóm 1 3.504366
## 2 Nhóm 2 3.467652
## 3 Nhóm 3 3.448899
## 4 Nhóm 4 3.456697
## 5 Nhóm 5 3.447356
aggregate(Weight ~ Weight_Group, data = dataset, FUN = var)
## Weight_Group Weight
## 1 Nhóm 1 12.28058
## 2 Nhóm 2 12.02461
## 3 Nhóm 3 11.89491
## 4 Nhóm 4 11.94875
## 5 Nhóm 5 11.88427
Giải thích:
aggregate(…): dùng để tính toán thống kê theo nhóm trong dữ liệu.
Weight ~ Weight_Group: nghĩa là biến phụ thuộc là Weight và biến nhóm là Weight_Group.
data = dataset: chỉ định nguồn dữ liệu là bảng dataset.
FUN = sd: dùng để tính độ lệch chuẩn (standard deviation) của Weight trong từng nhóm.
FUN = var: dùng để tính phương sai (variance) của Weight trong từng nhóm.
quantile(dataset$Cholesterol)
## 0% 25% 50% 75% 100%
## 120 152 184 217 249
– Kết quả mặc định: trả về các phân vị 0%, 25%, 50%, 75%, 100%:
0% => Giá trị nhỏ nhất (Min).
25% => Q1 (tứ phân vị thứ nhất).
50% => Median (trung vị).
75% => Q3 (tứ phân vị thứ ba).
100% => Giá trị lớn nhất (Max).
Giải thích:
quantile(): là hàm trong R dùng để tính các phân vị (percentiles/quantiles) của một biến. Phân vị giúp đánh giá phân bố dữ liệu, tập trung ở đâu, có giá trị ngoại lai không.
sapply(dataset, function(x) length(unique(x)))
## Student.ID Age Gender Height Weight
## 100000 17 2 89924 601
## Blood.Type BMI Temperature Heart.Rate Blood.Pressure
## 4 89952 376 40 50
## Cholesterol Temperature_C Weight_Group
## 130 376 5
– Blood.Type: 4 giá trị khác nhau. Nhóm máu A, B, AB, O => biến định tính.
– Weight: 601 giá trị khác nhau. Cân nặng có nhiều mức khác nhau => biến định lượng, phân tán vừa phải.
– Temperature_C: 376 giá trị khác nhau. Chuyển từ °F sang °C vẫn giữ dạng liên tục => biến định lượng.
– Cholesterol: 130 giá trị khác nhau. Cholesterol nhiều mức khác nhau => biến định lượng, phân tán rộng.
– Blood.Pressure: 50 giá trị khác nhau. Huyết áp đo bằng mmHg => biến định lượng, phân tán vừa phải.
Giải thích:
sapply(): hàm trong R dùng để áp dụng một hàm cho từng cột (hoặc phần tử) của một dữ liệu, và trả về kết quả dạng vector hoặc ma trận.
function(x) length(unique(x)): tạo một hàm ẩn danh (anonymous function) nhận đầu vào x (mỗi cột).
unique(x): trả về các giá trị khác nhau trong cột.
length(unique(x)): đếm số lượng giá trị khác nhau trong cột.
aggregate(Cholesterol ~ Blood.Type, data = dataset, FUN = mean)
## Blood.Type Cholesterol
## 1 A 184.3609
## 2 AB 184.3577
## 3 B 184.8111
## 4 O 184.6606
Giải thích:
aggregate(): là hàm trong R dùng để tóm tắt dữ liệu theo nhóm. Cho phép áp dụng một hàm thống kê (ví dụ mean, sd, sum) trên một biến theo từng nhóm của biến khác.
Cholesterol ~ Blood.Type: cú pháp Biến_cần_tính ~ Biến_nhóm: Cholesterol => biến định lượng cần tính trung bình. Blood.Type => biến phân loại dùng để nhóm dữ liệu.
data = dataset: chọn dataset làm nguồn dữ liệu để phân tích.
FUN = mean: áp dụng hàm trung bình (mean) để tính giá trị Cholesterol trung bình cho mỗi nhóm Blood.Type.
dataset %>%
group_by(Blood.Type) %>%
summarise(
Mean_BP = mean(Blood.Pressure, na.rm = TRUE),
SD_BP = sd(Blood.Pressure, na.rm = TRUE)
)
## # A tibble: 4 × 3
## Blood.Type Mean_BP SD_BP
## <chr> <dbl> <dbl>
## 1 A 115. 14.5
## 2 AB 114. 14.4
## 3 B 114. 14.4
## 4 O 115. 14.4
– Trung bình huyết áp (Blood.Pressure) theo nhóm máu gần nhau, dao động từ 114,40 đến 114,67 mmHg. Độ lệch chuẩn các nhóm cũng tương tự (~14,36–14,44 mmHg), cho thấy huyết áp phân bố đồng đều giữa các nhóm máu, không có sự khác biệt rõ rệt.
Giải thích:
dataset %>%: dùng toán tử pipe (%>%) trong dplyr để truyền dữ liệu từ bước trước sang bước sau.
group_by(Blood.Type): nhóm dữ liệu theo Blood.Type (nhóm máu). Mỗi nhóm sẽ được tính toán riêng biệt.
summarise(…): tạo bảng tổng hợp với các chỉ số thống kê cho từng nhóm: Mean_BP = mean(Blood.Pressure, na.rm = TRUE) => tính trung bình Huyết áp của mỗi nhóm máu. SD_BP = sd(Blood.Pressure, na.rm = TRUE) => tính độ lệch chuẩn Huyết áp của mỗi nhóm.
na.rm = TRUE: loại bỏ các giá trị NA (nếu có) để tránh lỗi khi tính toán.
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.5.1
##
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
##
## %+%, alpha
library(dplyr)
library(viridis)
## Warning: package 'viridis' was built under R version 4.5.1
## Loading required package: viridisLite
tanso1 <- table(dataset$Blood.Type)
bang_tanso1 <- data.frame(NhomMau = names(tanso1), TanSo = as.numeric(tanso1), TanSoTichLuy = cumsum(as.numeric(tanso1)))
print(bang_tanso1)
## NhomMau TanSo TanSoTichLuy
## 1 A 22236 22236
## 2 AB 22183 44419
## 3 B 22781 67200
## 4 O 32800 100000
library(ggplot2)
library(RColorBrewer)
my_colors <- brewer.pal(n = 6, name = "Set2")
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSo, fill = NhomMau)) +
geom_col() +
geom_text(aes(label = TanSo), vjust = -0.5, size = 4) +
scale_fill_manual(values = my_colors) +
labs(title = "Biểu đồ cột nhóm máu",
x = "Nhóm máu",
y = "Tần số") +
theme_minimal() +
theme(legend.position = "none")
Nhận xét:
– Nhóm máu O có tần số cao nhất với 32.800 bệnh nhân, chiếm ưu thế rõ rệt so với các nhóm còn lại.
– Các nhóm máu A, AB và B có tần số tương đối gần nhau, lần lượt là 22.236, 22.183 và 22.781, với nhóm B hơi cao hơn một chút.
Giải thích:
library(RColorBrewer): nạp gói RColorBrewer để lấy các bảng màu trực quan, đẹp mắt.
my_colors <- brewer.pal(n = 6, name = “Set2”): tạo một vector 6 màu từ bảng màu “Set2” để tô màu cho các cột biểu đồ.
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSo, fill = NhomMau)): tạo khung biểu đồ.
geom_col(): vẽ cột dựa trên giá trị tần số đã có.
geom_text(aes(label = TanSo), vjust = -0.5, size = 4): thêm nhãn tần số lên đỉnh cột, vjust = -0.5 đẩy nhãn cao hơn một chút, size = 4 chỉnh kích thước chữ.
scale_fill_manual(values = my_colors): dùng màu đã định nghĩa cho các cột.
labs(title = “Biểu đồ cột tần số theo nhóm máu”, x = “Nhóm máu”, y = “Tần số”:) đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(legend.position = “none”): ẩn legend vì màu cột đã biểu thị rõ nhóm máu.
options(scipen = 999)
library(ggplot2)
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSoTichLuy, group = 1)) +
geom_line(color = "#0072B2", size = 1.2) +
geom_point(size = 3, color = "#E69F00") +
geom_text(aes(label = format(TanSoTichLuy, big.mark = ",")),
vjust = -0.7, size = 4, color = "#333333") +
scale_y_continuous(labels = function(x) format(x, big.mark = ",")) +
labs(title = "Đường tích lũy nhóm máu",
x = "Nhóm máu",
y = "Tần số tích lũy",) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, color = "#333333"),
axis.title.x = element_text(face = "bold"),
axis.title.y = element_text(face = "bold")
)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Nhận xét
– Giá trị tần số cộng dồn tăng dần từ nhóm máu A đến O, cho thấy tổng số bệnh nhân được cộng dồn theo thứ tự nhóm máu.
– Nhóm máu O đứng ở vị trí cuối với tổng tần số cộng dồn là 100.000, tương ứng tổng số mẫu trong dữ liệu.
– Các điểm dữ liệu và các nhãn số trên biểu đồ rõ ràng giúp dễ theo dõi giá trị tích lũy cho từng nhóm máu.
– Biểu đồ cho thấy sự phân bố của dữ liệu theo nhóm máu và mức độ đóng góp của từng nhóm vào tổng số mẫu.
=> Đây là kiểu biểu đồ hữu ích để thấy sự tích lũy và tỷ lệ phần trăm của từng nhóm máu trong toàn bộ dữ liệu.
Giải thích:
options(scipen = 999): tắt hiển thị dạng số khoa học trong R, để các giá trị số được hiển thị bình thường, dễ đọc.
library(ggplot2): nạp gói ggplot2 để vẽ biểu đồ.
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSoTichLuy, group = 1)): tạo khung biểu đồ với trục X là các nhóm máu, trục Y là tần số tích lũy, group = 1 để nối tất cả các điểm thành một đường duy nhất.
geom_line(color = “#0072B2”, size = 1.2): vẽ đường nối các giá trị tần số tích lũy, màu xanh dương, độ dày 1.2.
geom_point(size = 3, color = “#E69F00”): đánh dấu các điểm dữ liệu trên đường bằng chấm màu cam, kích thước 3.
geom_text(aes(label = format(TanSoTichLuy, big.mark = “,”)), vjust = -0.7, size = 4, color = “#333333”): hiển thị nhãn tần số tích lũy trên từng điểm, định dạng có dấu phẩy, nhãn hơi lệch lên trên điểm, chữ màu xám đậm, cỡ chữ 4.
scale_y_continuous(labels = function(x) format(x, big.mark = “,”)): định dạng trục Y để hiển thị số có dấu phẩy, dễ đọc.
labs(title = “Đường Biểu Diễn Tần Số Tích Lũy Nhóm Máu”, x = “Nhóm Máu”, y = “Tần số tích lũy”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(base_size = 14): dùng giao diện tối giản, chữ cơ bản cỡ 14.
theme(plot.title = element_text(face = “bold”, hjust = 0.5, color = “#333333”), axis.title.x = element_text(face = “bold”), axis.title.y = element_text(face = “bold”)): tùy chỉnh chi tiết giao diện, tiêu đề in đậm, căn giữa, màu xám đậm; nhãn trục X, Y in đậm.
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSo, fill = NhomMau)) +
geom_col(color = "black") +
geom_text(aes(label = TanSo), hjust = -0.5, size = 4) +
coord_flip() +
labs(title = "Biểu đồ ngang nhóm máu",
x = "Nhóm máu",
y = "Tần số") +
scale_fill_brewer(palette = "Set2") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", hjust = 0.3))
Nhận xét:
– Nhóm máu O có tần số vượt trội hoàn toàn so với các nhóm máu còn lại (ở mức 32.800).
– Sự khác biệt này tạo nên một phân bố không đồng đều, cho thấy Nhóm máu O là nhóm máu phổ biến nhất trong tập dữ liệu này
– Ba nhóm máu còn lại (A, B, AB) có tần số tương đương nhau và tạo thành một cụm ở mức thấp hơn đáng kể.
– Nhóm máu AB là nhóm máu ít phổ biến nhất với tần số thấp nhất là 22.183.
– Nhóm AB chỉ chiếm một phần rất nhỏ so với nhóm O.
Giải thích:
ggplot(bang_tanso1, aes(x = NhomMau, y = TanSo, fill = NhomMau)): tạo khung biểu đồ với trục X là nhóm máu, trục Y là tần số, mỗi cột được tô màu theo nhóm máu.
geom_col(color = “black”): vẽ các cột, chiều cao dựa trên tần số, có đường viền màu đen.
geom_text(aes(label = TanSo), hjust = -0.5, size = 4): thêm nhãn giá trị tần số lên từng cột, nhãn hơi lệch ra ngoài, chữ cỡ 4.
coord_flip(): xoay trục X và Y, biểu đồ trở thành cột ngang để dễ đọc tên nhóm máu.
labs(title = “Biểu đồ ngang tần số theo nhóm máu”, x = “Nhóm máu”, y = “Tần số”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
scale_fill_brewer(palette = “Set2”): sử dụng bảng màu Set2 từ RColorBrewer, màu pastel hài hòa và dễ phân biệt.
theme_minimal(): giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(face = “bold”, hjust = 0.5)): tùy chỉnh tiêu đề in đậm và căn giữa.
tansuat1 <- prop.table(tanso1) * 100
bang_tansuat1 <- data.frame(NhomMau = names(tansuat1), TanSuat = round(as.numeric(tansuat1), 2), TanSuatTichLuy = round(cumsum(as.numeric(tansuat1)), 2))
print(bang_tansuat1)
## NhomMau TanSuat TanSuatTichLuy
## 1 A 22.24 22.24
## 2 AB 22.18 44.42
## 3 B 22.78 67.20
## 4 O 32.80 100.00
Sys.setlocale("LC_ALL", "Vietnamese")
## Warning in Sys.setlocale("LC_ALL", "Vietnamese"): using locale code page other
## than 65001 ("UTF-8") may cause problems
## [1] "LC_COLLATE=Vietnamese_Vietnam.1258;LC_CTYPE=Vietnamese_Vietnam.1258;LC_MONETARY=Vietnamese_Vietnam.1258;LC_NUMERIC=C;LC_TIME=Vietnamese_Vietnam.1258"
library(ggplot2)
ggplot(bang_tansuat1, aes(x = "", y = TanSuat, fill = NhomMau)) +
geom_bar(width = 1, stat = "identity", color = "white", linewidth = 0.5) +
coord_polar("y", start = 0) +
geom_text(aes(label = paste0(TanSuat, "%")),
position = position_stack(vjust = 0.55),
color = "gray10", size = 4, fontface = "bold") +
scale_fill_manual(values = c(
"#A8DADC",
"#F6BD60",
"#F28482",
"#84A59D",
"#B9FBC0",
"#FFD6A5"
)) +
labs(
title = "Biểu đồ tròn nhóm máu",
fill = "Nhóm máu"
) +
theme_void() +
theme(
plot.title = element_text(size = 15, face = "bold", hjust = 0.5, color = "#333333"),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
legend.position = "right"
)
Nhận xét:
– Nhóm máu phổ biến nhất là nhóm máu O chiếm tỷ lệ cao nhất với 32.8%.
– Các nhóm máu còn lại (A, B, AB) có tỷ lệ rất sát nhau và đều xấp xỉ 22%.
Nhóm máu B chiếm 22.78%
Nhóm máu A chiếm 22.24%
Nhóm máu AB chiếm 22.18%
– Nhóm máu ít phổ biến nhất trong 4 nhóm, nhóm máu AB có tỷ lệ thấp nhất (22.18%), nhưng chỉ chênh lệch một chút so với nhóm A và B.
– Nhóm máu O chiếm gần 1/3 tổng số, trong khi ba nhóm máu còn lại (A, B, AB) phân bố gần như đồng đều.
Giải thích:
Sys.setlocale(“LC_ALL”, “Vietnamese”): cài đặt môi trường hệ thống sang tiếng Việt để hiển thị đúng các ký tự tiếng Việt.
library(ggplot2) : tải thư viện ggplot2, công cụ đồ họa chính để vẽ biểu đồ.
ggplot(bang_tansuat1, aes(x = ““, y = TanSuat, fill = NhomMau)): khởi tạo đồ thị, ánh xạ trục \(x\) cố định, trục \(y\) là TanSuat (tần suất) và màu sắc (fill) theo NhomMau.
geom_bar(width = 1, stat = “identity”, color = “white”, linewidth = 0.5): vẽ các thanh cột, stat = “identity” sử dụng trực tiếp giá trị TanSuat làm chiều cao, thêm viền trắng mỏng để phân tách các lát cắt.
coord_polar(“y”, start = 0): chuyển đổi hệ tọa độ từ biểu đồ cột sang biểu đồ tròn, biến trục \(y\) (tần suất) thành bán kính.
geom_text(aes(label = paste0(TanSuat, “%”)), position = position_stack(vjust = 0.55), color = “gray10”, size = 4, fontface = “bold”): thêm nhãn phần trăm vào giữa các lát cắt, position_stack(vjust = 0.55) canh giữa nhãn chính xác.
scale_fill_manual(values = c(“#A8DADC”, “#F6BD60”, “#F28482”, “#84A59D”, “#B9FBC0”, “#FFD6A5”)): thiết lập các mã màu tùy chỉnh (Hexadecimal) cho từng nhóm máu.
labs(title = “Biểu đồ tròn theo nhóm máu”, fill = “Nhóm máu”): đặt tiêu đề chính của đồ thị và tiêu đề của chú giải màu (fill).
theme_void(): áp dụng giao diện tối giản, xóa tất cả các thành phần không cần thiết (trục, đường lưới, nền).
theme(plot.title = element_text(size = 15, face = “bold”, hjust = 0.5, color = “#333333”), legend.title = element_text(size = 12, face = “bold”), legend.text = element_text(size = 11), legend.position = “right”): định dạng tiêu đề đồ thị (căn giữa, in đậm), định dạng chú giải, đặt chú giải ở bên phải.
Sys.setlocale("LC_ALL", "Vietnamese_Vietnam.1258")
## [1] "LC_COLLATE=Vietnamese_Vietnam.1258;LC_CTYPE=Vietnamese_Vietnam.1258;LC_MONETARY=Vietnamese_Vietnam.1258;LC_NUMERIC=C;LC_TIME=Vietnamese_Vietnam.1258"
options(encoding = "UTF-8")
Sys.setlocale("LC_CTYPE", "en_US.UTF-8")
## [1] "en_US.UTF-8"
library(ggplot2)
ggplot(dataset, aes(x = Weight)) +
geom_histogram(
bins = 15,
fill = "#69b3a2",
color = "white"
) +
geom_text(
stat = "bin",
bins = 15,
aes(label = ..count..),
vjust = -0.3,
size = 3,
color = "black"
) +
scale_x_continuous(
breaks = seq(40, max(dataset$Weight, na.rm = TRUE), by = 5)
) +
labs(
title = "Biểu đồ cột cân nặng",
x = "Cân nặng (kg)",
y = "Tần số"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
axis.text = element_text(size = 11),
axis.title = element_text(size = 11)
)
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Nhận xét:
– Tần số tập trung cao: Đa số các cá nhân có cân nặng từ 45 kg đến 95 kg, với tần số duy trì ổn định ở mức rất cao, quanh 7.000 người.
– Giá trị thấp nhất (hai đầu): Hai nhóm cân nặng ở hai đầu mút (40 kg và 100 kg) có tần số thấp hơn đáng kể (khoảng 3.600 - 3.700 người) so với nhóm ở giữa.
– Hình dạng phân bố: Phân bố có hình dạng gần như đối xứng, cho thấy các cân nặng trung bình là phổ biến nhất.
Giải thích:
ggplot(dataset, aes(x = Weight)): tạo khung biểu đồ với trục X là cột cân nặng của dữ liệu.
geom_histogram(bins = 15, fill = “#69b3a2”, color = “white”): vẽ biểu đồ cột (histogram) với 15 cột, cột tô màu xanh (#69b3a2) và đường viền màu trắng.
geom_text(stat = “bin”, bins = 15, aes(label = ..count..), vjust = -0.3, size = 3, color = “black”): thêm nhãn hiển thị số lượng quan sát trong mỗi cột, nhãn hơi lệch lên trên, cỡ chữ 3, màu chữ đen.
scale_x_continuous(breaks = seq(40, max(dataset$Weight, na.rm = TRUE), by = 5)): định dạng trục X với các giá trị hiển thị từ 40 đến giá trị cân nặng lớn nhất, cách nhau 5 kg.
labs(title = “Biểu đồ cột tần số theo cân nặng”, x = “Cân nặng (kg)”, y = “Tần số”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(hjust = 0.5, face = “bold”, size = 13), axis.text = element_text(size = 11), axis.title = element_text(size = 12)): tùy chỉnh giao diện chi tiết, tiêu đề căn giữa và in đậm, kích thước chữ tiêu đề và nhãn trục được chỉnh phù hợp, chữ trục số liệu cỡ 11.
library(ggplot2)
ggplot(dataset, aes(x = Weight)) +
geom_density(color = "#1f78b4", size = 1.2) +
labs(
title = "Biểu đồ đường mật độ cân nặng",
x = "Cân nặng (kg)",
y = "Mật độ"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5)
)
Nhận xét:
– Phân bố đồng đều: Mật độ phân bố gần như rất đồng đều trong khoảng cân nặng rộng, từ khoảng 45 kg đến 95 kg. Đường mật độ trong khu vực này duy trì ổn định quanh mức 0.016.
– Mật độ thấp ở hai đầu: Mật độ giảm mạnh, tạo thành hai đuôi dốc đứng ở hai đầu mút của biểu đồ, tương ứng với mức cân nặng 40 kg và 100 kg. Điều này cho thấy số lượng cá thể có cân nặng cực đoan (rất nhẹ hoặc rất nặng) là ít hơn hẳn.
– Không có đỉnh rõ rệt: Biểu đồ không có một đỉnh duy nhất nổi bật, mà có nhiều dao động nhỏ trên đỉnh phẳng, củng cố nhận định rằng hầu hết các cân nặng trong khoảng 45 kg - 95 kg đều có mật độ xuất hiện tương đương nhau.
Giải thích:
ggplot(dataset, aes(x = Weight)): tạo khung biểu đồ với trục X là cột cân nặng của dữ liệu.
geom_density(color = “#1f78b4”, size = 1.2): vẽ đường mật độ (density) cho dữ liệu cân nặng, đường màu xanh dương (#1f78b4) và dày 1.2.
labs(title = “Biểu đồ đường mật độ của cân nặng”, x = “Weight (kg)”, y = “Mật độ”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(base_size = 14): sử dụng giao diện tối giản với cỡ chữ cơ bản 14.
theme(plot.title = element_text(face = “bold”, hjust = 0.5)): tùy chỉnh tiêu đề in đậm và căn giữa.
library(ggplot2)
ggplot(dataset, aes(y = Weight)) +
geom_boxplot(fill = "lightcoral", color = "black") +
labs(
title = "Boxplot cân nặng",
y = "Cân nặng (kg)"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
axis.title.y = element_text(size = 13),
axis.text.y = element_text(size = 11)
)
Nhận xét:
– Phân bố đối xứng: Dữ liệu cân nặng có sự phân bố rất đối xứng, không có giá trị ngoại lai (outlier).
– Trung vị và phạm vi chính: Cân nặng trung vị (Q2) là 70 kg.
– Tập trung dữ liệu: 50% số người được khảo sát có cân nặng nằm trong khoảng 55 kg đến 85 kg.
– Phạm vi tổng thể: Toàn bộ dữ liệu nằm trong khoảng 40 kg đến 100 kg.
Giải thích:
ggplot(dataset, aes(y = Weight)): tạo khung biểu đồ với trục Y là cột cân nặng của dữ liệu.
geom_boxplot(fill = “lightcoral”, color = “black”): vẽ biểu đồ Boxplot, bên trong cột tô màu hồng nhạt (lightcoral), viền cột màu đen.
labs(title = “Biểu đồ Boxplot theo cân nặng”, y = “Cân nặng (kg)”): đặt tiêu đề biểu đồ và nhãn trục Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(size = 16, face = “bold”, hjust = 0.5), axis.title.y = element_text(size = 13), axis.text.y = element_text(size = 11)): tùy chỉnh giao diện chi tiết, tiêu đề in đậm, cỡ chữ 16, căn giữa; nhãn trục Y cỡ chữ 13; chữ trục số liệu cỡ 11.
dataset$Weight_Group <- cut(dataset$Weight,
breaks = 3,
include.lowest = TRUE)
tanso2 <- table(dataset$Weight_Group)
bang_tanso2 <- data.frame(
Weight_Group = names(tanso2),
TanSo = as.numeric(tanso2),
TanSoTichLuy = cumsum(as.numeric(tanso2)))
print(bang_tanso2)
## Weight_Group TanSo TanSoTichLuy
## 1 [39.9,60] 33716 33716
## 2 (60,80] 33264 66980
## 3 (80,100] 33020 100000
library(ggplot2)
ggplot(dataset, aes(x = Blood.Type, fill = Weight_Group)) +
geom_bar(position = "dodge", color = "black") +
geom_text(
stat = "count",
aes(label = ..count..),
position = position_dodge(width = 0.9),
vjust = -0.3,
size = 3.5
) +
scale_fill_brewer(palette = "Set3", name = "Nhóm cân nặng") +
labs(
title = "Nhóm cân nặng và nhóm máu",
x = "Nhóm máu",
y = "Tần số"
) +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
axis.text.x = element_text(size = 12),
axis.title = element_text(size = 13)
)
Nhận xét:
– Sự khác biệt rõ rệt theo nhóm máu: Tần số giữa các nhóm máu có sự khác biệt rất lớn. Nhóm máu O có tần số cao hơn đáng kể so với ba nhóm máu còn lại.
Nhóm O: Tổng tần số xấp xỉ 32.000 (cao nhất).
Nhóm A, AB, B: Tổng tần số của mỗi nhóm chỉ dao động quanh 22.000 - 23.000.
– Phân bố Cân nặng theo Nhóm máu: Trong mỗi nhóm máu, tần số của các nhóm cân nặng rất đồng đều và gần như tương đương nhau.
– Nhóm A, AB, B: Tần số của ba nhóm cân nặng ([39, 60], (60, 80], (80, 100]) đều nằm trong khoảng hẹp 7.292 đến 7.743.
– Nhóm O: Tần số của ba nhóm cân nặng cũng rất đồng đều, xấp xỉ 10.000 người ([39, 60] là 11.132; (60, 80] là 10.968; (80, 100] là 10.700).
Giải thích:
ggplot(dataset, aes(x = Blood.Type, fill = Weight_Group)): tạo khung biểu đồ với trục X là nhóm máu và các cột được tô màu theo nhóm cân nặng.
geom_bar(position = “dodge”, color = “black”): vẽ biểu đồ cột phân tổ, các cột nhóm cân nặng đặt cạnh nhau (dodge), viền cột màu đen.
geom_text(stat = “count”, aes(label = ..count..), position = position_dodge(width = 0.9), vjust = -0.3, size = 3.5): thêm nhãn số lượng trên mỗi cột, nhãn căn đúng với từng nhóm cột, hơi lệch lên trên, chữ cỡ 3.5.
scale_fill_brewer(palette = “Set3”, name = “Nhóm cân nặng”): sử dụng bảng màu Set3 từ RColorBrewer và đặt tên cho legend là “Nhóm cân nặng”.
labs(title = “Biểu đồ cột phân tổ nhóm cân nặng theo nhóm máu”, x = “Nhóm máu”, y = “Tần số”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(legend.position = “top”, plot.title = element_text(size = 16, face = “bold”, hjust = 0.5), axis.text.x = element_text(size = 12), axis.title = element_text(size = 13)): tùy chỉnh giao diện chi tiết, đặt legend lên trên, tiêu đề in đậm, căn giữa, chữ tiêu đề cỡ 16; chữ trục X cỡ 12; nhãn trục cỡ 13.
bang_tansuat2 <- dataset %>%
group_by(Blood.Type, Weight_Group) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Blood.Type) %>%
mutate(TanSuat = round(Count / sum(Count) * 100, 1))
print(bang_tansuat2)
## # A tibble: 12 × 4
## # Groups: Blood.Type [4]
## Blood.Type Weight_Group Count TanSuat
## <chr> <fct> <int> <dbl>
## 1 A [39.9,60] 7359 33.1
## 2 A (60,80] 7431 33.4
## 3 A (80,100] 7446 33.5
## 4 AB [39.9,60] 7482 33.7
## 5 AB (60,80] 7292 32.9
## 6 AB (80,100] 7409 33.4
## 7 B [39.9,60] 7743 34
## 8 B (60,80] 7573 33.2
## 9 B (80,100] 7465 32.8
## 10 O [39.9,60] 11132 33.9
## 11 O (60,80] 10968 33.4
## 12 O (80,100] 10700 32.6
library(ggplot2)
ggplot(bang_tansuat2, aes(x = "", y = TanSuat, fill = Weight_Group)) +
geom_bar(width = 1, stat = "identity", color = "white", linewidth = 0.5) +
coord_polar("y", start = 0) +
facet_wrap(~ Blood.Type) +
geom_text(aes(label = paste0(TanSuat, "%")),
position = position_stack(vjust = 0.5),
size = 3.5, fontface = "bold") +
scale_fill_brewer(palette = "Set3", name = "Nhóm cân nặng") +
labs(
title = "Nhóm cân nặng và nhóm máu"
) +
theme_void() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
strip.text = element_text(face = "bold", size = 12)
)
Nhận xét:
– Phân bố cân nặng đồng đều: Tỷ lệ phần trăm của ba nhóm cân nặng ([39, 60], (60, 80], (80, 100]) là rất đồng nhất trong tất cả bốn nhóm máu (A, AB, B, O).
– Tỷ lệ xấp xỉ 1/3: Trong mỗi nhóm máu, ba nhóm cân nặng đều chiếm tỷ lệ xấp xỉ 33% (dao động trong khoảng 32.6% đến 34%). Điều này có nghĩa là mỗi nhóm cân nặng chiếm khoảng một phần ba tổng số người trong nhóm máu đó.
– Không có mối liên hệ rõ rệt: Việc tỷ lệ phần trăm các nhóm cân nặng gần như bằng nhau giữa các nhóm máu (A, AB, B, O) cho thấy không có mối liên hệ đáng kể giữa nhóm máu và sự phân bố cân nặng.
Giải thích:
ggplot(bang_tansuat2, aes(x = ““, y = TanSuat, fill = Weight_Group)): tạo khung biểu đồ với trục Y là tần suất nhóm cân nặng, trục X để trống, các phần được tô màu theo nhóm cân nặng.
geom_bar(width = 1, stat = “identity”, color = “white”, linewidth = 0.5): vẽ cột với chiều cao tương ứng giá trị tần suất, viền cột màu trắng, độ dày viền 0.5, bề rộng cột đầy đủ (width = 1).
coord_polar(“y”, start = 0): chuyển đổi biểu đồ cột thành biểu đồ tròn (pie chart) dựa trên trục Y.
facet_wrap(~ Blood.Type): tạo các biểu đồ tròn riêng biệt cho từng nhóm máu.
geom_text(aes(label = paste0(TanSuat, “%”)), position = position_stack(vjust = 0.5), size = 3.5, fontface = “bold”): thêm nhãn phần trăm lên từng phần trong biểu đồ, căn giữa từng phần, chữ cỡ 3.5, in đậm.
scale_fill_brewer(palette = “Set3”, name = “Nhóm cân nặng”): sử dụng bảng màu Set3 từ RColorBrewer, đặt tên legend là “Nhóm cân nặng”.
labs(title = “Biểu đồ tròn phân tổ nhóm cân nặng theo nhóm máu”): đặt tiêu đề cho biểu đồ.
theme_void(): sử dụng giao diện trống, loại bỏ các trục và lưới để tập trung vào biểu đồ tròn.
theme(plot.title = element_text(hjust = 0.5, face = “bold”, size = 16), legend.position = “bottom”, legend.title = element_text(face = “bold”), strip.text = element_text(face = “bold”, size = 12)): tùy chỉnh giao diện chi tiết, tiêu đề in đậm và căn giữa, legend đặt dưới biểu đồ, tiêu đề legend in đậm, nhãn facet (tên nhóm máu) in đậm và cỡ chữ 12.
library(ggplot2)
ggplot(dataset, aes(y = Cholesterol)) +
geom_boxplot(fill = "#F28482", color = "black", width = 0.4) +
labs(
title = "Boxplot Cholesterol",
y = "Cholesterol (mg/dL)"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 14),
axis.text.x = element_text(size = 12),
axis.title.x = element_text(size = 12),
axis.title.y = element_text(size = 12)
)
Nhận xét:
Giá trị trung vị (Median): Đường kẻ đậm chia hộp nằm chính xác tại 185 mg/dL. Điều này cho thấy 50% các cá thể có mức Cholesterol dưới 185 mg/dL.
Trung vị: Mức Cholesterol trung vị (Q2) là 185 mg/dL.
Tập trung dữ liệu: 50% số người được khảo sát có mức Cholesterol tập trung trong khoảng 155 mg/dL đến 215 mg/dL.
Giải thích:
ggplot(dataset, aes(y = Cholesterol)): tạo khung biểu đồ với trục Y là cột Cholesterol của dữ liệu.
geom_boxplot(fill = “#F28482”, color = “black”, width = 0.4): vẽ biểu đồ Boxplot, bên trong cột tô màu hồng nhạt (#F28482), viền cột màu đen, chiều rộng cột 0.4.
labs(title = “Biểu đồ Boxplot của Cholesterol”, y = “Cholesterol”): đặt tiêu đề biểu đồ và nhãn trục Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(face = “bold”, hjust = 0.5, size = 14), axis.text.x = element_text(size = 12), axis.title.x = element_text(size = 12), axis.title.y = element_text(size = 12)): tùy chỉnh giao diện chi tiết, tiêu đề in đậm, căn giữa, cỡ chữ 14; chữ trục và nhãn trục cỡ 12.
library(ggplot2)
ggplot(dataset, aes(x = Cholesterol)) +
geom_density(fill = "#9b59b6", alpha = 0.6) +
labs(
title = "Biểu đồ mật độ Cholesterol",
x = "Cholesterol (mg/dL)",
y = "Mật độ"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5)
)
Nhận xét:
– Phân bố đồng đều và phẳng: Mật độ phân phối Cholesterol rất đồng đều và gần như phẳng trong phạm vi rộng, từ khoảng 140 mg/dL đến 240 mg/dL. Đường mật độ duy trì ổn định xấp xỉ mức 0.0078.
– Mật độ giảm mạnh ở hai đầu: Mật độ giảm nhanh chóng, tạo thành các đuôi dốc đứng ở hai đầu (từ 120 đến 140 mg/dL và từ 240 đến 250 mg/dL).
– Không có đỉnh nổi bật: Biểu đồ không có một đỉnh (mode) rõ ràng, mà chỉ có các dao động nhỏ trên đỉnh phẳng. Điều này khẳng định rằng hầu hết các mức Cholesterol trong phạm vi chính đều có mật độ xuất hiện gần như nhau.
Giải thích:
ggplot(dataset, aes(x = Cholesterol)): tạo khung biểu đồ với trục X là cột Cholesterol của dữ liệu.
geom_density(fill = “#9b59b6”, alpha = 0.6): vẽ đường mật độ (density) cho dữ liệu Cholesterol, tô màu tím (#9b59b6) với độ trong mờ 0.6.
labs(title = “Biểu đồ mật độ phân phối của Cholesterol”, x = “Cholesterol”, y = “Mật độ”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(face = “bold”, hjust = 0.5)): tùy chỉnh tiêu đề in đậm và căn giữa.
dataset$Cholesterol_Group <- cut(dataset$Cholesterol,
breaks = seq(120, 260, by = 22),
right = FALSE,
labels = paste(seq(120, 238, by = 22),
seq(141, 260, by = 22), sep = "-"))
tanso3 <- table(dataset$Cholesterol_Group)
bang_tanso3 <- data.frame(
Cholesterol_Group = names(tanso3),
TanSo = as.numeric(tanso3),
TanSoTichLuy = cumsum(as.numeric(tanso3))
)
print(bang_tanso3)
## Cholesterol_Group TanSo TanSoTichLuy
## 1 120-141 16855 16855
## 2 142-163 17023 33878
## 3 164-185 16940 50818
## 4 186-207 16701 67519
## 5 208-229 16921 84440
## 6 230-251 15560 100000
library(ggplot2)
ggplot(bang_tanso3, aes(x = Cholesterol_Group, y = TanSo, fill = TanSo)) +
geom_col(color = "black", width = 0.7) +
geom_text(aes(label = TanSo), vjust = -0.5, size = 3) +
geom_hline(yintercept = mean(bang_tanso3$TanSo), linetype = "dashed", color = "red") +
scale_fill_gradient(low = "#a6cee3", high = "#1f78b4") +
labs(
title = "Biểu đồ cột nhóm Cholesterol",
x = "Nhóm Cholesterol (mg/dL)",
y = "Tần số"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text.x = element_text(angle = 45, hjust = 1)
)
Nhận xét:
– Phân bố đồng đều: Tần số của hầu hết các nhóm Cholesterol rất đồng đều, dao động quanh mức 16,900 người (được minh họa bằng đường gạch ngang màu đỏ).
– Bốn nhóm giữa ([142-163], [164-185], [186-207], [208-229]) và nhóm [120-141] đều có tần số xấp xỉ 16,900.
– Nhóm Cholesterol cao nhất thấp hơn: Nhóm có mức Cholesterol cao nhất [230-251] có tần số thấp hơn đáng kể (15,560 người) so với các nhóm còn lại.
Giải thích:
ggplot(bang_tanso3, aes(x = Cholesterol_Group, y = TanSo, fill = TanSo)): tạo khung biểu đồ với trục X là nhóm Cholesterol, trục Y là tần số, các cột được tô màu theo giá trị tần số.
geom_col(color = “black”, width = 0.7): vẽ cột với viền màu đen, chiều rộng cột 0.7.
geom_text(aes(label = TanSo), vjust = -0.5, size = 3): thêm nhãn hiển thị giá trị tần số trên đỉnh cột, nhãn hơi lệch lên trên, chữ cỡ 3.
geom_hline(yintercept = mean(bang_tanso3$TanSo), linetype = “dashed”, color = “red”): vẽ đường ngang tại giá trị trung bình của tần số, nét đứt, màu đỏ để tham chiếu.
scale_fill_gradient(low = “#a6cee3”, high = “#1f78b4”): sử dụng gradient màu từ xanh nhạt đến xanh đậm cho các cột theo giá trị tần số.
labs(title = “Biểu đồ cột tần số theo nhóm Cholesterol”, x = “Nhóm Cholesterol”, y = “Tần số”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(plot.title = element_text(face = “bold”, hjust = 0.5), axis.text.x = element_text(angle = 45, hjust = 1)): tùy chỉnh giao diện, tiêu đề in đậm và căn giữa; chữ trục X xoay 45 độ để dễ đọc.
library(ggplot2)
library(dplyr)
bang_tanso4 <- dataset %>%
group_by(Blood.Type, Cholesterol_Group) %>%
summarise(Count = n(), .groups = "drop")
ggplot(bang_tanso4, aes(x = Blood.Type, y = Count, fill = Cholesterol_Group)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = Count),
position = position_dodge(width = 0.8),
vjust = -0.5, size = 1.7) +
scale_fill_brewer(palette = "Set3", name = "Nhóm Cholesterol") +
labs(
title = "Nhóm cholesterol và nhóm máu",
x = "Nhóm máu",
y = "Tần số"
) +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
axis.text.x = element_text(size = 12),
axis.title = element_text(size = 13)
)
Nhận xét:
– Sự khác biệt rõ rệt theo Nhóm máu: Tần số ở nhóm máu O cao hơn hẳn so với ba nhóm còn lại (A, AB, B).
Nhóm O: Mọi nhóm Cholesterol đều có tần số xấp xỉ 5,000 đến 5,500 người.
Nhóm A, AB, B: Mọi nhóm Cholesterol đều có tần số xấp xỉ 3,400 đến 3,900 người.
– Phân bố Cholesterol đồng đều trong từng nhóm: Trong mỗi nhóm máu (A, AB, B, O), tần số của các nhóm Cholesterol khác nhau là rất đồng nhất, dao động trong phạm vi hẹp. Điều này khẳng định nhận xét từ biểu đồ tỷ lệ trước đó: sự phân bố Cholesterol không bị ảnh hưởng bởi nhóm máu.
– Nhóm [230-251] có tần số thấp nhất (chủ yếu): Mặc dù sự khác biệt nhỏ, nhóm Cholesterol cao nhất [230-251] (màu cam) có xu hướng có tần số thấp nhất hoặc gần thấp nhất trong hầu hết các nhóm máu (A, AB, B, O).
Giải thích:
library(ggplot2): nạp gói ggplot2 để vẽ biểu đồ.
library(dplyr): nạp gói dplyr để xử lý dữ liệu.
bang_tanso4 <- dataset %>% group_by(Blood.Type, Cholesterol_Group) %>% summarise(Count = n(), .groups = “drop”): nhóm dữ liệu theo nhóm máu và nhóm Cholesterol, đếm số quan sát trong mỗi nhóm và tạo bảng tần số mới.
ggplot(bang_tanso4, aes(x = Blood.Type, y = Count, fill = Cholesterol_Group)): tạo khung biểu đồ với trục X là nhóm máu, trục Y là tần số, các cột được tô màu theo nhóm Cholesterol.
geom_col(position = position_dodge(width = 0.8), width = 0.7): vẽ cột cho từng nhóm Cholesterol, đặt các cột cạnh nhau (dodge) với chiều rộng 0.7.
geom_text(aes(label = Count), position = position_dodge(width = 0.8), vjust = -0.5, size = 2.25): thêm nhãn số lượng trên đỉnh từng cột, nhãn căn đúng với cột, hơi lệch lên trên, chữ cỡ 2.25.
scale_fill_brewer(palette = “Set3”, name = “Nhóm Cholesterol”): sử dụng bảng màu Set3 từ RColorBrewer và đặt tên legend là “Nhóm Cholesterol”.
labs(title = “Biểu đồ cột tần số phân tổ nhóm Cholesterol theo nhóm máu”, x = “Nhóm máu”, y = “Tần số”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
theme(legend.position = “top”, plot.title = element_text(size = 16, face = “bold”, hjust = 0.5), axis.text.x = element_text(size = 12), axis.title = element_text(size = 13)): tùy chỉnh giao diện, đặt legend lên trên, tiêu đề in đậm, căn giữa, chữ tiêu đề cỡ 16; chữ trục X cỡ 12; nhãn trục cỡ 13.
library(ggplot2)
ggplot(dataset, aes(x = Weight_Group, y = Cholesterol, fill = Weight_Group)) +
geom_boxplot() +
labs(
title = "Boxplot cholesterol và nhóm cân nặng",
x = "Nhóm cân nặng",
y = "Cholesterol (mg/dL)"
) +
theme_minimal() +
scale_fill_brewer(palette = "Pastel1") +
theme(
plot.title = element_text(hjust = 0.5, face = "bold")
)
Nhận xét:
– Trung vị (Median) Cholesterol đồng đều: Giá trị trung vị (đường kẻ ngang đậm trong hộp) của Cholesterol gần như bằng nhau giữa cả ba nhóm cân nặng: [39, 60], (60, 80], và (80, 100]. Đường trung vị đều nằm xấp xỉ mức 185 mg/dL.
– Phạm vi phân vị (IQR) đồng đều: Khoảng phân vị giữa (IQR), được biểu thị bằng chiều cao của hộp (box), là giống nhau cho cả ba nhóm cân nặng. Điều này cho thấy 50% dữ liệu Cholesterol giữa \(Q_1\) và \(Q_3\) có độ phân tán tương đương nhau, không bị ảnh hưởng bởi nhóm cân nặng.
– Phạm vi tổng thể (Range) đồng đều: Phạm vi dữ liệu Cholesterol tổng thể (từ râu dưới đến râu trên) là như nhau cho cả ba nhóm cân nặng, từ mức thấp nhất xấp xỉ 120 mg/dL đến mức cao nhất xấp xỉ 250 mg/dL.
Giải thích:
ggplot(dataset, aes(x = Weight_Group, y = Cholesterol, fill = Weight_Group)): tạo khung biểu đồ với trục X là nhóm cân nặng, trục Y là Cholesterol, các cột Boxplot được tô màu theo nhóm cân nặng.
geom_boxplot(): vẽ biểu đồ Boxplot cho từng nhóm cân nặng.
labs(title = “Biểu đồ Boxplot của Cholesterol theo nhóm Weight”, x = “Weight Group”, y = “Cholesterol”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
scale_fill_brewer(palette = “Pastel1”): sử dụng bảng màu Pastel1 từ RColorBrewer để tô màu các Boxplot.
theme(plot.title = element_text(hjust = 0.5, face = “bold”)): tùy chỉnh tiêu đề in đậm và căn giữa.
library(dplyr)
library(ggplot2)
bang_tansuat3 <- dataset %>%
group_by(Blood.Type, Cholesterol_Group) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Blood.Type) %>%
mutate(Percent = round(Count / sum(Count) * 100, 2))
ggplot(bang_tansuat3, aes(x = Blood.Type, y = Percent, fill = Cholesterol_Group)) +
geom_col(position = "stack", color = "black") +
geom_text(aes(label = paste0(Percent, "%")),
position = position_stack(vjust = 0.5),
size = 3) +
labs(
title = "Tỷ lệ nhóm cholesterol và nhóm máu",
x = "Nhóm máu",
y = "Tỷ lệ (%)",
fill = "Nhóm Cholesterol"
) +
theme_minimal() +
scale_fill_brewer(palette = "Set3") +
theme(
plot.title = element_text(hjust = 0.5, face = "bold")
)
Nhận xét:
– Phân bố Cholesterol cực kỳ đồng đều: Tỷ lệ phần trăm của sáu nhóm Cholesterol khác nhau là rất nhất quán giữa cả bốn nhóm máu (A, AB, B, O).
– Tỷ lệ xấp xỉ 1/6: Trong mỗi nhóm máu, mỗi nhóm Cholesterol chiếm tỷ lệ gần như bằng nhau, dao động quanh mức 16.5% đến 17.2% (tức là khoảng 1/6).
– Nhóm [230-251] thấp hơn một chút: Nhóm Cholesterol cao nhất, [230-251], có xu hướng chiếm tỷ lệ thấp hơn một chút (khoảng 15.4% - 15.8%) so với các nhóm khác (thường trên 16.5%).
Giải thích:
library(dplyr): nạp gói dplyr để xử lý dữ liệu.
bang_tansuat3 <- dataset %>% group_by(Blood.Type, Cholesterol_Group) %>% summarise(Count = n(), .groups = “drop”) %>% group_by(Blood.Type) %>% mutate(Percent = round(Count/sum(Count)*100,2)): tính bảng tần suất và tỷ lệ phần trăm của từng nhóm Cholesterol trong mỗi nhóm máu.
ggplot(bang_tansuat3, aes(x = Blood.Type, y = Percent, fill = Cholesterol_Group)): tạo khung biểu đồ với trục X là nhóm máu, trục Y là tỷ lệ %, các phần được tô màu theo nhóm Cholesterol.
geom_col(position = “stack”, color = “black”): vẽ cột xếp chồng (stacked bar) với viền cột màu đen.
geom_text(aes(label = paste0(Percent,“%”)), position = position_stack(vjust = 0.5), size = 3): thêm nhãn phần trăm lên từng phần của cột, căn giữa từng phần, chữ cỡ 3.
labs(title = “Biểu đồ tỷ lệ nhóm Cholesterol theo nhóm máu”, x = “Nhóm máu”, y = “Tỷ lệ %”): đặt tiêu đề biểu đồ và nhãn trục X, Y.
theme_minimal(): sử dụng giao diện tối giản, loại bỏ các chi tiết rườm rà.
scale_fill_brewer(palette = “Set3”): sử dụng bảng màu Set3 từ RColorBrewer để tô màu các phần của cột.
theme(plot.title = element_text(hjust = 0.5, face = “bold”)): tùy chỉnh tiêu đề in đậm và căn giữa.
library(dplyr)
library(tidyr)
library(stringi)
library(ggplot2)
library(psych)
library(janitor)
## Warning: package 'janitor' was built under R version 4.5.2
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
Giải thích:
library(dplyr): dùng để thao tác, biến đổi và tóm tắt dữ liệu. Nó cho phép lọc (filter), chọn cột (select), sắp xếp (arrange), tạo biến mới (mutate) và nhóm dữ liệu (group_by, summarise) một cách ngắn gọn, dễ đọc và hiệu quả.
library(tidyr): dùng để làm gọn cấu trúc dữ liệu, đặc biệt là chuyển đổi giữa dạng rộng (wide) và dài (long) bằng các hàm như pivot_longer() hoặc pivot_wider(). Nó giúp dữ liệu phù hợp với các công cụ trực quan hóa hoặc mô hình thống kê.
library(stringi): dùng để xử lý chuỗi ký tự, đặc biệt hữu ích khi làm việc với dữ liệu tiếng Việt. Gói này cho phép chuyển đổi chữ có dấu sang không dấu (stri_trans_general), đổi chữ hoa/thường, xóa ký tự đặc biệt và chuẩn hóa tên biến.
library(ggplot2): là gói chuyên dùng để vẽ đồ thị thống kê theo nguyên tắc “Grammar of Graphics”. Nó giúp trực quan hóa dữ liệu bằng nhiều loại biểu đồ như cột, đường, hộp, phân tán… và dễ dàng tùy chỉnh màu sắc, nhãn, chủ đề.
library(psych): được sử dụng để thực hiện các phân tích thống kê mô tả và kiểm định cơ bản. Hàm phổ biến nhất là describe(), cung cấp nhanh các chỉ số như trung bình, độ lệch chuẩn, giá trị nhỏ nhất, lớn nhất, độ lệch, độ nhọn.
library(janitor): giúp làm sạch dữ liệu và tên biến. Các hàm như clean_names() chuyển tên cột về dạng chuẩn (snake_case), tabyl() tính tần suất các giá trị, và remove_empty() loại bỏ hàng hoặc cột trống. Gói này thường được dùng ở bước tiền xử lý để dữ liệu sạch và dễ thao tác hơn.
library(readxl)
cdkt <- read_excel("D:/DuLieuThayTuongST3chuong2.xlsx", sheet = "CDKT")
kqkd <- read_excel("D:/DuLieuThayTuongST3chuong2.xlsx", sheet = "HDKD")
lctt <- read_excel("D:/DuLieuThayTuongST3chuong2.xlsx", sheet = "LCTT")
names(cdkt)[1] <- "Khoan_muc"
names(lctt)[1] <- "Khoan_muc"
names(kqkd)[1] <- "Khoan_muc"
– Chuẩn hóa cấu trúc dữ liệu để dễ dàng gộp, nối và xử lý dữ liệu giữa các bảng.
Giải thích:
names(cdkt): lấy ra danh sách tên các cột của bảng cdkt.
names(cdkt)[1] <- “Khoan_muc”: truy cập vào phần tử thứ nhất trong danh sách tên cột (tức là cột đầu tiên) và gán lại tên của cột đó thành “Khoan_muc”.
names(lctt)[1] <- “Khoan_muc” và names(kqkd)[1] <- “Khoan_muc”: đổi tên cột đầu tiên trong hai bảng lctt và kqkd thành “Khoan_muc”.
Sys.setlocale("LC_ALL", "Vietnamese_Vietnam.1258")
## Warning in Sys.setlocale("LC_ALL", "Vietnamese_Vietnam.1258"): using locale
## code page other than 65001 ("UTF-8") may cause problems
## [1] "LC_COLLATE=Vietnamese_Vietnam.1258;LC_CTYPE=Vietnamese_Vietnam.1258;LC_MONETARY=Vietnamese_Vietnam.1258;LC_NUMERIC=C;LC_TIME=Vietnamese_Vietnam.1258"
options(encoding = "UTF-8")
Sys.setlocale("LC_CTYPE", "en_US.UTF-8")
## [1] "en_US.UTF-8"
vars_to_select <- c(
"TỔNG CỘNG TÀI SẢN",
"I. Nợ ngắn hạn",
"II. Nợ dài hạn",
"7. Chi phí tài chính",
"18. Lợi nhuận sau thuế thu nhập doanh nghiệp(60=50-51-52)",
"Lưu chuyển tiền thuần từ hoạt động kinh doanh",
"I. Tiền và các khoản tương đương tiền"
)
Giải thích:
vars_to_select <- c(…): dấu <- dùng để gán giá trị cho biến. Hàm c() (combine) được dùng để tạo một vector gồm nhiều phần tử ký tự (chuỗi).
Cụ thể, vector này gồm 7 mục:
“TỔNG CỘNG TÀI SẢN”: tổng giá trị tài sản của doanh nghiệp.
“I. Nợ ngắn hạn”: tổng các khoản nợ phải trả trong thời gian ngắn hạn (dưới 1 năm).
“II. Nợ dài hạn”: tổng các khoản nợ dài hạn (trên 1 năm).
“7. Chi phí tài chính”: chi phí liên quan đến hoạt động tài chính.
“18. Lợi nhuận sau thuế thu nhập doanh nghiệp(60=50-51-52)”: lợi nhuận ròng sau khi trừ thuế thu nhập doanh nghiệp.
“Lưu chuyển tiền thuần từ hoạt động kinh doanh”: lượng tiền thực thu ròng từ hoạt động kinh doanh chính.
“I. Tiền và các khoản tương đương tiền”: tiền mặt và các tài sản dễ chuyển đổi thành tiền.
clean_name <- function(x) {
toupper(stringi::stri_trans_general(x, "Latin-ASCII")) %>%
gsub("[^A-Z0-9]", "", .)
}
vars_clean <- clean_name(vars_to_select)
– Loại bỏ dấu và ký tự đặc biệt để dễ xử lý, so sánh và ghép dữ liệu.
Giải thích:
clean_name <- function(x) { … }: tạo một hàm chuẩn hóa tên biến.
stringi::stri_trans_general(x, “Latin-ASCII”): loại bỏ dấu tiếng Việt, chuyển ký tự có dấu về chữ latin không dấu.
toupper(…): chuyển toàn bộ chuỗi sang chữ in hoa.
%>%: truyền kết quả từ bước trước sang bước sau trong chuỗi thao tác.
gsub(“[^A-Z0-9]”, ““, .): loại bỏ mọi ký tự không phải chữ cái a–z hoặc chữ số 0–9, chỉ giữ ký tự và số.
vars_clean <- clean_name(vars_to_select): áp dụng hàm cho vector vars_to_select và lưu kết quả vào vars_clean.
vars_clean: chứa các tên đã được chuẩn hóa, viết hoa, không dấu, không khoảng trắng và không ký tự đặc biệt.
filter_df <- function(df, nguon) {
df %>%
mutate(Khoan_muc_clean = clean_name(Khoan_muc)) %>%
filter(Khoan_muc_clean %in% vars_clean) %>%
mutate(Nguon = nguon) %>%
select(-Khoan_muc_clean)
}
– Hàm này trả về bảng dữ liệu đã được lọc theo các khoản mục cần thiết và gắn thêm thông tin về nguồn dữ liệu.
Giải thích:
filter_df <- function(df, nguon) { … }: tạo một hàm tên là filter_df, nhận hai đối số là df (bảng dữ liệu) và nguon (tên nguồn dữ liệu).
df %>%: lấy dữ liệu đầu vào và thực hiện các thao tác tuần tự.
mutate(Khoan_muc_clean = clean_name(Khoan_muc)): tạo cột mới Khoan_muc_clean bằng cách chuẩn hóa tên trong cột Khoan_muc bằng hàm clean_name.
filter(Khoan_muc_clean %in% vars_clean): lọc các dòng mà giá trị trong Khoan_muc_clean nằm trong danh sách vars_clean.
mutate(Nguon = nguon): thêm một cột mới tên là Nguon, chứa tên nguồn dữ liệu được truyền vào hàm.
select(-Khoan_muc_clean): xóa cột Khoan_muc_clean khỏi bảng dữ liệu sau khi đã dùng xong.
cdkt_sel <- filter_df(cdkt, "CDKT")
lctt_sel <- filter_df(lctt, "LCTT")
kqkd_sel <- filter_df(kqkd, "KQKD")
– Lọc các khoản mục cần thiết trong từng bảng.
financial_selected <- bind_rows(cdkt_sel, lctt_sel, kqkd_sel)
– Tạo ra bảng tổng hợp financial_selected, chứa toàn bộ dữ liệu đã lọc từ 3 nguồn.
cols_years <- names(financial_selected)[!names(financial_selected) %in% c("Nguon", "Khoan_muc")]
– Chọn tất cả các cột năm.
library(dplyr)
library(tidyr)
financial_long <- financial_selected %>%
pivot_longer(
cols = -c(Nguon, Khoan_muc),
names_to = "Nam",
values_to = "Gia_tri"
) %>%
mutate(
Nam = as.numeric(gsub("[^0-9]", "", Nam)),
Khoan_muc_VN = case_when(
grepl("TỔNG CỘNG TÀI SẢN", Khoan_muc, ignore.case = TRUE) ~ "TCTS",
grepl("Nợ ngắn hạn", Khoan_muc, ignore.case = TRUE) ~ "NNH",
grepl("Nợ dài hạn", Khoan_muc, ignore.case = TRUE) ~ "NDH",
grepl("Chi phí tài chính", Khoan_muc, ignore.case = TRUE) ~ "CPTC",
grepl("Lợi nhuận sau thuế thu nhập doanh nghiệp", Khoan_muc, ignore.case = TRUE) ~ "LNST",
grepl("Lưu chuyển tiền thuần từ hoạt động kinh doanh", Khoan_muc, ignore.case = TRUE) ~ "LCTT",
grepl("Tiền và các khoản tương đương tiền", Khoan_muc, ignore.case = TRUE) ~ "TVTDT",
TRUE ~ Khoan_muc
)
)
– Tạo bảng financial_long ở dạng dữ liệu dài, có cột năm, giá trị, nguồn và mã hóa tên các khoản mục ngắn gọn.
Giải thích:
financial_long <- financial_selected %>%: lấy dữ liệu từ bảng financial_selected và thực hiện các bước xử lý tiếp theo.
pivot_longer(…): chuyển dữ liệu từ dạng rộng (wide) sang dạng dài (long) để dễ phân tích.
cols = -c(Nguon, Khoan_muc): giữ nguyên hai cột “Nguon” và “Khoan_muc”, còn lại chuyển thành cột “Nam” và “Gia_tri”.
names_to = “Nam”: đặt tên cho cột chứa các tên năm là “Nam”.
values_to = “Gia_tri”: đặt tên cho cột chứa giá trị tương ứng là “Gia_tri”.
mutate(…): tạo hoặc biến đổi thêm các cột mới.
Nam = as.numeric(gsub(“[^0-9]”, ““, Nam)): trích số năm từ tên cột và chuyển thành kiểu số.
Khoan_muc_VN = case_when(…): tạo cột mới tên là “Khoan_muc_VN”, mã hóa các khoản mục bằng ký hiệu ngắn gọn.
grepl(“TỔNG CỘNG TÀI SẢN”, Khoan_muc, ignore.case = TRUE) ~ “TCTS”: nếu “Khoan_muc” chứa cụm từ “TỔNG CỘNG TÀI SẢN” thì gán mã là “TCTS”.
grepl(“Nợ ngắn hạn”, Khoan_muc, ignore.case = TRUE) ~ “NNH”: nếu chứa “Nợ ngắn hạn” thì gán mã là “NNH”.
grepl(“Nợ dài hạn”, Khoan_muc, ignore.case = TRUE) ~ “NDH”: nếu chứa “Nợ dài hạn” thì gán mã là “NDH”.
grepl(“Chi phí tài chính”, Khoan_muc, ignore.case = TRUE) ~ “CPTC”: nếu chứa “Chi phí tài chính” thì gán mã là “CPTC”.
grepl(“Lợi nhuận sau thuế thu nhập doanh nghiệp”, Khoan_muc, ignore.case = TRUE) ~ “LNST”: nếu chứa cụm này thì gán mã là “LNST”.
grepl(“Lưu chuyển tiền thuần từ hoạt động kinh doanh”, Khoan_muc, ignore.case = TRUE) ~ “LCTT”: nếu chứa cụm này thì gán mã là “LCTT”.
grepl(“Tiền và các khoản tương đương tiền”, Khoan_muc, ignore.case = TRUE) ~ “TVTDT”: nếu chứa cụm này thì gán mã là “TVTDT”.
TRUE ~ Khoan_muc: nếu không khớp với điều kiện nào ở trên thì giữ nguyên giá trị gốc.
financial_long_unique <- financial_long %>%
group_by(Nam, Khoan_muc_VN) %>%
summarise(Gia_tri = first(Gia_tri), .groups = "drop")
– Loại bỏ các bản ghi trùng lặp trong nhóm (Nam, Khoan_muc_VN) và giữ giá trị đầu tiên.
financial_wide <- financial_long_unique %>%
pivot_wider(
names_from = Khoan_muc_VN,
values_from = Gia_tri
) %>%
arrange(Nam)
Giải thích:
pivot_wider: biến các giá trị trong một cột (Khoan_muc_VN) thành cột mới.
values_from = Gia_tri: điền dữ liệu vào các cột mới này.
arrange(Nam): sắp xếp bảng theo thứ tự tăng dần của năm.
cat("## Kết quả: Tên cột trong financial_wide\n")
## ## Kết quả: Tên cột trong financial_wide
print(names(financial_wide))
## [1] "Nam" "CPTC" "LCTT" "LNST" "NDH" "NNH" "TCTS" "TVTDT"
str(financial_wide)
## tibble [10 × 8] (S3: tbl_df/tbl/data.frame)
## $ Nam : num [1:10] 2015 2016 2017 2018 2019 ...
## $ CPTC : num [1:10] 112637632042 150966297263 145904768287 43698716269 146510028288 ...
## $ LCTT : num [1:10] 353815618542 761518412131 632876665393 545285498122 1057439882016 ...
## $ LNST : num [1:10] 564932238864 443734791018 581436276874 1900250425402 613569051999 ...
## $ NDH : num [1:10] 1791384488732 1290150502229 1520448359028 1890915837664 1724167022149 ...
## $ NNH : num [1:10] 1169335416918 2961152475919 2676231766155 1564164959918 1828483009231 ...
## $ TCTS : num [1:10] 8179782482929 10117918996180 11291217207272 9984063244119 10119906897002 ...
## $ TVTDT: num [1:10] 943317929162 724469956298 779802200597 172567048493 185545788383 ...
Giải thích:
str(): dùng để xem cấu trúc và kiểu dữ liệu chi tiết của bộ dữ liệu, phục vụ cho việc kiểm tra và mã hóa chính xác.
dim(financial_wide)
## [1] 10 8
– Bộ dữ liệu gồm có 10 dòng và 8 cột.
head(financial_wide)
## # A tibble: 6 × 8
## Nam CPTC LCTT LNST NDH NNH TCTS TVTDT
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015 112637632042 353815618542 564932238864 1.79e12 1.17e12 8.18e12 9.43e11
## 2 2016 150966297263 761518412131 443734791018 1.29e12 2.96e12 1.01e13 7.24e11
## 3 2017 145904768287 632876665393 581436276874 1.52e12 2.68e12 1.13e13 7.80e11
## 4 2018 43698716269 545285498122 1900250425402 1.89e12 1.56e12 9.98e12 1.73e11
## 5 2019 146510028288 1057439882016 613569051999 1.72e12 1.83e12 1.01e13 1.86e11
## 6 2020 159264353024 655364412679 440475754374 1.49e12 1.75e12 9.83e12 4.28e11
summary(financial_wide)
## Nam CPTC LCTT
## Min. :2015 Min. : 43698716269 Min. : -2870318244
## 1st Qu.:2017 1st Qu.:120954416103 1st Qu.: 567183289940
## Median :2020 Median :148401242505 Median : 708441412405
## Mean :2020 Mean :133764595442 Mean : 879430966658
## 3rd Qu.:2022 3rd Qu.:153762834318 3rd Qu.:1034284190540
## Max. :2024 Max. :165690839670 Max. :2299239828020
## LNST NDH NNH
## Min. : 440475754374 Min. :1290150502230 Min. :1169335416920
## 1st Qu.: 569058248366 1st Qu.:1500914466190 1st Qu.:1766029587820
## Median : 667065434087 Median :1757775755440 Median :2008047806480
## Mean :1088377188160 Mean :1703114238270 Mean :2143397451210
## 3rd Qu.:1715511268310 3rd Qu.:1886266430770 3rd Qu.:2572854002320
## Max. :2533934246420 Max. :2125168858460 Max. :3210578779510
## TCTS TVTDT
## Min. : 8179782482930 Min. : 172567048493
## 1st Qu.:10017527182100 1st Qu.: 480094457596
## Median :10425558980100 Median : 752136078448
## Mean :11483317558900 Mean :1067107065570
## 3rd Qu.:12595794059000 3rd Qu.:1259091661410
## Max. :17997853312700 Max. :3964316764610
sapply(financial_wide, class)
## Nam CPTC LCTT LNST NDH NNH TCTS TVTDT
## "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric"
– Tất cả các cột trong tập dữ liệu đều đang được lưu trữ dưới dạng số.
financial_wide <- financial_wide %>% clean_names()
– financial_wide sau khi chạy sẽ vẫn giữ các giá trị trong bảng, nhưng tên cột được chuẩn hóa.
Giải thích:
financial_wide <- financial_wide %>% clean_names(): dùng để chuẩn hóa tên cột của bảng dữ liệu financial_wide.
clean_names(): chuyển các tên cột về dạng dễ đọc và nhất quán hơn, loại bỏ dấu cách, ký tự đặc biệt và đảm bảo các tên là duy nhất, giúp việc xử lý dữ liệu về sau thuận tiện hơn.
colnames(financial_wide)
## [1] "nam" "cptc" "lctt" "lnst" "ndh" "nnh" "tcts" "tvtdt"
anyNA(financial_wide)
## [1] FALSE
– Bộ dữ liệu không có giá trị bị thiếu.
financial_wide$nam <- as.numeric(financial_wide$nam)
– Một thao tác cơ bản trong xử lý dữ liệu với R nhằm chuyển đổi kiểu dữ liệu của một cột.
financial_wide <- financial_wide %>%
mutate(
tsr = tcts - nnh - ndh,
tn = nnh + ndh,
kntt = tvtdt / nnh,
roa = lnst / tcts,
lctt_tts = lctt / tcts,
cptc_tn = cptc / (nnh + ndh),
ln_lctt = lnst / lctt
)
– tsr = tcts - nnh - ndh: biến tsr là tổng tài sản ròng, được tính bằng tổng tài sản (tcts) trừ nợ ngắn hạn (nnh) và nợ dài hạn (ndh).
– tn = nnh + ndh: biến tn là tổng nợ, được tính bằng nợ ngắn hạn cộng nợ dài hạn.
– kntt = tvtdt / nnh: biến kntt là khả năng thanh toán, được tính bằng tài sản ngắn hạn (tvtdt) chia nợ ngắn hạn (nnh).
– roa = lnst / tcts: biến roa là tỷ suất sinh lời trên tài sản.
– lctt_tts = lctt / tcts: biến lctt_tts là tỷ lệ lưu chuyển tiền thuần trên tổng tài sản.
– cptc_tn = cptc / (nnh + ndh): biến cptc_tn là tỷ lệ chi phí tài chính trên tổng nợ, được tính bằng chi phí tài chính (cptc) chia tổng nợ (nnh + ndh).
– ln_lctt = lnst / lctt: biến ln_lctt là tỷ lệ lợi nhuận trên lưu chuyển tiền thuần, được tính bằng lợi nhuận sau thuế (lnst) chia lưu chuyển tiền thuần (lctt).
financial_wide <- financial_wide %>%
mutate(across(c(cptc, lctt, lnst, ndh, nnh, tcts, tvtdt),
~ . / 1e12)) %>%
mutate(
tsr = tcts - nnh - ndh,
tn = nnh + ndh,
kntt = tvtdt / nnh,
roa = lnst / tcts,
lctt_tts = lctt / tcts,
cptc_tn = cptc / (nnh + ndh),
ln_lctt = lnst / lctt
)
– Chuyển đổi đơn vị các biến tài chính từ đồng sang nghìn tỷ đồng, giúp dữ liệu gọn, rõ, dễ phân tích và trực quan hóa hơn.
. / 1e12: đây là hàm ẩn danh (anonymous function) áp dụng cho từng cột.
Dấu . đại diện cho giá trị gốc của cột.
1e12 nghĩa là 1.000.000.000.000 => Tức là chia toàn bộ giá trị trong các cột này cho 1 nghìn tỷ.
colSums(is.na(financial_wide))
## nam cptc lctt lnst ndh nnh tcts tvtdt
## 0 0 0 0 0 0 0 0
## tsr tn kntt roa lctt_tts cptc_tn ln_lctt
## 0 0 0 0 0 0 0
– Không có giá trị nào bị thiếu sau khi kiểm tra.
financial_wide <- financial_wide %>% distinct()
Mục đích:
– Loại bỏ dữ liệu trùng lặp.
– Giữ lại mỗi quan sát duy nhất một lần.
– Đảm bảo độ chính xác và tính gọn gàng của dữ liệu.
Giải thích:
financial_wide: là tên dataframe (bảng dữ liệu) đang làm việc.
%>%: là toán tử pipe của dplyr, giúp chuyển kết quả từ bước trước sang bước sau.
distinct(): là hàm loại bỏ các dòng trùng lặp trong bảng dữ liệu.
summary(financial_wide)
## nam cptc lctt lnst
## Min. :2015 Min. :0.0437 Min. :-0.00287 Min. :0.4405
## 1st Qu.:2017 1st Qu.:0.1210 1st Qu.: 0.56718 1st Qu.:0.5691
## Median :2020 Median :0.1484 Median : 0.70844 Median :0.6671
## Mean :2020 Mean :0.1338 Mean : 0.87943 Mean :1.0884
## 3rd Qu.:2022 3rd Qu.:0.1538 3rd Qu.: 1.03428 3rd Qu.:1.7155
## Max. :2024 Max. :0.1657 Max. : 2.29924 Max. :2.5339
## ndh nnh tcts tvtdt
## Min. :1.290 Min. :1.169 Min. : 8.18 Min. :0.1726
## 1st Qu.:1.501 1st Qu.:1.766 1st Qu.:10.02 1st Qu.:0.4801
## Median :1.758 Median :2.008 Median :10.43 Median :0.7521
## Mean :1.703 Mean :2.143 Mean :11.48 Mean :1.0671
## 3rd Qu.:1.886 3rd Qu.:2.573 3rd Qu.:12.60 3rd Qu.:1.2591
## Max. :2.125 Max. :3.211 Max. :18.00 Max. :3.9643
## tsr tn kntt roa
## Min. : 5.219 Min. :2.961 Min. :0.1015 Min. :0.04386
## 1st Qu.: 6.539 1st Qu.:3.479 1st Qu.:0.2448 1st Qu.:0.05378
## Median : 6.820 Median :3.750 Median :0.2865 Median :0.06811
## Mean : 7.637 Mean :3.847 Mean :0.5162 Mean :0.09104
## 3rd Qu.: 7.734 3rd Qu.:4.219 3rd Qu.:0.6825 3rd Qu.:0.10244
## Max. :13.772 Max. :5.083 Max. :1.8871 Max. :0.19033
## lctt_tts cptc_tn ln_lctt
## Min. :-0.0002119 Min. :0.01265 Min. :-882.8060
## 1st Qu.: 0.0549743 1st Qu.:0.03314 1st Qu.: 0.5808
## Median : 0.0709517 Median :0.03554 Median : 0.7095
## Mean : 0.0751293 Mean :0.03494 Mean : -87.2459
## 3rd Qu.: 0.0886391 3rd Qu.:0.03993 3rd Qu.: 1.1746
## Max. : 0.1764486 Max. :0.04916 Max. : 3.4849
– Tóm tắt nhanh toàn bộ nội dung của bảng dữ liệu.
library(skimr)
## Warning: package 'skimr' was built under R version 4.5.2
str(financial_wide)
## tibble [10 × 15] (S3: tbl_df/tbl/data.frame)
## $ nam : num [1:10] 2015 2016 2017 2018 2019 ...
## $ cptc : num [1:10] 0.1126 0.151 0.1459 0.0437 0.1465 ...
## $ lctt : num [1:10] 0.354 0.762 0.633 0.545 1.057 ...
## $ lnst : num [1:10] 0.565 0.444 0.581 1.9 0.614 ...
## $ ndh : num [1:10] 1.79 1.29 1.52 1.89 1.72 ...
## $ nnh : num [1:10] 1.17 2.96 2.68 1.56 1.83 ...
## $ tcts : num [1:10] 8.18 10.12 11.29 9.98 10.12 ...
## $ tvtdt : num [1:10] 0.943 0.724 0.78 0.173 0.186 ...
## $ tsr : num [1:10] 5.22 5.87 7.09 6.53 6.57 ...
## $ tn : num [1:10] 2.96 4.25 4.2 3.46 3.55 ...
## $ kntt : num [1:10] 0.807 0.245 0.291 0.11 0.101 ...
## $ roa : num [1:10] 0.0691 0.0439 0.0515 0.1903 0.0606 ...
## $ lctt_tts: num [1:10] 0.0433 0.0753 0.0561 0.0546 0.1045 ...
## $ cptc_tn : num [1:10] 0.038 0.0355 0.0348 0.0126 0.0412 ...
## $ ln_lctt : num [1:10] 1.597 0.583 0.919 3.485 0.58 ...
Giải thích:
skim(): cho ta số dòng, trung bình, độ lệch chuẩn, min, max, tỉ lệ NA,… Dùng để đánh giá chất lượng dữ liệu sau xử lý.
colSums(is.na(financial_wide))
## nam cptc lctt lnst ndh nnh tcts tvtdt
## 0 0 0 0 0 0 0 0
## tsr tn kntt roa lctt_tts cptc_tn ln_lctt
## 0 0 0 0 0 0 0
– Bộ dữ liệu không có giá trị nào bị thiếu.
summary(financial_wide)
## nam cptc lctt lnst
## Min. :2015 Min. :0.0437 Min. :-0.00287 Min. :0.4405
## 1st Qu.:2017 1st Qu.:0.1210 1st Qu.: 0.56718 1st Qu.:0.5691
## Median :2020 Median :0.1484 Median : 0.70844 Median :0.6671
## Mean :2020 Mean :0.1338 Mean : 0.87943 Mean :1.0884
## 3rd Qu.:2022 3rd Qu.:0.1538 3rd Qu.: 1.03428 3rd Qu.:1.7155
## Max. :2024 Max. :0.1657 Max. : 2.29924 Max. :2.5339
## ndh nnh tcts tvtdt
## Min. :1.290 Min. :1.169 Min. : 8.18 Min. :0.1726
## 1st Qu.:1.501 1st Qu.:1.766 1st Qu.:10.02 1st Qu.:0.4801
## Median :1.758 Median :2.008 Median :10.43 Median :0.7521
## Mean :1.703 Mean :2.143 Mean :11.48 Mean :1.0671
## 3rd Qu.:1.886 3rd Qu.:2.573 3rd Qu.:12.60 3rd Qu.:1.2591
## Max. :2.125 Max. :3.211 Max. :18.00 Max. :3.9643
## tsr tn kntt roa
## Min. : 5.219 Min. :2.961 Min. :0.1015 Min. :0.04386
## 1st Qu.: 6.539 1st Qu.:3.479 1st Qu.:0.2448 1st Qu.:0.05378
## Median : 6.820 Median :3.750 Median :0.2865 Median :0.06811
## Mean : 7.637 Mean :3.847 Mean :0.5162 Mean :0.09104
## 3rd Qu.: 7.734 3rd Qu.:4.219 3rd Qu.:0.6825 3rd Qu.:0.10244
## Max. :13.772 Max. :5.083 Max. :1.8871 Max. :0.19033
## lctt_tts cptc_tn ln_lctt
## Min. :-0.0002119 Min. :0.01265 Min. :-882.8060
## 1st Qu.: 0.0549743 1st Qu.:0.03314 1st Qu.: 0.5808
## Median : 0.0709517 Median :0.03554 Median : 0.7095
## Mean : 0.0751293 Mean :0.03494 Mean : -87.2459
## 3rd Qu.: 0.0886391 3rd Qu.:0.03993 3rd Qu.: 1.1746
## Max. : 0.1764486 Max. :0.04916 Max. : 3.4849
summary(financial_wide$tcts)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8.18 10.02 10.43 11.48 12.60 18.00
sd(financial_wide$tcts)
## [1] 2.774758
Nhận xét:
– Giá trị trung bình (Mean) và trung vị (Median) lệch nhau: Giá trị trung bình (Mean = 11.48) lớn hơn đáng kể so với trung vị (Median = 10.43). Điều này cho thấy phân bố của biến tổng cộng tài sản bị lệch phải, tức là có một số giá trị tài sản rất lớn đang kéo giá trị trung bình lên cao.
– Độ phân tán lớn: Độ lệch chuẩn (SD = 2.774758) tương đối lớn so với giá trị trung bình (11.48), chỉ ra rằng dữ liệu có sự phân tán rộng quanh giá trị trung bình.
– Phạm vi rộng: Phạm vi dữ liệu (Range = Max - Min) là 9.82 (18.00 - 8.18).
– Sự tập trung của dữ liệu: 50% các quan sát tập trung trong khoảng từ tứ phân vị thứ nhất (Q1 = 10.02) đến tứ phân vị thứ ba (Q3 = 12.60).
Giải thích:
summary(): tạo bản tóm tắt thống kê cho một biến số.
sd(): tính độ lệch chuẩn (standard deviation) của biến.
mean(financial_wide$lnst)
## [1] 1.088377
median(financial_wide$lnst)
## [1] 0.6670654
range(financial_wide$lnst)
## [1] 0.4404758 2.5339342
Nhận xét:
– Giá trị trung bình (1.09) lớn hơn trung vị (0.67) một cách đáng kể => Điều này cho thấy phân bố của biến lợi nhuận sau thuế bị lệch phải rất mạnh. Có một số ít đơn vị có mức lợi nhuận sau thuế rất cao, kéo giá trị trung bình lên xa so với trung vị.
– Phạm vi (Range): Biến lợi nhuận sau thuế có phạm vi rộng, từ mức tối thiểu 0.44 đến tối đa 2.53 => Phần lớn các đơn vị có lợi nhuận tập trung quanh mức trung vị thấp (0.67), trong khi một số ít đơn vị đạt được lợi nhuận cao hơn nhiều, dẫn đến sự chênh lệch lớn giữa Mean và Median.
Giải thích:
mean(): trung bình
sd(): tính độ lệch chuẩn
var(): tính phương sai
var(financial_wide$cptc)
## [1] 0.001356584
sd(financial_wide$cptc)
## [1] 0.03683184
Nhận xét:
– Cả phương sai (rất gần 0) và độ lệch chuẩn (0.037) đều là những giá trị rất nhỏ.
=> Điều này chỉ ra rằng các giá trị của biến chi phí tài chính (cptc) phân tán rất ít quanh giá trị trung bình của nó.
summary(financial_wide$lctt)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -0.00287 0.56718 0.70844 0.87943 1.03428 2.29924
Nhận xét:
– Giá trị Trung bình (Mean = 0.879) lớn hơn Trung vị (Median = 0.708) => Điều này cho thấy phân bố của biến lưu chuyển tiền thuần (lctt) bị lệch phải. Có một số đơn vị có mức lưu chuyển tiền thuần rất cao, kéo giá trị trung bình lên cao hơn so với trung vị của dữ liệu.
– Giá trị tối thiểu (Min) là -0.00287 => Sự tồn tại của giá trị âm cho thấy có một số đơn vị có lưu chuyển tiền thuần âm (dòng tiền ra lớn hơn dòng tiền vào), mặc dù giá trị này rất gần 0.
– Biến lưu chuyển tiền thuần có xu hướng lệch phải, với đa số các đơn vị có dòng tiền dương nhưng một số ít đơn vị đạt được mức dòng tiền rất cao.
summary(financial_wide[, c("nnh", "ndh")])
## nnh ndh
## Min. :1.169 Min. :1.290
## 1st Qu.:1.766 1st Qu.:1.501
## Median :2.008 Median :1.758
## Mean :2.143 Mean :1.703
## 3rd Qu.:2.573 3rd Qu.:1.886
## Max. :3.211 Max. :2.125
Nhận xét:
– Nợ ngắn hạn (nnh) cao hơn: Các giá trị thống kê của nnh đều cao hơn so với ndh ở mọi chỉ số (Median, Mean, Max).
– Trung bình (nnh Mean = 2.143) cao hơn đáng kể so với trung bình (ndh Mean = 1.703).
– Giá trị tối đa (nnh Max = 3.211) cao hơn giá trị tối đa (ndh Max = 2.125).
=> Điều này cho thấy các đơn vị được khảo sát có xu hướng gánh nợ ngắn hạn nhiều hơn nợ dài hạn.
– Đối với nnh: Mean (2.143) > Median (2.008).
– Đối với ndh: Mean (1.703) < Median (1.758).
=> Biến nợ ngắn hạn (nnh) bị lệch phải, cho thấy có một số ít đơn vị có mức nợ ngắn hạn rất cao. Biến nợ dài hạn (ndh) gần như đối xứng hoặc hơi lệch trái nhẹ (do Median > Mean), nhưng sự khác biệt không đáng kể.
– Nợ ngắn hạn phân tán rộng hơn: Khoảng phân vị giữa (IQR = Q3 - Q1) của nnh (2.573 - 1.766 = 0.807) lớn hơn của ndh (1.886 - 1.501 = 0.385) .
=> Điều này chỉ ra rằng mức nợ ngắn hạn có sự khác biệt lớn hơn giữa các đơn vị so với mức nợ dài hạn.
sapply(financial_wide[, c("cptc", "lctt", "lnst", "ndh", "nnh", "tcts", "tvtdt")], mean)
## cptc lctt lnst ndh nnh tcts tvtdt
## 0.1337646 0.8794310 1.0883772 1.7031142 2.1433975 11.4833176 1.0671071
Nhận xét:
– tcts (Tổng cộng tài sản): 11.4833176 là giá trị trung bình cao nhất, phản ánh quy mô tài sản lớn nhất.
– Giá trị trung bình ở mức trung bình:
nnh (Nợ ngắn hạn): 2.1433975
ndh (Nợ dài hạn): 1.7031142
lnst (Lợi nhuận sau thuế): 1.088377
tvtdt (Tài sản vô hình và tài sản dài hạn): 1.0671071
lctt (Lưu chuyển tiền thuần): 0.8794310
– cptc (Chi phí tài chính): 0.1337646 là giá trị trung bình thấp nhất, phù hợp với nhận xét trước đó về độ phân tán rất nhỏ của biến này.
– Mức nợ ngắn hạn (nnh = 2.14) trung bình cao hơn đáng kể so với mức nợ dài hạn (ndh = 1.70).
– Trung bình lợi nhuận sau thuế (lnst = 1.09) cao hơn trung bình lưu chuyển tiền thuần (lctt = 0.88).
sapply(financial_wide[, c("cptc", "lctt", "lnst", "ndh", "nnh", "tcts", "tvtdt")],
function(x) sd(x)/mean(x))
## cptc lctt lnst ndh nnh tcts tvtdt
## 0.2753482 0.7354831 0.6969639 0.1533387 0.2992067 0.2416338 1.0375251
Nhận xét:
– Kết quả cho thấy biến động tiền và tương đương tiền (tvtdt), lưu chuyển tiền tệ (lctt) và lợi nhuận sau thuế (lnst) là những chỉ số bất ổn nhất, trong khi cấu trúc nợ (đặc biệt là nợ dài hạn) là ổn định nhất trong bộ dữ liệu.
Giải thích:
sapply(): áp dụng một hàm con (ở đây là function(x) sd(x)/mean(x)) lần lượt cho từng cột trong các cột đã chọn.
sd(x): tính độ lệch chuẩn của cột x, cho biết mức độ biến động dữ liệu.
financial_wide %>%
group_by(nam) %>%
summarise(across(c(cptc, lctt, lnst, ndh, nnh, tcts, tvtdt), mean))
## # A tibble: 10 × 8
## nam cptc lctt lnst ndh nnh tcts tvtdt
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015 0.113 0.354 0.565 1.79 1.17 8.18 0.943
## 2 2016 0.151 0.762 0.444 1.29 2.96 10.1 0.724
## 3 2017 0.146 0.633 0.581 1.52 2.68 11.3 0.780
## 4 2018 0.0437 0.545 1.90 1.89 1.56 9.98 0.173
## 5 2019 0.147 1.06 0.614 1.72 1.83 10.1 0.186
## 6 2020 0.159 0.655 0.440 1.49 1.75 9.83 0.428
## 7 2021 0.108 0.965 0.721 1.42 2.26 10.7 0.637
## 8 2022 0.166 2.30 1.16 1.87 3.21 13.0 1.36
## 9 2023 0.155 -0.00287 2.53 1.90 1.92 13.5 1.47
## 10 2024 0.150 1.53 1.92 2.13 2.10 18.0 3.96
cor(financial_wide[, c("cptc", "lctt", "lnst", "ndh", "nnh", "tcts", "tvtdt")])
## cptc lctt lnst ndh nnh tcts
## cptc 1.0000000 0.31759350 -0.18297496 -0.1096537 0.4921861 0.3687987
## lctt 0.3175935 1.00000000 -0.08992542 0.2318695 0.5919432 0.4397241
## lnst -0.1829750 -0.08992542 1.00000000 0.7516008 -0.1556587 0.6343854
## ndh -0.1096537 0.23186952 0.75160078 1.0000000 -0.3108658 0.6079920
## nnh 0.4921861 0.59194320 -0.15565872 -0.3108658 1.0000000 0.2976216
## tcts 0.3687987 0.43972415 0.63438540 0.6079920 0.2976216 1.0000000
## tvtdt 0.3356372 0.36703870 0.49245788 0.6156292 0.1232809 0.9049609
## tvtdt
## cptc 0.3356372
## lctt 0.3670387
## lnst 0.4924579
## ndh 0.6156292
## nnh 0.1232809
## tcts 0.9049609
## tvtdt 1.0000000
– Ma trận tương quan cho thấy các biến liên quan đến quy mô tài sản (tcts, tvtdt) và cấu trúc nợ (ndh) có mối quan hệ tuyến tính mạnh mẽ với nhau và với hiệu suất (lnst). Ngược lại, mối quan hệ giữa dòng tiền (lctt) và lợi nhuận (lnst) là rất yếu.
financial_wide %>%
summarise(across(c(cptc, lctt, lnst, ndh, nnh, tcts, tvtdt), sum))
## # A tibble: 1 × 7
## cptc lctt lnst ndh nnh tcts tvtdt
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1.34 8.79 10.9 17.0 21.4 115. 10.7
financial_wide %>%
filter(tcts == min(tcts))
## # A tibble: 1 × 15
## nam cptc lctt lnst ndh nnh tcts tvtdt tsr tn kntt roa
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015 0.113 0.354 0.565 1.79 1.17 8.18 0.943 5.22 2.96 0.807 0.0691
## # ℹ 3 more variables: lctt_tts <dbl>, cptc_tn <dbl>, ln_lctt <dbl>
– Năm có tổng cộng tài sản thấp nhất là năm 2015, đạt khoảng 8.179782 tỷ đồng.
Giải thích:
tcts == min(tcts): điều kiện chọn dòng có tổng cộng tài sản (tcts) bằng giá trị tổn cộng tài sản lớn nhất trong toàn bộ bảng.
mean(financial_wide$lnst)
## [1] 1.088377
mean(financial_wide$lctt)
## [1] 0.879431
Nhận xét:
– Giá trị trung bình của lợi nhuận sau thuế (1.09) cao hơn đáng kể so với giá trị trung bình của lưu chuyển tiền tệ (0.88) => Sự chênh lệch này cho thấy trong kỳ kế toán, các đơn vị có xu hướng ghi nhận lợi nhuận cao hơn số tiền mặt thực tế họ luân chuyển hoặc thu được.
financial_wide$roa <- financial_wide$lnst / financial_wide$tcts
summary(financial_wide$roa)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.04386 0.05378 0.06811 0.09104 0.10244 0.19033
Nhận xét:
– ROA trung bình (Mean) là 9.10%. Điều này cho thấy, trung bình, cứ mỗi 100 đơn vị tài sản được sử dụng sẽ tạo ra 9.10 đơn vị lợi nhuận sau thuế.
– Giá trị trung bình (Mean = 0.091) lớn hơn đáng kể so với trung vị (Median = 0.068) => Điều này cho thấy phân bố của ROA bị lệch phải. Có một số ít đơn vị đạt được tỷ suất sinh lời trên tài sản rất cao (kéo giá trị trung bình lên), thể hiện qua giá trị Tối đa là 19.03%.
– 50% dữ liệu ROA tập trung trong khoảng từ tứ phân vị thứ nhất (Q1 = 5.38%) đến tứ phân vị thứ ba (Q3 = 10.24%). Đây là phạm vi sinh lời phổ biến nhất.
Giải thích:
financial_wide$roa: được tính bằng lợi nhuận sau thuế (lnst) chia cho tổng tài sản (tcts). Đây là chỉ tiêu ROA (Return on Assets) - dùng để đo lường hiệu quả sử dụng tài sản của doanh nghiệp.
shapiro.test(financial_wide$roa)
##
## Shapiro-Wilk normality test
##
## data: financial_wide$roa
## W = 0.78554, p-value = 0.009671
Nhận xét:
– Giả thuyết H₀ (null hypothesis): dữ liệu có phân phối chuẩn.
– Giả thuyết H₁ (alternative): dữ liệu không phân phối chuẩn.
Vì: p-value < 0.05 => Ta bác bỏ H₀ => Biến ROA không tuân theo phân phối chuẩn.
Giải thích:
shapiro.test(): dùng để kiểm định tính phân phối chuẩn (normality test) trong R.
financial_wide$roa: là biến cần kiểm định.
financial_wide$tsr <- financial_wide$tcts - financial_wide$nnh - financial_wide$ndh
summary(financial_wide$tsr)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.219 6.539 6.820 7.637 7.734 13.772
Nhận xét:
– Giá trị trung bình (Mean = 7.637) lớn hơn đáng kể so với trung vị (Median = 6.820) => Điều này cho thấy phân bố của biến tài sản ròng (tsr) bị lệch phải. Sự tồn tại của các đơn vị có mức tài sản ròng rất cao (được thể hiện qua giá trị Max = 13.772) đã kéo giá trị trung bình lên cao hơn trung vị.
– Giá trị tối đa (13.772) cao gấp hơn hai lần giá trị trung vị (6.820), cho thấy có sự khác biệt lớn về quy mô tài sản ròng giữa các đơn vị.
– 50% các đơn vị có tài sản ròng tập trung trong khoảng từ tứ phân vị thứ nhất (Q1 = 6.539) đến tứ phân vị thứ ba (Q3 = 7.734), cho thấy phần lớn dữ liệu tập trung ở mức thấp và trung bình.
shapiro.test(financial_wide$lnst)
##
## Shapiro-Wilk normality test
##
## data: financial_wide$lnst
## W = 0.81117, p-value = 0.01981
Nhận xét:
– Giả thuyết H₀ (null hypothesis): dữ liệu có phân phối chuẩn.
– Giả thuyết H₁ (alternative): dữ liệu không phân phối chuẩn.
Vì: p-value < 0.05 => Ta bác bỏ H₀ => Biến LNST không tuân theo phân phối chuẩn.
library(skimr)
skim(financial_wide[, c("cptc", "lctt", "lnst", "ndh", "nnh", "tcts", "tvtdt")])
| Name | …[] |
| Number of rows | 10 |
| Number of columns | 7 |
| _______________________ | |
| Column type frequency: | |
| numeric | 7 |
| ________________________ | |
| Group variables | None |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| cptc | 0 | 1 | 0.13 | 0.04 | 0.04 | 0.12 | 0.15 | 0.15 | 0.17 | ▁▁▂▁▇ |
| lctt | 0 | 1 | 0.88 | 0.65 | 0.00 | 0.57 | 0.71 | 1.03 | 2.30 | ▃▇▃▂▂ |
| lnst | 0 | 1 | 1.09 | 0.76 | 0.44 | 0.57 | 0.67 | 1.72 | 2.53 | ▇▁▁▂▁ |
| ndh | 0 | 1 | 1.70 | 0.26 | 1.29 | 1.50 | 1.76 | 1.89 | 2.13 | ▃▃▂▇▂ |
| nnh | 0 | 1 | 2.14 | 0.64 | 1.17 | 1.77 | 2.01 | 2.57 | 3.21 | ▅▇▅▂▅ |
| tcts | 0 | 1 | 11.48 | 2.77 | 8.18 | 10.02 | 10.43 | 12.60 | 18.00 | ▇▃▃▁▂ |
| tvtdt | 0 | 1 | 1.07 | 1.11 | 0.17 | 0.48 | 0.75 | 1.26 | 3.96 | ▇▃▁▁▁ |
Mục đích:
– So sánh mức độ biến động giữa các chỉ tiêu tài chính.
– Phát hiện dữ liệu bị thiếu (NA).
– Quan sát sơ bộ hình dạng phân phối của từng biến.
library(ggplot2)
ggplot(financial_wide, aes(x = nam, y = lnst)) +
geom_col(fill = "pink", alpha = 1) +
geom_text(aes(label = round(lnst, 1)), vjust = -0.3, size = 3) +
geom_smooth(aes(x = as.numeric(nam), y = lnst), method = "lm", se = FALSE, color = "red") +
labs(title = "Biểu đồ cột LNST qua các năm",
x = "Năm",
y = "LNST (tỷ đồng)") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", color = "darkgreen"))
## `geom_smooth()` using formula = 'y ~ x'
Nhận xét:
– Đường xu hướng màu đỏ cho thấy LNST có xu hướng tăng dần qua các năm, đặc biệt trong giai đoạn cuối của chuỗi thời gian. Điều này phản ánh hiệu quả kinh doanh nhìn chung được cải thiện.
– Mức LNST dao động rất mạnh giữa các năm, cho thấy sự bất ổn lớn trong kết quả kinh doanh:
Mức thấp: LNST giảm mạnh trong các năm 2016 (0.4 tỷ) và 2020 (0.4 tỷ).
Mức cao đột biến: Có hai đỉnh lợi nhuận cao nhất vào năm 2018 (1.9 tỷ) và đặc biệt là năm 2023 (2.5 tỷ), cho thấy sự tăng trưởng đột phá trong hai năm này.
– Sự tăng trưởng LNST trở nên rõ rệt và mạnh mẽ hơn trong giai đoạn từ năm 2021 đến 2023 (từ 0.7 tỷ lên 2.5 tỷ), trước khi giảm nhẹ vào năm 2024 (1.9 tỷ).
=> Lợi nhuận sau thuế có tính chu kỳ hoặc biến động mạnh nhưng duy trì một xu hướng tăng trưởng tích cực trong dài hạn.
Giải thích:
ggplot(financial_wide, aes(x = nam, y = lnst)): khởi tạo biểu đồ từ bộ dữ liệu financial_wide. Dùng aes(x = nam, y = lnst) để quy định trục hoành là năm (nam) và trục tung là lợi nhuận sau thuế (lnst).
geom_col(fill = “pink”, alpha = 1): vẽ biểu đồ cột (column chart) thể hiện giá trị LNST qua từng năm. fill = “pink”: tô màu cột là hồng. alpha = 1: độ trong suốt bằng 1 → hiển thị màu rõ nét hoàn toàn.
geom_text(aes(label = round(lnst, 1)), vjust = -0.3, size = 3): thêm nhãn số liệu trên đầu mỗi cột. label = round(lnst, 1): hiển thị giá trị LNST, làm tròn 1 chữ số thập phân. vjust = -0.3: điều chỉnh vị trí nhãn nằm trên đỉnh cột. size = 3: cỡ chữ của nhãn.
geom_smooth(aes(x = as.numeric(nam), y = lnst), method = “lm”, se = FALSE, color = “red”): thêm đường xu hướng (trend line) dựa trên mô hình hồi quy tuyến tính (lm). se = FALSE: không hiển thị khoảng tin cậy. color = “red”: đường xu hướng có màu đỏ. as.numeric(nam): đảm bảo biến năm được hiểu là số, giúp hồi quy chính xác.
library(ggplot2)
ggplot(financial_wide, aes(x = nam, y = lctt)) +
geom_area(fill = "skyblue", alpha = 0.4) +
geom_line(color = "blue", size = 1) +
geom_point(size = 3, color = "darkblue") +
geom_text(aes(label = round(lctt, 1)), vjust = -0.4, size = 3) +
labs(title = "LCTT từ hoạt động kinh doanh", x = "Năm", y = "LCTT (tỷ đồng)") +
theme_minimal()
Nhận xét:
– Lưu chuyển tiền tệ có tính chu kỳ và dao động cực kỳ mạnh qua các năm, với nhiều đỉnh và đáy rõ rệt. Mức độ bất ổn của dòng tiền cao.
– Nhìn chung, không có xu hướng tăng trưởng rõ ràng trong dài hạn, mà là sự dao động mạnh quanh mức trung bình thấp.
– Biến động:
Đỉnh cao nhất (2022): LCTT đạt mức cao nhất đột biến là 2.3 tỷ đồng vào khoảng năm 2022.
Đáy thấp nhất (2023): LCTT giảm sâu nhất và chạm mức gần 0 (hoặc rất gần 0) vào khoảng năm 2023. Sự sụt giảm đột ngột từ đỉnh 2.3 tỷ xuống gần 0 cho thấy một vấn đề nghiêm trọng hoặc thay đổi lớn trong quản lý dòng tiền tại thời điểm đó.
Phục hồi (2024): LCTT phục hồi mạnh mẽ trở lại mức 1.5 tỷ đồng vào khoảng năm 2024.
=> LCTT từ hoạt động kinh doanh cho thấy sự không ổn định đáng kể, với mức độ rủi ro dòng tiền cao do sự khác biệt lớn giữa đỉnh và đáy trong thời gian ngắn.
Giải thích:
ggplot(financial_wide, aes(x = nam, y = lctt)): khởi tạo biểu đồ từ bộ dữ liệu financial_wide. aes(x = nam, y = lctt) quy định: Trục hoành (x): năm (nam). Trục tung (y): lưu chuyển tiền tệ từ hoạt động kinh doanh (lctt).
geom_area(fill = “skyblue”, alpha = 0.4): vẽ biểu đồ vùng (area chart) để thể hiện mức độ biến động theo thời gian. fill = “skyblue”: tô vùng màu xanh da trời nhạt. alpha = 0.4: làm vùng trong mờ 40%, giúp dễ nhìn hơn.
geom_line(color = “blue”, size = 1): thêm đường nối các điểm dữ liệu để thấy rõ xu hướng. color = “blue”: màu đường là xanh dương. size = 1: độ dày đường.
geom_point(size = 3, color = “darkblue”): vẽ các điểm dữ liệu (marker) tại từng năm. size = 3: kích thước điểm. color = “darkblue”: màu xanh đậm.
geom_text(aes(label = round(lctt, 1)), vjust = -0.4, size = 3): thêm nhãn giá trị trên từng điểm dữ liệu. label = round(lctt, 1): hiển thị giá trị LCTT, làm tròn 1 chữ số thập phân. vjust = -0.4: điều chỉnh vị trí chữ cao hơn một chút so với điểm. size = 3: cỡ chữ.
library(ggplot2)
ggplot(financial_wide, aes(x = nam)) +
geom_line(aes(y = ndh, color = "Nợ dài hạn"), size = 1.2) +
geom_line(aes(y = nnh, color = "Nợ ngắn hạn"), size = 1.2) +
geom_point(aes(y = ndh, color = "Nợ dài hạn"), size = 3) +
geom_point(aes(y = nnh, color = "Nợ ngắn hạn"), size = 3) +
labs(
title = "So sánh NDH và NNH",
x = "Năm",
y = "Giá trị (tỷ đồng)",
color = "Loại nợ"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", color = "darkblue", size = 13),
legend.position = "top"
)
Nhận xét:
– Nợ ngắn Hạn (NNH) biến động mạnh: đường nợ ngắn hạn (màu xanh ngọc) có mức độ dao động (rủi ro) cao hơn hẳn so với nợ dài hạn.
NNH có sự tăng trưởng và sụt giảm đột ngột (từ 2.0 tỷ lên đỉnh 3.2 tỷ vào khoảng năm 2022, sau đó giảm về 2.0 tỷ).
Mức nợ ngắn hạn luôn cao hơn nợ dài hạn trong hầu hết các năm (trừ giai đoạn 2017-2019).
– Nợ dài Hạn (NDH) Ổn định hơn: Đường Nợ dài hạn (màu đỏ) có xu hướng ổn định hơn và ít có các đỉnh đột biến. NDH duy trì ở mức trung bình quanh 1.5 - 1.9 tỷ, với sự sụt giảm nhẹ vào khoảng năm 2016 và mức phục hồi ổn định sau đó.
– Trong giai đoạn này, có lúc NDH có giá trị cao hơn NNH (khoảng năm 2018).
– Nợ ngắn hạn (NNH) đạt đỉnh cao nhất, sau đó cả hai loại nợ đều có xu hướng tăng dần và gặp nhau ở mức xấp xỉ 2.1 tỷ vào cuối chuỗi thời gian, cho thấy sự cân bằng trở lại trong cấu trúc nợ.
=> Cấu trúc nợ cho thấy sự ưu tiên và bất ổn cao ở Nợ ngắn hạn, mặc dù Nợ dài hạn duy trì sự ổn định hơn.
Giải thích:
geom_line(aes(y = ndh, color = “Nợ dài hạn”), size = 1.2): vẽ đường biểu diễn nợ dài hạn (ndh) qua các năm. y = ndh: trục tung thể hiện giá trị nợ dài hạn. color = “Nợ dài hạn”: gán màu riêng cho đường này và tạo chú giải (legend). size = 1.2: độ dày của đường kẻ.
geom_line(aes(y = nnh, color = “Nợ ngắn hạn”), size = 1.2): vẽ đường biểu diễn nợ ngắn hạn (nnh) qua các năm. color = “Nợ ngắn hạn” giúp tự động thêm màu khác trong chú giải để phân biệt với NDH.
geom_point(aes(y = ndh, color = “Nợ dài hạn”), size = 3) + geom_point(aes(y = nnh, color = “Nợ ngắn hạn”), size = 3): thêm các điểm dữ liệu (marker) cho từng năm trên hai đường, giúp người xem dễ xác định giá trị tại từng thời điểm. size = 3: kích thước điểm vừa phải, cân đối với đường.
library(dplyr)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.2
## corrplot 0.95 loaded
cor_matrix <- financial_wide %>%
select(cptc, lctt, lnst, ndh, nnh, tcts, tvtdt) %>%
cor(use = "complete.obs")
corrplot(
cor_matrix,
method = "color",
col = colorRampPalette(c("#6D9EC1", "white", "#E46726"))(200),
addCoef.col = "black",
tl.col = "black",
tl.srt = 45,
number.cex = 0.9,
title = "Ma trận tương quan",
mar = c(0, 0, 2, 0),
cl.cex = 0.8,
diag = TRUE
)
Nhận xét:
– Kết quả cho thấy các biến quy mô tài sản và nợ dài hạn có quan hệ tuyến tính mạnh mẽ với hiệu suất (lnst), trong khi dòng tiền (lctt) gần như độc lập với lợi nhuận sau thuế.
Giải thích:
cor_matrix: dữ liệu đầu vào là ma trận tương quan vừa tính.
method = “color”: dùng ô màu để biểu diễn mức độ tương quan.
Màu đỏ/cam: tương quan dương mạnh. Màu xanh: tương quan âm mạnh. Màu trắng: tương quan yếu.
col = colorRampPalette(c(“#6D9EC1”, “white”, “#E46726”))(200): tạo thang màu chuyển dần từ xanh => trắng => cam, với 200 cấp độ màu. Giúp biểu đồ nhìn mượt và dễ phân biệt hơn.
addCoef.col = “black”: hiển thị giá trị hệ số tương quan (r) ngay trong từng ô bằng màu đen.
tl.col = “black”: đặt màu nhãn tên biến là màu đen.
tl.srt = 45: xoay nhãn tên biến 45 độ cho dễ đọc khi chúng dài.
number.cex = 0.9: điều chỉnh kích cỡ chữ của số tương quan.
title = “Ma trận tương quan”: tiêu đề của biểu đồ.
mar = c(0, 0, 2, 0): tùy chỉnh khoảng cách lề quanh biểu đồ (trên, dưới, trái, phải).
cl.cex = 0.8: điều chỉnh kích cỡ chữ của thang màu (color legend) bên phải.
diag = TRUE: giữ lại đường chéo chính, nơi tương quan giữa biến với chính nó bằng 1.
library(ggplot2)
ggplot(financial_wide, aes(x = lnst)) +
geom_density(fill = "skyblue", alpha = 0.6, color = "darkblue") +
geom_vline(aes(xintercept = mean(lnst, na.rm = TRUE)),
color = "red", linetype = "dashed", size = 1) +
labs(
title = "Phân phối mật độ LNST",
x = "LNST (tỷ đồng)",
y = "Mật độ"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", color = "darkblue", size = 13)
)
Nhận xét:
– Biểu đồ thể hiện sự lệch phải rất rõ rệt. Phần lớn mật độ tập trung ở phía bên trái (mức LNST thấp) và đường cong kéo dài dần về phía bên phải (mức LNST cao).
Mật độ cao nhất (đỉnh) nằm ở khoảng 0.6 tỷ đồng. Đây là mức lợi nhuận sau thuế phổ biến nhất trong tập dữ liệu.
Mật độ giảm dần từ đỉnh 0.6 tỷ đồng và kéo dài đến khoảng 2.5 tỷ đồng. Tuy nhiên, sau mốc khoảng 1.0 tỷ đồng (đường gạch ngang đỏ), mật độ giảm xuống rất nhiều, cho thấy số lượng đơn vị đạt lợi nhuận trên 1.0 tỷ đồng là tương đối ít.
=> Phân phối LNST bị lệch phải mạnh, cho thấy sự phân hóa lớn về lợi nhuận, với đa số các đơn vị đạt lợi nhuận thấp và một số ít đạt lợi nhuận vượt trội.
Giải thích:
ggplot(financial_wide, aes(x = lnst)): khởi tạo biểu đồ với bộ dữ liệu financial_wide. Trục hoành (x) là biến lnst (lợi nhuận sau thuế).
geom_density(fill = “skyblue”, alpha = 0.6, color = “darkblue”): vẽ biểu đồ mật độ (density plot) của biến lợi nhuận sau thuế. fill = “skyblue”: tô màu vùng bên dưới đường mật độ bằng màu xanh nhạt. alpha = 0.6: độ trong suốt 60%, giúp biểu đồ nhìn nhẹ nhàng hơn. color = “darkblue”: viền của đường mật độ có màu xanh đậm.
geom_vline(aes(xintercept = mean(lnst, na.rm = TRUE)), color = “red”, linetype = “dashed”, size = 1): vẽ đường thẳng đứng tại vị trí giá trị trung bình của LNST. xintercept = mean(lnst, na.rm = TRUE): lấy trung bình của LNST (bỏ qua giá trị thiếu). color = “red”: đường màu đỏ để dễ nhận biết. linetype = “dashed”: kiểu gạch đứt. size = 1: độ dày đường.
labs(title = “Phân phối mật độ LNST”, x = “LNST (tỷ đồng)”, y = “Mật độ”): đặt tiêu đề và nhãn cho biểu đồ: title: tên biểu đồ. x: tên trục hoành. y: tên trục tung.
theme_minimal(): áp dụng giao diện tối giản, loại bỏ đường nền, giúp biểu đồ sáng sủa và chuyên nghiệp hơn.
theme(plot.title = element_text(face = “bold”, color = “darkblue”, size = 13)): tùy chỉnh tiêu đề biểu đồ. face = “bold”: chữ in đậm. color = “darkblue”: màu xanh đậm. size = 13: cỡ chữ 13.
financial_long1 <- financial_wide %>%
select(nam, nnh, ndh) %>%
pivot_longer(cols = c(nnh, ndh), names_to = "Loai_no", values_to = "Gia_tri")
library(ggplot2)
ggplot(financial_long1, aes(x = nam, y = Gia_tri, fill = Loai_no)) +
geom_col(position = "dodge", alpha = 0.8) +
geom_text(aes(label = round(Gia_tri, 1)),
position = position_dodge(width = 0.9), vjust = -0.3, size = 3) +
geom_line(aes(y = Gia_tri, color = Loai_no, group = Loai_no),
size = 1, linetype = "dotted") +
labs(title = "So sánh NNH và NDH theo năm",
x = "Năm",
y = "Giá trị (tỷ đồng)",
fill = "Loại nợ",
color = "Loại nợ") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", color = "darkblue", size = 13))
Nhận xét:
– Nợ ngắn hạn (NNH) có mức độ biến động cao hơn hẳn nợ dài hạn (NDH), thể hiện qua các đỉnh và đáy rõ rệt (đạt đỉnh 3.2 tỷ vào khoảng 2022.5). Trong hầu hết các năm, NNH có giá trị cao hơn NDH, đặc biệt là trong giai đoạn 2016-2017 và sau năm 2021.
– Nợ dài hạn (NDH) duy trì sự ổn định tương đối, chủ yếu dao động trong khoảng 1.5 tỷ đến 1.9 tỷ qua các năm, với mức thay đổi qua từng năm nhỏ hơn NNH.
– Các Giai đoạn cân bằng:
2019-2020: Hai loại nợ có giá trị gần như tương đương nhau (khoảng 1.7 - 1.8 tỷ).
2023-2024: Hai loại nợ có xu hướng cân bằng lại ở mức khoảng 2.1 tỷ, cho thấy sự điều chỉnh trong cấu trúc nợ sau giai đoạn NNH đạt đỉnh.
Giải thích:
select(nam, nnh, ndh): chọn ba cột gồm năm, nợ ngắn hạn (nnh), và nợ dài hạn (ndh) từ dữ liệu financial_wide.
pivot_longer(…): chuyển dữ liệu từ dạng rộng (wide) sang dạng dài (long) để ggplot dễ vẽ hơn.
cols = c(nnh, ndh): chọn hai cột cần gom lại.
names_to = “Loai_no”: tên mới của cột chứa loại nợ (NNH hoặc NDH).
values_to = “Gia_tri”: tên mới của cột chứa giá trị của từng loại nợ.
=> Cấu trúc nợ của các đơn vị cho thấy sự ưu tiên và bất ổn cao hơn ở Nợ ngắn hạn, trong khi nợ dài hạn đóng vai trò ổn định trong cơ cấu vốn.
library(ggplot2)
financial_wide$tn <- financial_wide$nnh + financial_wide$ndh
ggplot(financial_wide, aes(x = nam)) +
geom_line(aes(y = tcts, color = "Tổng cộng tài sản"), size = 1.2) +
geom_line(aes(y = tn, color = "Tổng nợ"), size = 1.2, linetype = "dashed") +
geom_point(aes(y = tcts, color = "Tổng cộng tài sản"), size = 3) +
geom_point(aes(y = tn, color = "Tổng nợ"), size = 3) +
labs(title = "TCTS và TN qua các năm",
x = "Năm", y = "Giá trị (tỷ đồng)", color = "Chỉ tiêu") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", color = "darkred", size = 13))
Nhận xét:
– Tổng cộng tài sản (TCTS - đường đỏ) luôn có giá trị cao hơn đáng kể so với tổng nợ trong suốt chuỗi thời gian.
– TCTS thể hiện xu hướng tăng trưởng ổn định và mạnh mẽ trong dài hạn, đặc biệt là trong giai đoạn từ năm 2021 đến cuối chu kỳ, đạt mức cao nhất (trên 15 tỷ đồng).
– Tổng nợ (TN - đường xanh lam) duy trì ở mức ổn định thấp, chủ yếu dao động trong khoảng 3 tỷ đến 5 tỷ đồng.
– TN có một đợt tăng nhẹ vào năm 2022, nhưng sau đó giảm xuống và duy trì ổn định.
=> Sự chênh lệch lớn và liên tục giữa TCTS và TN cho thấy các đơn vị duy trì tỷ lệ vốn chủ sở hữu cao (Tài sản Ròng lớn). Việc TCTS tăng trưởng mạnh mẽ trong khi TN chỉ biến động nhẹ cho thấy sự tăng trưởng quy mô tài sản trong những năm gần đây chủ yếu được tài trợ bằng vốn chủ sở hữu hơn là nợ vay.
Giải thích:
financial_wide\(tn <- financial_wide\)nnh + financial_wide$ndh: tạo biến tổng nợ (TN) bằng cách cộng nợ ngắn hạn và dài hạn.
ggplot(financial_wide, aes(x = nam)): khởi tạo biểu đồ với trục hoành là năm.
geom_line(… tcts …): vẽ đường biểu diễn tổng cộng tài sản (TCTS).
geom_line(… tn …): vẽ đường biểu diễn tổng nợ (TN) dạng gạch đứt để phân biệt.
geom_point(): thêm các điểm tròn đánh dấu giá trị từng năm.
labs(): thêm tiêu đề, nhãn trục và chú thích.
theme_minimal() + theme(): tạo giao diện tối giản, tiêu đề đỏ đậm, in đậm.
financial_wide$roa <- financial_wide$lnst / financial_wide$tcts
ggplot(financial_wide, aes(x = nam, y = roa)) +
geom_line(color = "darkgreen", size = 1.2) +
geom_point(color = "forestgreen", size = 3) +
geom_text(aes(label = round(roa, 3)), vjust = -0.5, size = 3) +
labs(title = "Tỷ suất sinh lời trên tài sản",
x = "Năm", y = "ROA") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", color = "darkgreen", size = 13))
Nhận xét:
– ROA thể hiện sự biến động cực kỳ mạnh mẽ, tạo thành các đỉnh và đáy sắc nét, cho thấy hiệu quả sử dụng tài sản rất bất ổn qua các năm.
Năm 2018 (khoảng 2017.5) đạt 0.19 (19%) là mức cao nhất.
Năm 2023 (khoảng 2022.5) đạt 0.187 (18.7%) là mức cao gần nhất.
– Hai đỉnh này cho thấy đơn vị đã có hai giai đoạn sử dụng tài sản đặc biệt hiệu quả.
– Sau đỉnh cao năm 2023, ROA giảm mạnh xuống 0.107 (10.7%) vào năm 2024. Mặc dù có giảm, mức 10.7% này vẫn cao hơn đáng kể so với mức ROA trung bình trong giai đoạn 2015-2022.
=> ROA có tính chu kỳ và bất ổn cao, với hiệu quả sử dụng tài sản đạt đỉnh vào năm 2018 và 2023, nhưng có xu hướng giảm sau mỗi đỉnh cao.
Giải thích:
aes(x = nam, y = roa): trục hoành là năm, trục tung là ROA (tỷ suất sinh lời trên tài sản).
geom_line(): vẽ đường xu hướng ROA.
geom_point(): thêm điểm tròn đánh dấu ROA từng năm.
geom_text(): hiển thị giá trị ROA trên từng điểm.
labs(): đặt tiêu đề và tên trục.
theme_minimal() + theme(): giao diện gọn, tiêu đề in đậm và màu xanh.
ggplot(financial_wide, aes(x = nam, y = tvtdt)) +
geom_area(fill = "lightblue", alpha = 0.5) +
geom_line(color = "blue", size = 1.2) +
geom_point(color = "darkblue", size = 3) +
labs(
title = "Tiền và tương đương tiền",
x = "Năm",
y = "TVTDT (tỷ đồng)"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", color = "navy", size = 13)
)
Nhận xét:
– Chỉ tiêu này có một xu hướng tăng trưởng rất rõ ràng và mạnh mẽ trong nửa sau của chuỗi thời gian.
Giai đoạn giảm (đầu chu kỳ): Giá trị giảm dần từ khoảng 1.0 tỷ đồng xuống mức đáy (dưới 0.5 tỷ đồng) trong giai đoạn đầu.
Giai đoạn tăng trưởng (cuối chu kỳ): Sau khi đạt đáy, giá trị tăng trưởng nhanh chóng và liên tục, vượt qua mốc 1.0 tỷ đồng và kết thúc ở đỉnh cao nhất, đạt 4.0 tỷ đồng.
– Tăng trưởng đột phá gần đây: Sự tăng trưởng từ mức 1.5 tỷ đồng lên 4.0 tỷ đồng là sự đột biến, cho thấy khả năng tích lũy tiền mặt hoặc các khoản tương đương tiền đã tăng vọt trong những năm gần đây.
=> Chỉ tiêu tiền và tương đương tiền thể hiện sự phục hồi mạnh mẽ và tăng trưởng đột biến trong giai đoạn cuối của chu kỳ, cho thấy sự cải thiện đáng kể về khả năng thanh khoản và quản lý vốn lưu động.
Giải thích:
aes(x = nam, y = tvtdt): trục hoành là năm, trục tung là tiền và tương đương tiền (TVTDT).
geom_area(): tô màu vùng dưới đường để nhấn mạnh tổng lượng tiền theo năm.
geom_line(): vẽ đường xu hướng TVTDT.
geom_point(): đánh dấu giá trị từng năm bằng điểm tròn.
labs(): thêm tiêu đề và nhãn trục.
theme_minimal() + theme(): giao diện gọn, tiêu đề in đậm màu xanh đậm.
library(dplyr)
library(ggplot2)
financial_2023 <- financial_wide %>%
filter(nam == 2023) %>%
select(tvtdt, lnst, tcts) %>%
pivot_longer(cols = everything(), names_to = "Chi_tieu", values_to = "Gia_tri")
financial_2023 <- financial_2023 %>%
mutate(Ty_le = Gia_tri / sum(Gia_tri) * 100)
ggplot(financial_2023, aes(x = "", y = Ty_le, fill = Chi_tieu)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
geom_text(aes(label = paste0(round(Ty_le, 1), "%")),
position = position_stack(vjust = 0.5), color = "white", size = 4) +
scale_fill_manual(values = c("#66c2a5", "#fc8d62", "#8da0cb")) +
labs(
title = "TVTDT, LNST và TCTS năm 2023",
fill = "Chỉ tiêu"
) +
theme_void() +
theme(
plot.title = element_text(face = "bold", color = "darkblue", size = 13, hjust = 0.5),
legend.title = element_text(face = "bold")
)
Nhận xét:
– Tổng cộng tài sản (tcts) chiếm ưu thế tuyệt đối: Tổng cộng tài sản (tcts) chiếm tỷ trọng lớn nhất và áp đảo, đạt 77.2% (gần 4/5 tổng giá trị). Điều này là hợp lý vì tổng tài sản thường là chỉ tiêu có quy mô lớn nhất trong một doanh nghiệp.
– Lợi nhuận sau thuế (lnst) xếp thứ hai: Lợi nhuận sau thuế (lnst) chiếm tỷ trọng thứ hai với 14.4%.
– Tiền và tương đương tiền (tvtdt) chiếm tỷ trọng thấp nhất: Tiền và tương đương tiền (tvtdt) chiếm tỷ trọng nhỏ nhất, chỉ 8.4%.
Giải thích:
filter(nam == 2023): chọn dữ liệu năm 2023.
select(tvtdt, lnst, tcts): lấy 3 chỉ tiêu tiền và tương đương tiền, lợi nhuận sau thuế, tổng tài sản.
pivot_longer(): chuyển dữ liệu sang dạng dài (Chi_tieu và Gia_tri) để vẽ pie chart.
mutate(Ty_le = Gia_tri / sum(Gia_tri) * 100): tính tỷ lệ % của từng chỉ tiêu.
geom_col() + coord_polar(theta = “y”): tạo biểu đồ tròn.
geom_text(): hiển thị phần trăm trên từng lát cắt.
scale_fill_manual(): đặt màu sắc đẹp, phân biệt từng chỉ tiêu.
theme_void() + theme(): giao diện gọn, tiêu đề in đậm và màu xanh, chú thích rõ ràng.
financial_long2 <- financial_wide %>%
select(nam, lnst, lctt, tvtdt) %>%
pivot_longer(cols = c(lnst, lctt, tvtdt), names_to = "Chi_tieu", values_to = "Gia_tri")
ggplot(financial_long2, aes(x = nam, y = Gia_tri, color = Chi_tieu)) +
geom_line(size = 1.2) +
geom_point(size = 3) +
labs(
title = "LNST, LCTT và TVTDT qua các năm",
x = "Năm", y = "Giá trị (tỷ đồng)",
color = "Chỉ tiêu"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", color = "darkblue", size = 13))
Nhận xét:
– Cả ba chỉ tiêu đều thể hiện sự biến động mạnh qua các năm, với nhiều đỉnh và đáy đột ngột, phản ánh tính bất ổn trong kết quả hoạt động và cấu trúc tài sản.
– tvtdt (Đường xanh dương): Thể hiện xu hướng tăng trưởng mạnh nhất trong dài hạn, đặc biệt là vào cuối chu kỳ, đạt mức cao nhất (gần 4.0 tỷ đồng).
– lnst và lctt: Hai chỉ tiêu này cũng có xu hướng tăng trưởng, nhưng với mức độ ổn định thấp hơn và không mạnh mẽ bằng tvtdt.
– Trong nhiều năm, lnst và lctt di chuyển cùng pha (cùng tăng/cùng giảm), nhưng có những giai đoạn chúng phân kỳ (lnst đạt đỉnh 2.5 tỷ thì LCTT ở mức thấp).
– tvtdt có mối quan hệ ít rõ ràng hơn với hai chỉ tiêu kia trong ngắn hạn, nhưng cho thấy sự tăng trưởng mạnh mẽ trong các năm gần đây.
=> Chỉ tiêu tvtdt (Tiền và tương đương tiền) có mức tăng trưởng ổn định và mạnh nhất. Các chỉ tiêu hiệu quả hoạt động (lnst, lctt) thể hiện sự bất ổn lớn, đặc biệt là sự sụt giảm đột ngột của dòng tiền (lctt) vào cuối chu kỳ trước.
Giải thích:
select(nam, lnst, lctt, tvtdt): lấy năm và 3 chỉ tiêu tài chính.
pivot_longer(): chuyển dữ liệu sang dạng dài để vẽ nhiều đường trên cùng biểu đồ.
geom_line(): vẽ đường xu hướng từng chỉ tiêu qua các năm.
geom_point(): đánh dấu giá trị từng năm bằng điểm tròn.
labs(): thêm tiêu đề, nhãn trục và chú thích.
theme_minimal() + theme(): giao diện gọn, tiêu đề in đậm, màu xanh.