Em xin bày tỏ lòng biết ơn sâu sắc đến ThS. Trần Mạnh Tường – người đã tận tình hướng dẫn, chỉ bảo và truyền đạt nhiều kiến thức quý báu trong suốt quá trình học tập và thực hiện bài tiểu luận này. Nhờ sự tận tâm, trách nhiệm và những định hướng sâu sắc của Thầy, em đã có thể hoàn thành bài báo cáo một cách đầy đủ và trọn vẹn nhất.
Em vô cùng trân trọng những bài học mà Thầy đã truyền đạt – không chỉ về chuyên môn mà còn về tinh thần học tập nghiêm túc, phương pháp nghiên cứu khoa học và thái độ làm việc cẩn trọng, trách nhiệm. Mặc dù đã cố gắng hoàn thiện bài tiểu luận trong phạm vi khả năng, em nhận thấy rằng vẫn còn một số thiếu sót nhất định. Kính mong Thầy dành thời gian góp ý, nhận xét để em có thể tiếp tục rèn luyện và hoàn thiện hơn trong những nghiên cứu sau này.
Cuối cùng, em xin kính chúc Thầy dồi dào sức khỏe, tràn đầy nhiệt huyết và gặt hái nhiều thành công trong sự nghiệp giáo dục. Em xin chân thành cảm ơn!
Em xin cam đoan rằng toàn bộ số liệu, kết quả phân tích và nội dung trình bày trong bài tiểu luận này là trung thực, được thu thập từ các nguồn tin cậy và trích dẫn rõ ràng. Các thông tin, dữ liệu được sử dụng hoàn toàn phục vụ mục đích học tập và nghiên cứu, không sao chép hay vi phạm bản quyền của bất kỳ cá nhân, tổ chức nào.
Bài báo cáo tiểu luận của nhóm chúng em gồm hai phần nội dung chính:
Phần 1: Phân tích bộ dữ liệu chuyến bay tại Mỹ giai đoạn 2 tháng đầu năm 2024.
Phần 2: Phân tích Công ty Cổ phần Tập đoàn Đầu tư Địa ốc No Va thông qua báo cáo tài chính giai đoạn 2015 – 2024.
Hai phần trên là những nội dung nghiên cứu tách biệt, được thực hiện song song nhằm phục vụ cho mục tiêu học tập và rèn luyện kỹ năng phân tích dữ liệu, tổng hợp thông tin kinh tế – tài chính.
Tên bộ dữ liệu: Flight Delay Dataset 2024
Nguồn bộ dữ liệu: https: www.kaggle.com/datasets/hrishitpatil/flight-data-2024
Thông tin bộ dữ liệu: Bộ dữ liệu này chứa thông tin chi tiết về hiệu suất chuyến bay và độ trễ cho các chuyến bay nội địa vào năm 2024, được hợp nhất từ các tệp BTS TranStats hàng tháng thành một bộ dữ liệu được làm sạch duy nhất.
Nó cung cấp thông tin toàn diện về thời gian bay theo lịch trình và thực tế, sự chậm trễ, hủy chuyến, chuyển hướng và khoảng cách giữa các sân bay.
Bộ dữ liệu phù hợp cho phân tích dữ liệu khám phá (EDA), các tác vụ học máy như dự đoán độ trễ, phân tích chuỗi thời gian và nghiên cứu hiệu suất của hãng hàng không/sân bay.
Mục đích lấy dữ liệu: Dữ liệu được dùng để xử lý, làm sạch và phân tích bộ dữ liệu nhằm hiểu rõ đặc điểm của các chuyến bay.
flight_data_2024 <- read.csv("C:/Users/LENOVO/Downloads/flight_data_2024.csv")
dim(flight_data_2024)
## [1] 1048575 26
Giải thích: (1) dùng để kiểm tra kích thước của bộ dữ liệu.
Nhận xét: Bộ dữ liệu có 1.048.575 quan sát và 26 biến.
names(flight_data_2024)
## [1] "month" "day_of_month" "day_of_week"
## [4] "fl_date" "op_unique_carrier" "op_carrier_fl_num"
## [7] "origin" "origin_city_name" "origin_state_nm"
## [10] "dest" "dest_city_name" "dest_state_nm"
## [13] "crs_dep_time" "dep_time" "dep_delay"
## [16] "taxi_out" "wheels_off" "wheels_on"
## [19] "taxi_in" "crs_arr_time" "arr_time"
## [22] "arr_delay" "crs_elapsed_time" "actual_elapsed_time"
## [25] "air_time" "distance"
Giải thích: (1) Trả về tên các biến
(cột) trong dữ liệu flight_data_2024.
Nhận xét: Kết quả cung cấp danh sách tên biến nhằm làm nền tảng cho các bước mô tả, so sánh và mô hình hóa trong phân tích thống kê sau này.
loai<- data.frame(Kieu_du_lieu = sapply(flight_data_2024, typeof))
kable(loai, col.names = c("Tên biến", "Kiểu dữ liệu"))
| Tên biến | Kiểu dữ liệu |
|---|---|
| month | integer |
| day_of_month | integer |
| day_of_week | integer |
| fl_date | character |
| op_unique_carrier | character |
| op_carrier_fl_num | integer |
| origin | character |
| origin_city_name | character |
| origin_state_nm | character |
| dest | character |
| dest_city_name | character |
| dest_state_nm | character |
| crs_dep_time | integer |
| dep_time | integer |
| dep_delay | integer |
| taxi_out | integer |
| wheels_off | integer |
| wheels_on | integer |
| taxi_in | integer |
| crs_arr_time | integer |
| arr_time | integer |
| arr_delay | integer |
| crs_elapsed_time | integer |
| actual_elapsed_time | integer |
| air_time | integer |
| distance | integer |
Giải thích:
(1) Tạo data frame loai chứa kiểu dữ
liệu của từng biến trong flight_data_2024 bằng hàm
sapply().
(2) Dùng hàm kable() để hiển thị bảng
loai với hai cột: “Tên biến” và “Kiểu dữ liệu”.
Nhận xét:
Các biến định lượng (integer) như: month, day_of_month,
day_of_week, op_carrier_fl_num, crs_dep_time, dep_time,
dep_delay,…
được dùng để tính trung bình, so sánh, đo lường, vẽ biểu đồ phân bố
(histogram, boxplot).
Các biến định tính (character) như: fl_date, op_unique_carrier, origin, origin_city_name, origin_state_nm, dest, dest_city_name,…dùng để mô tả, phân loại, vẽ bar chart hoặc pie chart.
table(sapply(flight_data_2024, typeof))
##
## character integer
## 8 18
Giải thích: (1) Tạo bảng tần suất
thể hiện số lượng các kiểu dữ liệu khác nhau trong
flight_data_2024.
Nhận xét: Bộ dữ liệu có 8 biến thuộc kiểu character và 18 biến thuộc kiểu integer.
sum(duplicated(flight_data_2024))
## [1] 0
Giải thích: (1) Trả về tổng số dòng
bị trùng lặp trong dữ liệu flight_data_2024.
Nhận xét: Không có quan sát bị trùng lặp trong bộ dữ liệu vì tổng số dòng dữ liệu bị trùng lặp bằng 0.
kable(t(head(flight_data_2024, 5)))
| 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|
| month | 1 | 1 | 1 | 1 | 1 |
| day_of_month | 1 | 1 | 1 | 1 | 1 |
| day_of_week | 1 | 1 | 1 | 1 | 1 |
| fl_date | 01/01/2024 | 01/01/2024 | 01/01/2024 | 01/01/2024 | 01/01/2024 |
| op_unique_carrier | 9E | 9E | 9E | 9E | 9E |
| op_carrier_fl_num | 4814 | 4815 | 4817 | 4817 | 4818 |
| origin | JFK | MSP | JFK | RIC | DTW |
| origin_city_name | New York, NY | Minneapolis, MN | New York, NY | Richmond, VA | Detroit, MI |
| origin_state_nm | New York | Minnesota | New York | Virginia | Michigan |
| dest | DTW | CLE | RIC | JFK | MKE |
| dest_city_name | Detroit, MI | Cleveland, OH | Richmond, VA | New York, NY | Milwaukee, WI |
| dest_state_nm | Michigan | Ohio | Virginia | New York | Wisconsin |
| crs_dep_time | 1252 | 1015 | 1415 | 1650 | 1015 |
| dep_time | 1247 | 1001 | 1411 | 1643 | 1010 |
| dep_delay | -5 | -14 | -4 | -7 | -5 |
| taxi_out | 31 | 20 | 21 | 13 | 21 |
| wheels_off | 1318 | 1021 | 1432 | 1656 | 1031 |
| wheels_on | 1442 | 1249 | 1533 | 1747 | 1016 |
| taxi_in | 7 | 6 | 8 | 12 | 4 |
| crs_arr_time | 1508 | 1325 | 1601 | 1841 | 1034 |
| arr_time | 1449 | 1255 | 1541 | 1759 | 1020 |
| arr_delay | -19 | -30 | -20 | -42 | -14 |
| crs_elapsed_time | 136 | 130 | 106 | 111 | 79 |
| actual_elapsed_time | 122 | 114 | 90 | 76 | 70 |
| air_time | 84 | 88 | 61 | 51 | 45 |
| distance | 509 | 622 | 288 | 288 | 237 |
Giải thích: (1) Hiển thị 5 dòng đầu
tiên của dữ liệu flight_data_2024, chuyển vị để hiển thị
biến theo hàng và dùng kable() để trình bày bảng dữ liệu
mẫu đẹp.
Nhận xét: Việc quan sát 5 dòng đầu giúp hiểu cấu trúc dữ liệu trước khi phân tích thống kê.
kable(t(tail(flight_data_2024, 5)))
| 1048571 | 1048572 | 1048573 | 1048574 | 1048575 | |
|---|---|---|---|---|---|
| month | 2 | 2 | 2 | 2 | 2 |
| day_of_month | 29 | 29 | 29 | 29 | 29 |
| day_of_week | 4 | 4 | 4 | 4 | 4 |
| fl_date | 29/02/2024 | 29/02/2024 | 29/02/2024 | 29/02/2024 | 29/02/2024 |
| op_unique_carrier | AA | AA | AA | AA | AA |
| op_carrier_fl_num | 1613 | 1614 | 1615 | 1616 | 1616 |
| origin | SJU | PHX | JAX | CLT | MCI |
| origin_city_name | San Juan, PR | Phoenix, AZ | Jacksonville, FL | Charlotte, NC | Kansas City, MO |
| origin_state_nm | Puerto Rico | Arizona | Florida | North Carolina | Missouri |
| dest | MIA | MIA | CLT | MCI | CLT |
| dest_city_name | Miami, FL | Miami, FL | Charlotte, NC | Kansas City, MO | Charlotte, NC |
| dest_state_nm | Florida | Florida | North Carolina | Missouri | North Carolina |
| crs_dep_time | 1455 | 2255 | 2018 | 900 | 1123 |
| dep_time | 1447 | 59 | 2014 | 1104 | 1307 |
| dep_delay | -8 | 124 | -4 | 124 | 104 |
| taxi_out | 24 | 12 | 20 | 12 | 13 |
| wheels_off | 1511 | 111 | 2034 | 1116 | 1320 |
| wheels_on | 1640 | 647 | 2128 | 1210 | 1559 |
| taxi_in | 7 | 3 | 10 | 7 | 22 |
| crs_arr_time | 1646 | 502 | 2143 | 1033 | 1428 |
| arr_time | 1647 | 650 | 2138 | 1217 | 1621 |
| arr_delay | 1 | 108 | -5 | 104 | 113 |
| crs_elapsed_time | 171 | 247 | 85 | 153 | 125 |
| actual_elapsed_time | 180 | 231 | 84 | 133 | 134 |
| air_time | 149 | 216 | 54 | 114 | 99 |
| distance | 1045 | 1972 | 328 | 808 | 808 |
Giải thích: (1) Hiển thị 5 dòng
cuối cùng của dữ liệu flight_data_2024, chuyển vị để hiển
thị biến theo hàng và dùng kable() để trình bày bảng dữ
liệu mẫu đẹp.
Nhận xét: Việc quan sát 5 dòng cuối giúp kiểm tra tính đầy đủ, phát hiện các dữ liệu bị thiếu ở cuối bảng trước khi tiến hành phân tích thống kê.
length(unique(flight_data_2024$op_unique_carrier))
## [1] 15
Giải thích: (1) Trả về số lượng
hãng hàng không duy nhất trong biến op_unique_carrier của
dữ liệu flight_data_2024.
Nhận xét: Bộ dữ liệu có 15 hãng hàng không khác nhau thực hiện chuyến bay trong tháng 1 và tháng 2.
hang_bay <- data.frame(STT = 1:length(unique(flight_data_2024$op_unique_carrier)),
Hang_bay = unique(flight_data_2024$op_unique_carrier))
kable(hang_bay, col.names = c("STT", "Hãng bay"), align = c("c", "l")) %>%
kable_styling(full_width = FALSE, position = "center") %>%
column_spec(1, width = "4em") %>%
column_spec(2, width = "15em")
| STT | Hãng bay |
|---|---|
| 1 | 9E |
| 2 | AA |
| 3 | AS |
| 4 | B6 |
| 5 | DL |
| 6 | F9 |
| 7 | G4 |
| 8 | HA |
| 9 | MQ |
| 10 | NK |
| 11 | OH |
| 12 | OO |
| 13 | UA |
| 14 | WN |
| 15 | YX |
Giải thích:
(1-2) Tạo data frame hang_bay gồm hai
cột: STT (số thứ tự) và Hang_bay.
(3) Dùng kable() để tạo bảng với hai
cột “STT” và “Hãng bay”, căn giữa và trái tương ứng.
(4-6) Dùng để căn giữa bảng, thu hẹp chiều rộng, và định dạng cột hiển thị rõ ràng.
data_dict <- data.frame(variable = c("month", "day_of_month", "day_of_week", "fl_date", "op_unique_carrier",
"op_carrier_fl_num", "origin", "origin_city_name", "origin_state_nm",
"dest", "dest_city_name", "dest_state_nm", "crs_dep_time", "dep_time",
"dep_delay", "taxi_out", "wheels_off", "wheels_on", "taxi_in",
"crs_arr_time", "arr_time", "arr_delay", "crs_elapsed_time",
"actual_elapsed_time", "air_time", "distance"),
"Ý nghĩa" = c(
"Tháng trong năm, cho biết chuyến bay vào tháng nào trong năm.",
"Ngày trong tháng, cho biết ngày bay vào ngày nào trong tháng.",
"Ngày trong tuần, cho biết chuyến bay vào ngày nào trong tuần.",
"Ngày bay.",
"Mã hãng hàng không thực hiện chuyến bay.",
"Số hiệu chuyến bay của hãng.",
"Mã sân bay khởi hành.",
"Tên thành phố khởi hành.",
"Tên bang hoặc khu vực sân bay khởi hành.",
"Mã sân bay đến.",
"Tên thành phố đến.",
"Tên bang hoặc khu vực sân bay đến.",
"Giờ dự kiến cất cánh (theo lịch).",
"Giờ thực tế cất cánh.",
"Độ trễ cất cánh (phút), giá trị âm nếu cất cánh sớm hơn dự kiến.",
"Khoảng thời gian máy bay di chuyển từ cổng ra tới vị trí chuẩn bị cất cánh trên đường băng.",
"Thời điểm bánh xe rời mặt đất (giờ–phút).",
"Thời điểm bánh xe chạm đất tại sân bay đến (giờ–phút).",
"Khoảng thời gian máy bay di chuyển trên mặt đất từ khi vừa hạ cánh cho đến khi dừng hẳn tại cổng.",
"Giờ dự kiến hạ cánh (theo lịch).",
"Giờ thực tế hạ cánh.",
"Độ trễ hạ cánh (phút), giá trị âm nếu hạ cánh sớm hơn dự kiến.",
"Thời gian dự kiến bay (phút).",
"Thời gian bay thực tế (phút).",
"Thời gian bay trên không (phút).",
"Khoảng cách giữa sân bay đi và đến (dặm)."))
kable(data_dict, col.names = c("Tên biến", "Ý nghĩa"))
| Tên biến | Ý nghĩa |
|---|---|
| month | Tháng trong năm, cho biết chuyến bay vào tháng nào trong năm. |
| day_of_month | Ngày trong tháng, cho biết ngày bay vào ngày nào trong tháng. |
| day_of_week | Ngày trong tuần, cho biết chuyến bay vào ngày nào trong tuần. |
| fl_date | Ngày bay. |
| op_unique_carrier | Mã hãng hàng không thực hiện chuyến bay. |
| op_carrier_fl_num | Số hiệu chuyến bay của hãng. |
| origin | Mã sân bay khởi hành. |
| origin_city_name | Tên thành phố khởi hành. |
| origin_state_nm | Tên bang hoặc khu vực sân bay khởi hành. |
| dest | Mã sân bay đến. |
| dest_city_name | Tên thành phố đến. |
| dest_state_nm | Tên bang hoặc khu vực sân bay đến. |
| crs_dep_time | Giờ dự kiến cất cánh (theo lịch). |
| dep_time | Giờ thực tế cất cánh. |
| dep_delay | Độ trễ cất cánh (phút), giá trị âm nếu cất cánh sớm hơn dự kiến. |
| taxi_out | Khoảng thời gian máy bay di chuyển từ cổng ra tới vị trí chuẩn bị cất cánh trên đường băng. |
| wheels_off | Thời điểm bánh xe rời mặt đất (giờ–phút). |
| wheels_on | Thời điểm bánh xe chạm đất tại sân bay đến (giờ–phút). |
| taxi_in | Khoảng thời gian máy bay di chuyển trên mặt đất từ khi vừa hạ cánh cho đến khi dừng hẳn tại cổng. |
| crs_arr_time | Giờ dự kiến hạ cánh (theo lịch). |
| arr_time | Giờ thực tế hạ cánh. |
| arr_delay | Độ trễ hạ cánh (phút), giá trị âm nếu hạ cánh sớm hơn dự kiến. |
| crs_elapsed_time | Thời gian dự kiến bay (phút). |
| actual_elapsed_time | Thời gian bay thực tế (phút). |
| air_time | Thời gian bay trên không (phút). |
| distance | Khoảng cách giữa sân bay đi và đến (dặm). |
Giải thích:
(1) Tạo bảng data_dict gồm hai cột:
“Tên biến” và “Ý nghĩa”.
(21) dùng để hiển thị bảng với hai tiêu đề cột tương ứng.
Kiểm tra xem trong toàn bộ bảng dữ liệu có tồn tại giá trị bị thiếu (NA) ở bất kỳ vị trí nào hay không:
any(is.na(flight_data_2024))
## [1] TRUE
Giải thích: (1) Kiểm tra xem trong
dữ liệu flight_data_2024 có tồn tại giá trị thiếu hay
không.
Nhận xét: Vì kết quả trả về là TRUE nên bộ dữ liệu có ít nhất một ô dữ liệu bị thiếu ở bất kỳ hàng, cột nào. Ta thực hiện đếm số lượng giá trị bị thiếu (NA) ở từng biến.
colSums(is.na(flight_data_2024))
## month day_of_month day_of_week fl_date
## 0 0 0 0
## op_unique_carrier op_carrier_fl_num origin origin_city_name
## 0 0 0 0
## origin_state_nm dest dest_city_name dest_state_nm
## 0 0 0 0
## crs_dep_time dep_time dep_delay taxi_out
## 0 22553 22650 23125
## wheels_off wheels_on taxi_in crs_arr_time
## 23125 23677 23677 0
## arr_time arr_delay crs_elapsed_time actual_elapsed_time
## 23675 25751 1 25751
## air_time distance
## 25751 0
Giải thích: (1) Trả về tổng số giá
trị thiếu của từng biến trong dữ liệu flight_data_2024.
Nhận xét: Các cột có giá trị 0 là các cột không bị thiếu dữ liệu. Còn lại có giá trị bị thiếu cần được xử lý
Vì các biến bị thiếu không phải là biến trọng yếu và số lượng giá trị thiếu ở các biến là nhỏ, không ảnh hưởng đến tổng thể dữ liệu nên phương pháp xử lý NA phù hợp nhất là loại bỏ các dòng bị thiếu.
flight_data_clean <- na.omit(flight_data_2024)
colSums(is.na(flight_data_clean))
## month day_of_month day_of_week fl_date
## 0 0 0 0
## op_unique_carrier op_carrier_fl_num origin origin_city_name
## 0 0 0 0
## origin_state_nm dest dest_city_name dest_state_nm
## 0 0 0 0
## crs_dep_time dep_time dep_delay taxi_out
## 0 0 0 0
## wheels_off wheels_on taxi_in crs_arr_time
## 0 0 0 0
## arr_time arr_delay crs_elapsed_time actual_elapsed_time
## 0 0 0 0
## air_time distance
## 0 0
Giải thích:
(1) Tạo dữ liệu mới flight_data_clean
bằng cách loại bỏ toàn bộ các dòng chứa giá trị thiếu (NA)
trong flight_data_2024.
(2) Kiểm tra lại số lượng giá trị thiếu của từng
biến trong flight_data_clean sau khi đã xử lý.
Nhận xét: Bộ dữ liệu không còn giá trị thiếu.
Biến op_unique_carrier thể hiện mã hãng hàng không thực hiện chuyến bay. Mặc dù được lưu dưới dạng ký tự (character), nhưng giá trị của biến này chỉ dùng để phân loại các hãng bay chứ không mang ý nghĩa văn bản.
Do đó, việc chuyển sang dạng factor giúp phần mềm nhận diện đúng bản chất là biến định tính phân loại, thay vì biến chuỗi thông thường.
flight_data_clean$op_unique_carrier <- as.factor(flight_data_clean$op_unique_carrier)
class(flight_data_clean$op_unique_carrier)
## [1] "factor"
Giải thích:
(1) Chuyển biến op_unique_carrier trong
dữ liệu flight_data_clean sang kiểu factor.
(2) Kiểm tra kiểu dữ liệu của biến
op_unique_carrier sau khi chuyển đổi.
Nhận xét: Kết quả “factor” xác nhận việc chuyển đổi đã thành công.
Biến op_carrier_fl_num thể hiện mã số chuyến bay của hãng hàng không. Biến này ban đầu được lưu dưới dạng số nguyên (integer), tuy nhiên các giá trị của nó chỉ mang tính định danh cho từng chuyến bay, chứ không mang ý nghĩa đo lường hay thứ tự.
Do đó, việc chuyển sang dạng character giúp lưu trữ chính xác hơn bản chất nhận dạng (ID) của biến mà không làm phát sinh các xử lý nhầm lẫn như biến số.
flight_data_clean$op_carrier_fl_num <- as.character(flight_data_clean$op_carrier_fl_num)
class(flight_data_clean$op_carrier_fl_num)
## [1] "character"
Giải thích:
(1) Chuyển biến op_carrier_fl_num trong
dữ liệu flight_data_clean sang kiểu
character.
(2) Kiểm tra kiểu dữ liệu của biến
op_carrier_fl_num sau khi chuyển đổi.
Nhận xét: Kết quả “character” xác nhận việc chuyển đổi đã thành công.
Khi chuyển tất cả các cột thời gian (departure, arrival, wheels_off, wheels_on) đều ở đơn vị “phút trong ngày”, giúp dữ liệu trở nên đồng bộ, khiến dữ liệu trở nên đơn giản và trực quan hơn.
convert_to_minutes <- function(x) {
hour <- floor(x / 100)
minute <- x %% 100
total_minutes <- hour * 60 + minute
return(total_minutes)}
flight_data_clean <- flight_data_clean %>%
mutate(
crs_dep_time_min = convert_to_minutes(crs_dep_time),
dep_time_min = convert_to_minutes(dep_time),
wheels_off_min = convert_to_minutes(wheels_off),
wheels_on_min = convert_to_minutes(wheels_on),
crs_arr_time_min = convert_to_minutes(crs_arr_time),
arr_time_min = convert_to_minutes(arr_time))
Giải thích:
(1) hàm convert_to_minutes() chuyển đổi
giá trị thời gian định dạng giờ trong ngày sang phút.
(7) Sử dụng mutate() để tạo thêm các
biến thời gian mới (đuôi _min) bằng cách áp dụng hàm
convert_to_minutes() cho các biến thời gian tương ứng trong
flight_data_clean.
Biến day_of_week trong bộ dữ liệu biểu thị ngày trong tuần với giá trị từ 1 đến 7.
Trong đó: 1 = Thứ Hai, 2 = Thứ Ba, …, 6 = Thứ Bảy, 7 = Chủ Nhật.
Theo đó, một chuyến bay được xem là chuyến bay cuối tuần nếu giá trị của day_of_week là 6 hoặc 7.
flight_data_clean$weekend_flight <- ifelse(flight_data_clean$day_of_week %in% c(6, 7), 1, 0)
table(flight_data_clean$weekend_flight)
##
## 0 1
## 753717 269107
Giải thích:
(1) Tạo biến mới weekend_flight, gán
giá trị 1 nếu chuyến bay diễn ra vào thứ 6 hoặc 7, ngược lại gán 0.
(2) Tạo bảng tần suất thể hiện số lượng chuyến bay diễn ra vào cuối tuần và các ngày trong tuần.
Nhận xét: Trong bộ dữ liệu có tổng cộng 269107 chuyến bay diễn ra vào cuối tuần (Thứ Bảy và Chủ Nhật), còn lại diễn ra vào các ngày thường gồm 753717 chuyến bay.
Nhằm phục vụ phân tích xu hướng trễ chuyến bay theo thời điểm, tiến hành phân loại các chuyến bay trong tập dữ liệu thành bốn giai đoạn trong ngày (Morning, Afternoon, Evening, Night) dựa trên thời gian khởi hành (dep_time).
flight_data_clean$day_period <- ifelse(
flight_data_clean$dep_time >= 300 & flight_data_clean$dep_time < 720, "Morning",
ifelse(
flight_data_clean$dep_time >= 720 & flight_data_clean$dep_time < 1080, "Afternoon",
ifelse(
flight_data_clean$dep_time >= 1080 & flight_data_clean$dep_time < 1320, "Evening",
"Night")))
flight_data_clean$day_period <- as.factor(flight_data_clean$day_period)
summary(flight_data_clean$day_period)
## Afternoon Evening Morning Night
## 223079 142217 136900 520628
Giải thích:
(1-4) Tạo biến mới day_period phân loại
thời gian cất cánh thành bốn nhóm: Morning, Afternoon,
Evening và Night dựa trên giá trị
dep_time.
(5) Chuyển day_period sang kiểu factor
để phục vụ cho phân tích thống kê.
(6) thống kê tần suất của từng nhóm thời gian trong
biến day_period.
Nhận xét: Việc phân chia chuyến bay theo bốn khoảng thời gian - Morning (136.900 chuyến), Afternoon (223.079 chuyến), Evening (142.217 chuyến), và Night (520.628 chuyến) - cho thấy sự tập trung rõ ràng của lưu lượng bay vào ban đêm.
Trong phân tích hoạt động bay, tốc độ trung bình là chỉ số quan trọng giúp đánh giá hiệu quả khai thác và điều kiện vận hành của các chuyến bay. Để tính tốc độ trung bình (đơn vị: dặm/giờ), ta dựa vào hai biến sẵn có trong dữ liệu là distance và air_time.
Để phép chia hợp lệ (tránh chia cho 0 hoặc giá trị âm), ta phải kiểm định trước xem air_time và distance có > 0 trong toàn bộ dữ liệu hay không.
sum(flight_data_clean$air_time <= 0)
## [1] 0
sum(flight_data_clean$distance <= 0)
## [1] 0
Giải thích:
(1) Đếm số chuyến bay có thời gian bay
(air_time) hoặc khoảng cách (distance) nhỏ hơn
hoặc bằng 0.
Kết quả cho thấy không có quan sát nào trong bộ dữ liệu có giá trị air_time ≤ 0 hoặc distance ≤ 0.Điều này cho thấy dữ liệu hoàn toàn thỏa mãn điều kiện vật lý của chuyến bay — thời gian bay và quãng đường đều dương.
Vì vậy, có thể an toàn tính toán biến tốc độ trung bình
flight_data_clean$speed_mph <- flight_data_clean$distance / (flight_data_clean$air_time / 60)
summary(flight_data_clean$speed_mph)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.16 360.00 407.75 405.57 453.75 4473.33
Giải thích:
(1) Tính tốc độ trung bình speed_mph
của mỗi chuyến bay bằng công thức: quãng đường bay
(distance) chia cho thời gian bay (giờ).
(2) Dùng summary() để thống kê mô tả
biến speed_mph.
Nhận xét: Ta thấy giá trị nhỏ nhất chỉ 21.16 mph và giá trị lớn nhất tới 4473.33 là không thực tế, vì vận tốc này chênh lệch hơn nhiều so với tốc độ cất hạ cánh của máy bay. Nguyên nhân có thể do lỗi nhập liệu, thời gian bay ghi sai, hoặc sự cố trong quá trình đo đạc. Do đó, các giá trị tốc độ quá thấp hoặc quá cao (ngoại lai) cần được loại bỏ hoặc hiệu chỉnh ở bước xử lý kế tiếp, nhằm đảm bảo tính chính xác cho các phân tích mô tả và hồi quy sau này.
Q1 <- quantile(flight_data_clean$speed_mph, 0.25, na.rm = TRUE)
Q3 <- quantile(flight_data_clean$speed_mph, 0.75, na.rm = TRUE)
IQR_value <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR_value
upper_bound <- Q3 + 1.5 * IQR_value
flight_data_no_outlier <- flight_data_clean %>%
filter(speed_mph >= lower_bound & speed_mph <= upper_bound)
summary(flight_data_no_outlier$speed_mph)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 219.4 361.6 408.7 407.8 454.2 594.4
Giải thích:
(1-2) Tính các giá trị tứ phân vị thứ nhất
(Q1) và thứ ba (Q3) của biến
speed_mph.
(3) Tính khoảng tứ phân vị (IQR_value)
và xác định ngưỡng dưới (lower_bound) và ngưỡng trên
(upper_bound) để phát hiện ngoại lai.
(6-7) Lọc dữ liệu flight_data_clean để
loại bỏ các giá trị ngoại lai của speed_mph, lưu vào
flight_data_no_outlier.
(8) Dùng summary() để thống kê lại phân
bố của biến speed_mph sau khi loại ngoại lai.
Nhận xét: Sau khi lọc, khoảng giá trị từ 219,4 đến 594,4 dặm/giờ trở nên hợp lý, với tốc độ trung bình khoảng 408 dặm/giờ, phù hợp với đặc điểm kỹ thuật của máy bay phản lực dân dụng, có độ tin cậy cao hơn, sẵn sàng cho các phân tích mô tả và mô hình hóa tiếp theo.
Biến schedule_diff được tạo nhằm thể hiện mức độ khác biệt giữa thời gian bay thực tế (actual_elapsed_time) và thời gian bay theo lịch trình (crs_elapsed_time). Giá trị dương cho thấy chuyến bay kéo dài hơn dự kiến, trong khi giá trị âm phản ánh thời gian thực tế ngắn hơn so với kế hoạch.
flight_data_no_outlier <- flight_data_no_outlier %>%
mutate(schedule_diff = actual_elapsed_time - crs_elapsed_time)
View(flight_data_no_outlier)
Giải thích:
(2) Tạo biến mới schedule_diff bằng
hiệu giữa actual_elapsed_time và
crs_elapsed_time, thể hiện chênh lệch giữa thời gian bay
thực tế và thời gian dự kiến.
(3) Dùng View() để mở bảng dữ liệu
flight_data_no_outlier trong cửa sổ xem dữ liệu của
RStudio.
Nhận xét: Việc tạo biến schedule_diff giúp đánh giá chính xác hơn hiệu suất vận hành của từng hãng hàng không. Chỉ số này có thể được dùng để phát hiện chuyến bay có xu hướng kéo dài thường xuyên, qua đó hỗ trợ cải thiện kế hoạch bay và dự báo thời gian thực tế tốt hơn.
Phân tích đặc điểm cơ bản của 4 biến định lượng: air_time, schedule_diff, distance và dep_delay.
quant_vars <- flight_data_no_outlier[, c("air_time", "schedule_diff", "distance","dep_delay")]
Giải thích: (1) Tạo đối tượng
quant_vars chứa bốn biến định lượng air_time,
schedule_diff, dep_delay và
distance từ dữ liệu
flight_data_no_outlier.
Nhận xét: Lọc 3 biến định lượng này ra nhằm thống kê mô tả, tính trung bình, tính độ lệch chuẩn và tính khoảng của từng biến ở các bước tiếp theo.
summary(quant_vars)
## air_time schedule_diff distance dep_delay
## Min. : 8 Min. :-773.000 Min. : 31 Min. : -96.00
## 1st Qu.: 65 1st Qu.: -15.000 1st Qu.: 406 1st Qu.: -6.00
## Median :101 Median : -7.000 Median : 699 Median : -2.00
## Mean :117 Mean : -6.026 Mean : 839 Mean : 11.52
## 3rd Qu.:147 3rd Qu.: 1.000 3rd Qu.:1072 3rd Qu.: 8.00
## Max. :703 Max. : 500.000 Max. :5095 Max. :3125.00
Giải thích: (1) Tóm tắt thống kê mô
tả cho ba biến định lượng trong quant_vars, gồm giá trị nhỏ
nhất, lớn nhất, trung bình, trung vị và các tứ phân vị.
Biến air_time có giá trị dao động từ 8 đến 703 phút, thể
hiện sự biến thiên đáng kể giữa các tuyến bay.
Giá trị trung vị 101 phút và trung bình 117 phút cho thấy phần lớn các chuyến bay có thời gian bay trung bình, trong khi một số tuyến dài hơn đáng kể đã kéo trung bình tăng cao, phản ánh đặc trưng phân bố lệch phải.
Biến schedule_diff biến thiên từ -773 đến 500 phút, với
trung bình -6,03 phút và trung vị -7 phút, cho thấy phần lớn chuyến bay
kết thúc sớm hơn kế hoạch, tuy nhiên vẫn tồn tại một số trường hợp chậm
nghiêm trọng, làm tăng độ lệch của phân bố.
Biến distance dao động từ 31 đến 5.095 dặm, với trung
bình 839 dặm và trung vị 699 dặm, phản ánh sự đa dạng về cự ly khai thác
giữa các tuyến bay ngắn nội bang và các tuyến bay dài xuyên vùng, thể
hiện rõ tính phân tầng trong mạng lưới hàng không.
Biến dep_delay thể hiện mức độ biến thiên lớn, dao động
từ -96 đến 3.125 phút, phản ánh sự khác biệt đáng kể trong thời gian
khởi hành giữa các chuyến bay.
Giá trị trung vị -2 phút cho thấy phần lớn chuyến bay khởi hành đúng hoặc sớm nhẹ, trong khi trung bình 11,52 phút bị kéo lên do ảnh hưởng của một số trường hợp trễ nghiêm trọng, biểu hiện đặc trưng của phân bố lệch phải trong dữ liệu độ trễ.
sapply(quant_vars, sd)
## air_time schedule_diff distance dep_delay
## 70.58144 15.18577 584.93699 56.23152
Giải thích: (1) Tính độ lệch chuẩn
cho từng biến định lượng trong quant_vars.
Nhận xét:
Biến air_time có độ lệch chuẩn 70,58 phút, cho thấy mức độ phân tán lớn trong thời gian bay giữa các tuyến.
Biến schedule_diff có độ lệch chuẩn 15,19 phút, phản ánh dao động vừa phải giữa thời gian thực tế và lịch trình.
Biến distance có độ lệch chuẩn 584,94 dặm, thể hiện sự khác biệt rõ rệt về phạm vi tuyến bay trong toàn bộ mạng lưới.
Biến dep_delay có độ lệch chuẩn 56,23 phút, cho thấy biến động đáng kể trong thời gian khởi hành, với nhiều chuyến bay bị trễ hoặc sớm bất thường.
sapply(quant_vars, var, na.rm = TRUE)
## air_time schedule_diff distance dep_delay
## 4981.7395 230.6076 342151.2792 3161.9840
Giải thích:
Biến air_time (4.981,74) và distance (342.151,28) có phương sai lớn, phản ánh sự phân tán mạnh giữa các tuyến bay ngắn và dài.
Biến schedule_diff (230,61) có phương sai thấp hơn, cho thấy sự ổn định tương đối giữa thời gian thực tế và lịch trình.
Trong khi đó, dep_delay (3.161,98) phản ánh tình trạng phương sai sai số thay đổi rõ rệt giữa các chuyến bay, tức là mức độ biến động của độ trễ không đồng nhất, tăng dần theo các điều kiện vận hành khác nhau.
sapply(quant_vars, function(x) max(x) - min(x))
## air_time schedule_diff distance dep_delay
## 695 1273 5064 3221
Giải thích: (1) Trả về khoảng biến
thiên (hiệu giữa giá trị lớn nhất và nhỏ nhất) của từng biến trong
quant_vars.
Nhận xét:
Khoảng giá trị của các biến phản ánh mức độ phân tán và đặc trưng khai thác khác nhau giữa các chuyến bay.
Biến air_time (695 phút) thể hiện sự chênh lệch giữa các
tuyến bay ngắn và dài, trong khi schedule_diff (1.273 phút)
cho thấy độ lệch lớn giữa thực tế và lịch trình.
Distance (5.064 dặm) minh chứng cho sự đa dạng về cự ly,
còn dep_delay (3.221 phút) phản ánh mức biến động cao trong
thời gian khởi hành.
qual_vars <- flight_data_no_outlier[, c("op_unique_carrier", "origin", "dest")]
Giải thích:
(1) Tạo dữ liệu qual_vars gồm ba biến
định tính: op_unique_carrier, origin và
dest từ flight_data_clean.
Nhận xét: Lọc 3 biến định tính này ra nhằm xem tần suất xuất hiện, tạo bảng tần suất, tính tần suất tương đối và sắp xếp các nhóm theo tần suất giảm dần.
table_carrier <- as.data.frame(table(flight_data_no_outlier$op_unique_carrier))
kable(table_carrier, col.names = c("Hãng", "Tần suất"), options = list(pageLength = 10),
caption = "**Bảng tần suất hãng hàng không thực hiện chuyến bay**")
| Hãng | Tần suất |
|---|---|
| 9E | 31053 |
| AA | 147210 |
| AS | 30255 |
| B6 | 37060 |
| DL | 141543 |
| F9 | 27544 |
| G4 | 16369 |
| HA | 11770 |
| MQ | 38334 |
| NK | 39048 |
| OH | 28685 |
| OO | 100015 |
| UA | 107441 |
| WN | 211567 |
| YX | 41396 |
Giải thích:
(1) Tạo bảng tần suất table_carrier cho
biến op_unique_carrier trong
flight_data_no_outlier.
(2) Hiển thị bảng bằng kable() với tiêu
đề “Bảng tần suất hãng hàng không thực hiện chuyến bay”.
Nhận xét: Số lượng chuyến bay giữa các hãng phân bố không đều, chứng tỏ mức độ hoạt động của từng hãng có sự khác biệt.
table_origin <- as.data.frame(table(flight_data_no_outlier$origin))
colnames(table_origin) <- c("Mã sân bay xuất phát", "Số chuyến bay")
table_origin <- table_origin[order(-table_origin$'Số chuyến bay'), ]
kable(head(table_origin, 10),
caption = "**Tần suất 10 sân bay xuất phát có số chuyến bay cao nhất**", row.names = FALSE, align = "lc")
| Mã sân bay xuất phát | Số chuyến bay |
|---|---|
| ATL | 49667 |
| DFW | 44431 |
| DEN | 42461 |
| ORD | 37057 |
| CLT | 30470 |
| PHX | 29025 |
| LAS | 27791 |
| LAX | 27741 |
| MCO | 26862 |
| LGA | 23926 |
Giải thích:
(1) Tạo bảng thống kê số chuyến bay theo từng mã sân bay xuất phát.
(2) Đặt lại tên cột thành “Mã sân bay xuất phát” và “Số chuyến bay”.
(3) Sắp xếp bảng giảm dần theo “Số chuyến bay”.
(4) Dùng kable() hiển thị 10 sân bay
xuất phát có số chuyến bay cao nhất, kèm chú thích.
Nhận xét: Mười sân bay có tần suất chuyến bay xuất phát cao nhất đều là trung tâm hàng không trọng điểm của Hoa Kỳ. Sân bay ATL (Atlanta) dẫn đầu về số chuyến bay xuất phát, thể hiện vai trò trung tâm trung chuyển quốc gia.
table_dest <- as.data.frame(table(flight_data_no_outlier$dest))
colnames(table_dest) <- c("Mã sân bay đến", "Số chuyến bay")
table_dest <- table_dest[order(-table_dest$'Số chuyến bay'), ]
kable(head(table_dest, 10),
caption = "**Tần suất 10 sân bay đến có số chuyến bay cao nhất**", row.names = FALSE, align = "lc")
| Mã sân bay đến | Số chuyến bay |
|---|---|
| ATL | 49266 |
| DFW | 44167 |
| DEN | 42086 |
| ORD | 36555 |
| CLT | 29496 |
| PHX | 29070 |
| LAX | 27961 |
| LAS | 27922 |
| MCO | 26827 |
| LGA | 23565 |
Giải thích:
(1-3) Tạo bảng tần suất table_dest cho
biến dest trong flight_data_no_outlier và sắp
xếp giảm dần.
(4) Hiển thị bảng tần số của 10 hãng bay có tần suất bay cao nhất
Nhận xét: Sân bay ATL (Atlanta) dẫn đầu về số chuyến bay đến, thể hiện vai trò trung tâm trung chuyển quốc gia. Tổng thể, tần suất cao tập trung ở các sân bay lớn và đầu mối giao thông trọng điểm của Hoa Kỳ.
Giải thích chung: (1) Trả về số lượng giá trị ngoại lai trong các biến của dữ liệu.
length(boxplot.stats(flight_data_no_outlier$air_time)$out)
## [1] 48345
Nhận xét: Biến air_time có 48345 giá
trị ngoại lai, chủ yếu ở các chuyến bay quá dài hoặc quá ngắn so với mặt
bằng chung. Các giá trị này phản ánh sự khác biệt tự nhiên giữa tuyến
nội bang và xuyên vùng, nên được giữ lại để phân tích riêng, nhằm thể
hiện đúng đặc trưng mạng lưới hàng không.
length(boxplot.stats(flight_data_no_outlier$schedule_diff)$out)
## [1] 38620
Nhận xét: Biến schedule_diff có 38.620
giá trị ngoại lai, tập trung ở các chuyến bay chậm hoặc nhanh bất thường
so với thời gian dự kiến. Những giá trị này phản ánh biến động thực tế
trong vận hành, nên được giữ lại để phân tích riêng nhằm đánh giá chính
xác hơn độ ổn định lịch trình bay.
length(boxplot.stats(flight_data_no_outlier$distance)$out)
## [1] 57852
Nhận xét: Biến distance có 57.852 giá
trị ngoại lai, chủ yếu thuộc các chuyến bay rất ngắn hoặc rất dài so với
đa số tuyến khác. Các ngoại lệ này thể hiện sự đa dạng về phạm vi khai
thác của mạng lưới hàng không và nên được giữ lại để phân tích đặc trưng
tuyến bay.
length(boxplot.stats(flight_data_no_outlier$dep_delay)$out)
## [1] 126636
Nhận xét: Biến dep_delay có 126.636 giá
trị ngoại lai, chủ yếu ở các chuyến bay bị trễ quá mức hoặc khởi hành
sớm hiếm gặp. Các giá trị này phản ánh dao động thực tế trong thời gian
cất cánh, nên cần giữ lại để phân tích riêng nhằm đánh giá rõ hơn hiệu
suất và tính ổn định khai thác.
carrier_delay <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(avg_depdelay = mean(dep_delay), avg_arrdelay = mean(arr_delay)) %>%
arrange(desc(avg_depdelay))
print(carrier_delay)
## # A tibble: 15 × 3
## op_unique_carrier avg_depdelay avg_arrdelay
## <fct> <dbl> <dbl>
## 1 AA 16.7 12.2
## 2 B6 16.6 10.2
## 3 OO 14.5 9.31
## 4 F9 14.2 9.21
## 5 NK 13.4 7.43
## 6 G4 12.6 7.54
## 7 UA 11.6 4.59
## 8 OH 11.3 6.43
## 9 9E 10.1 2.06
## 10 WN 10.1 3.70
## 11 AS 9.42 4.22
## 12 HA 9.13 9.12
## 13 MQ 9.05 5.51
## 14 DL 8.01 0.219
## 15 YX 2.34 -5.47
Giải thích:
(2) Nhóm dữ liệu theo biến
op_unique_carrier để gom các chuyến bay theo từng hãng hàng
không.
(3) Tính trung bình độ trễ khi khởi hành
(avg_depdelay) và khi đến (avg_arrdelay) của
từng hãng bằng hàm mean().
(4) Sắp xếp các hãng theo thứ tự giảm dần của giá
trị avg_depdelay.
(5) In bảng carrier_delay
Nhận xét: Hãng AA có thời gian trễ trung bình cao nhất với 16,66 phút khi khởi hành và 12,19 phút khi hạ cánh, cho thấy mức độ chậm trễ lớn nhất trong các hãng. Ngược lại, hãng YX có độ trễ trung bình thấp nhất, chỉ 2,34 phút khi khởi hành và thậm chí đến sớm 5,47 phút khi hạ cánh.
avg_airtime <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(avg_air_time = mean(air_time, na.rm = TRUE)) %>%
arrange(desc(avg_air_time))
head(avg_airtime,15)
Giải thích:
(2) gom các chuyến bay theo từng hãng hàng không.
(3) Tính thời gian bay trung bình
(avg_air_time) của từng hãng.
(4) Sắp xếp các hãng theo thứ tự giảm dần của
avg_air_time.
(5) Hiển thị 15 hãng hàng không có thời gian bay trung bình lớn nhất.
Nhận xét: Hãng AS có thời gian bay trung bình cao nhất (≈179,8 phút), cho thấy hãng này chủ yếu khai thác các chặng bay dài. Hãng WN có thời gian bay trung bình ngắn nhất (≈103,7 phút), phản ánh tập trung vào các chuyến bay nội địa ngắn.
schedule_diff_by_carrier <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(avg_schedule_diff = mean(schedule_diff, na.rm = TRUE)) %>%
arrange(desc(avg_schedule_diff))
kable(schedule_diff_by_carrier, col.names = c("Hãng hàng không", "Chênh lệch trung bình (phút)"),
caption = "**Độ chênh lệch giữa thời gian thực tế và lịch trình theo từng hãng bay**")
| Hãng hàng không | Chênh lệch trung bình (phút) |
|---|---|
| HA | -0.013254 |
| MQ | -3.547582 |
| AA | -4.472685 |
| OH | -4.859020 |
| F9 | -5.023308 |
| G4 | -5.066773 |
| OO | -5.197220 |
| AS | -5.206445 |
| NK | -5.949472 |
| WN | -6.357083 |
| B6 | -6.433756 |
| UA | -7.037611 |
| DL | -7.795624 |
| YX | -7.833027 |
| 9E | -8.061733 |
Giải thích:
(2) Gom các chuyến bay theo từng hãng hàng không.
(3) Tính chênh lệch thời gian trung bình
(avg_schedule_diff) giữa thực tế và lịch trình cho từng
hãng.
(4) Sắp xếp các hãng theo thứ tự giảm dần của
avg_schedule_diff.
(5) Hiển thị bảng kết quả.
Nhận xét:
Độ chênh lệch giữa thời gian bay thực tế và lịch trình cho thấy phần lớn các hãng hoàn thành chuyến bay sớm hơn kế hoạch (giá trị âm).
HA có độ chênh gần như bằng 0 (-0.01 phút), thể hiện mức độ đúng giờ
rất cao.
Các hãng như 9E (-8.06 phút), YX (-7.83 phút) và DL (-7.80 phút) thường
về đích sớm hơn lịch trình khoảng 7–8 phút, cho thấy khả năng tối ưu hóa
lịch bay.
Trung bình toàn ngành có xu hướng bay nhanh hơn dự kiến từ 4–6 phút, phản ánh việc các hãng thường dự trù dư thời gian trong kế hoạch để giảm nguy cơ trễ giờ danh nghĩa.
schedule_diff_by_day <- flight_data_no_outlier %>%
group_by(day_of_week) %>%
summarise(avg_schedule_diff = mean(schedule_diff, na.rm = TRUE)) %>%
mutate(day_of_week = factor(day_of_week,
levels = 1:7,
labels = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday")))
kable(schedule_diff_by_day,
col.names = c("Ngày trong tuần", "Độ chênh trung bình (phút)"),
caption = "**Độ chênh lệch giữa thời gian thực tế và lịch trình theo từng ngày trong tuần**")
| Ngày trong tuần | Độ chênh trung bình (phút) |
|---|---|
| Monday | -5.843880 |
| Tuesday | -5.856902 |
| Wednesday | -6.860943 |
| Thursday | -6.657325 |
| Friday | -5.340314 |
| Saturday | -5.598832 |
| Sunday | -5.936731 |
Giải thích:
(2): Gom nhóm các chuyến bay theo ngày trong tuần
(day_of_week).
(3) Tính chênh lệch thời gian trung bình giữa thực tế và lịch trình của từng ngày.
(4) Gán nhãn cho các giá trị 1–7 tương ứng với các ngày trong tuần.
(6): Hiển thị bảng kết quả với hai cột — ngày trong tuần và độ chênh lệch trung bình.
Nhận xét:
Tất cả các ngày trong tuần đều có giá trị âm, cho thấy chuyến bay thường đến sớm hơn lịch trình. Mức sớm nhất là thứ Tư (-6.86 phút) và thứ Năm (-6.66 phút), thể hiện hiệu suất bay tốt hơn giữa tuần. Thứ Sáu (-5.34 phút) có độ chênh nhỏ nhất, nghĩa là giờ bay gần khớp lịch trình hơn. Nhìn chung, các chuyến bay hoạt động ổn định, không có ngày nào trễ đáng kể.
total_minutes_by_day <- flight_data_no_outlier %>%
group_by(day_of_week) %>%
summarise(total_air_time = sum(air_time, na.rm = TRUE)) %>%
mutate(day_of_week = factor(day_of_week,
levels = 1:7,
labels = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday"))) %>%
arrange(day_of_week)
kable(total_minutes_by_day,
col.names = c("Ngày trong tuần", "Tổng thời gian bay (phút)"),
caption = "**Tổng thời gian bay của các chuyến bay theo từng ngày trong tuần**")
| Ngày trong tuần | Tổng thời gian bay (phút) |
|---|---|
| Monday | 18556473 |
| Tuesday | 16864870 |
| Wednesday | 17466111 |
| Thursday | 16995779 |
| Friday | 16786833 |
| Saturday | 14752552 |
| Sunday | 16656921 |
Giải thích
(2): Gom nhóm dữ liệu theo ngày trong tuần
(day_of_week).
(3) Tính tổng thời gian bay (air_time)
của từng ngày.
(4) Đặt nhãn tên ngày trong tuần tương ứng với các giá trị 1–7.
(6) Sắp xếp lại các ngày theo thứ tự trong tuần.
(7) Hiển thị bảng kết quả gồm ngày trong tuần và tổng thời gian bay.
Nhận xét:
Tổng thời gian bay cao nhất vào thứ Hai (18.556.473 phút), cho thấy hoạt động bay đầu tuần sôi động hơn.
Thứ Bảy (14.752.552 phút) có tổng thời gian bay thấp nhất, phản ánh nhu cầu di chuyển giảm vào cuối tuần.
Các ngày giữa tuần (Tuesday–Thursday) duy trì mức tương đối ổn định quanh 16–17 triệu phút.
Nhìn chung, lưu lượng bay giảm dần từ đầu tuần đến cuối tuần, thể hiện quy luật hoạt động theo chu kỳ tuần.
Biến distance_level được tạo ra nhằm phân loại các chuyến bay theo độ dài quãng đường, giúp đánh giá sự khác biệt về đặc điểm hoạt động giữa các nhóm đường bay ngắn, trung bình và dài.
Việc phân chia được thực hiện tự động dựa trên phân vị của biến distance, đảm bảo phản ánh đúng phân bố thực tế trong bộ dữ liệu.
flight_data_no_outlier <- flight_data_no_outlier %>%
mutate(distance_level = cut(distance,
breaks = quantile(distance, probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
include.lowest = TRUE,
labels = c("Ngắn", "Trung bình", "Dài")))
table(flight_data_no_outlier$distance_level)
##
## Ngắn Trung bình Dài
## 336471 337152 335667
Giải thích:
(2-4) Tạo biến mới distance_level bằng
cách chia biến distance thành 3 nhóm theo các tứ phân vị
(1/3 và 2/3) và gán nhãn cho 3 mức tương ứng là “Ngắn”, “Trung bình”, và
“Dài”
(5) Đếm số chuyến bay thuộc từng nhóm khoảng cách.
Nhận xét: Phân loại quãng đường giúp nhận diện cơ cấu hoạt động bay của các hãng, ví dụ nếu số chuyến ngắn và trung bình chiếm tỷ trọng lớn, điều đó phản ánh mạng lưới bay nội địa hoặc khu vực chiếm ưu thế; ngược lại, quãng đường dài thể hiện hoạt động bay quốc tế hoặc đường bay xuyên vùng có tần suất thấp hơn.
carrier_delay_long <- carrier_delay %>%
pivot_longer(c(avg_depdelay, avg_arrdelay),
names_to = "delay_type", values_to = "delay_value")
ggplot(carrier_delay_long, aes(x = op_unique_carrier, y = delay_value, fill = delay_type)) +
geom_col(position = "dodge", color = "black") +
geom_text(aes(label = round(delay_value, 1)),
position = position_dodge(width = 0.9), vjust = -0.5, size = 3) +
scale_fill_manual(
values = c("avg_depdelay" = "#FFB7C5", "avg_arrdelay" = "#A7D8F0"),
labels = c("avg_depdelay" = "Trễ khởi hành", "avg_arrdelay" = "Trễ khi đến"))+
geom_hline(yintercept = mean(carrier_delay_long$delay_value, na.rm = TRUE),
linetype = "dashed", color = "red") +
labs(title = "So sánh độ trễ trung bình giữa các hãng hàng không",
x = "Hãng hàng không", y = "Độ trễ (phút)", fill = "Loại trễ") +
theme_minimal()
Giải thích:
(1–2): Dùng pivot_longer() chuyển dữ
liệu từ dạng rộng sang dạng dài, gom hai cột avg_depdelay
và avg_arrdelay thành một cột “delay_value”.
(3): Khởi tạo biểu đồ với trục x là hãng bay, trục y là độ trễ, màu theo loại trễ.
(4): Vẽ cột so sánh (geom_col) và thêm
nhãn số độ trễ trên mỗi cột.
(5–6): Gán màu và nhãn tiếng Việt cho hai loại trễ.
(7–8): Vẽ đường trung bình chung (nét đứt, màu đỏ) giúp so sánh dễ hơn.
(9–10): Thêm tiêu đề, nhãn trục, chú giải và theme tối giản cho biểu đồ rõ ràng, đẹp mắt.
Nhận xét Kết quả cho thấy thời gian chậm khởi hành và chậm đến của các hãng hàng không nhìn chung dao động quanh mức trung bình từ 8 đến 10 phút. Xét tổng thể, độ trễ khởi hành có xu hướng cao hơn độ trễ khi đến, cho thấy sự chậm trễ phần lớn bắt nguồn từ khâu khởi hành thay vì trong quá trình bay.
delay_weekend_month <- flight_data_no_outlier %>%
filter(month %in% 1:2) %>%
group_by(month, weekend_flight) %>%
summarise(
`Trễ khởi hành` = mean(dep_delay, na.rm = TRUE),
`Trễ khi đến` = mean(arr_delay, na.rm = TRUE),
.groups = "drop") %>%
pivot_longer(cols = c(`Trễ khởi hành`, `Trễ khi đến`),
names_to = "Loại trễ", values_to = "Giá trị trễ") %>%
mutate(weekend_flight = factor(weekend_flight, labels = c("Ngày thường", "Cuối tuần")))
ggplot(delay_weekend_month, aes(x = weekend_flight, y = `Giá trị trễ`, fill = `Loại trễ`)) +
geom_col(position = "dodge", color = "black") +
geom_text(aes(label = round(`Giá trị trễ`, 1)),
position = position_dodge(1), vjust = -0.3, size = 3.0) +
geom_hline(yintercept = mean(delay_weekend_month$`Giá trị trễ`),
color = "darkgreen", linetype = "dashed") +
facet_wrap(~ month, labeller = labeller(month = c(`1`="Tháng 1", `2`="Tháng 2"))) +
scale_fill_manual(values = c("#F8AFA6", "#CBB2FE")) +
labs(x = "Loại chuyến bay", y = "Độ trễ trung bình (phút)",
title = "So sánh độ trễ giữa ngày thường và cuối tuần (Tháng 1 & 2)",
)+
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", hjust = 0.5))
Giải thích:
(1–3) Lọc dữ liệu tháng 1–2 và nhóm theo tháng và loại chuyến bay.
(4–5) Tính trung bình trễ khởi hành và trễ đến.
(6–9) Chuyển dữ liệu sang dạng dài (2 loại trễ) và Đổi nhãn: 0 = Ngày thường, 1 = Cuối tuần.
(10–17) Vẽ biểu đồ cột song song, thêm nhãn số, đường trung bình, tách theo tháng, tô màu riêng và đặt tiêu đề, legend dưới.
Nhận xét:
Trong tháng 1, độ trễ trung bình khi khởi hành dao động quanh 15–16 phút, cao hơn đáng kể so với tháng 2, chỉ khoảng 6–10 phút, cho thấy tình hình khai thác được cải thiện rõ rệt.
Cả hai tháng đều ghi nhận cuối tuần (Weekend) có mức trễ cao hơn ngày thường (Weekday), đặc biệt trong tháng 2, trễ khởi hành cuối tuần đạt 10.1 phút so với 6.3 phút ngày thường.
carrier_delay <- flight_data_no_outlier %>%
group_by(month, weekend_flight, day_period) %>%
summarise(`Trễ cất cánh` = mean(dep_delay, na.rm = TRUE),
`Trễ hạ cánh` = mean(arr_delay, na.rm = TRUE),
.groups = "drop") %>%
pivot_longer(cols = c(`Trễ cất cánh`, `Trễ hạ cánh`),
names_to = "Loại trễ", values_to = "Độ trễ") %>%
mutate(day_period = factor(day_period,
levels = c("Morning", "Afternoon", "Evening", "Night")))
ggplot(carrier_delay, aes(x = day_period, y = `Độ trễ`, fill = `Loại trễ`)) +
geom_col(position = "dodge", color = "black") +
geom_text(aes(label = round(`Độ trễ`, 1)),
position = position_dodge(0.9), vjust = -0.4, size = 3.2, fontface = "bold") +
geom_hline(yintercept = mean(carrier_delay$`Độ trễ`, na.rm = TRUE),
color = "darkgreen", linetype = "dashed") +
facet_grid(month ~ weekend_flight,
labeller = labeller(month = c(`1`="Tháng 1", `2`="Tháng 2"),
weekend_flight = c(`0`="Ngày thường", `1`="Cuối tuần"))) +
scale_fill_manual(values = c("#E8A0BF", "#A8D1D1")) +
coord_cartesian(ylim = range(carrier_delay$`Độ trễ`, na.rm = TRUE) + c(-10, 5)) +
labs(x = "Khung giờ", y = "Độ trễ trung bình (phút)",
title = "Trung bình độ trễ theo khung giờ, tháng và loại ngày",
caption = "Nguồn: flight_data_no_outlier") +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
axis.text.x = element_text(face = "bold"),
legend.position = "bottom")
Giải thích:
(1–2) Nhóm theo tháng, loại ngày và khung giờ.
(3–4) Tính trung bình trễ cất cánh và hạ cánh.
(5–6) Chuyển dữ liệu sang dạng dài để vẽ 2 loại trễ.
(7-8) Sắp xếp thứ tự khung giờ: Morning, Afternoon, Evening, Night.
(9–19) Vẽ biểu đồ cột song song, thêm nhãn số, đường trung bình, chia ô theo tháng và loại ngày, tô màu riêng, đặt giới hạn trục, thêm tiêu đề và legend dưới.
Nhận xét:
Kết quả cho thấy thời gian trễ trung bình có sự khác biệt rõ rệt giữa các thời điểm trong ngày và giữa hai tháng quan sát.
Mức trễ cao nhất xuất hiện vào buổi tối (Night), đặc biệt trong tháng 1, khi cả thời gian trễ khởi hành và trễ đến đều vượt trên 30 phút, phản ánh tình trạng ùn tắc hoặc ảnh hưởng từ các chuyến bay dồn cuối ngày.
Ngược lại, buổi sáng (Morning) ghi nhận mức trễ thấp nhất, thậm chí âm ở một số trường hợp, cho thấy khả năng khởi hành sớm hơn kế hoạch.
table_time <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(`Tổng thời gian bay` = sum(air_time, na.rm = TRUE), .groups = "drop") %>%
mutate(Tỷ_lệ = `Tổng thời gian bay` / sum(`Tổng thời gian bay`) * 100) %>%
arrange(desc(Tỷ_lệ))
ggplot(table_time, aes(x = reorder(op_unique_carrier, Tỷ_lệ),
y = Tỷ_lệ, fill = op_unique_carrier)) +
geom_col(width = 0.7, color = "white") +
geom_text(aes(label = paste0(round(Tỷ_lệ, 1), "%")),
hjust = -0.1, size = 4, fontface = "bold") +
coord_flip() +
scale_fill_manual(values = c(brewer.pal(12, "Set3"), "#F8766D", "#7CAE00", "#00BFC4")) +
labs(title = "Tỷ trọng thời gian bay của các hãng hàng không",
x = "Hãng hàng không", y = "Tỷ lệ (%)") +
expand_limits(y = max(table_time$Tỷ_lệ) + 2) +
theme(plot.title = element_text(hjust = 0.5, face = "bold"),
axis.text.y = element_text(face = "bold"),
legend.position = "none")
Giải thích:
(1–2) Nhóm dữ liệu theo hãng hàng không.
(3) Tính tổng thời gian bay của từng hãng (bỏ giá trị NA).
(4) Tính tỷ lệ phần trăm thời gian bay so với tổng toàn bộ.
(5) Sắp xếp giảm dần theo tỷ lệ.
(6–12) Vẽ biểu đồ cột ngang thể hiện tỷ trọng, thêm nhãn %, chỉnh màu, tiêu đề, bỏ legend.
Nhận xét: Hãng WN chiếm tỷ trọng cao nhất, 18.6 phần trăm, phản ánh quy mô hoạt động lớn và tần suất khai thác dày đặc. Nhìn chung, biểu đồ thể hiện sự tập trung hoạt động mạnh ở nhóm hãng hàng không lớn, chiếm phần lớn tổng thời gian bay toàn ngành.
schedule_diff_by_carrier <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(avg_schedule_diff = mean(schedule_diff, na.rm = TRUE)) %>%
arrange(avg_schedule_diff)
ggplot(schedule_diff_by_carrier, aes(x = reorder(op_unique_carrier, avg_schedule_diff),
y = avg_schedule_diff, fill = avg_schedule_diff)) +
geom_bar(stat = "identity", color = "black", width = 0.7) +
coord_flip() + # chuyển sang cột ngang
geom_text(aes(label = round(avg_schedule_diff, 1)),
hjust = ifelse(schedule_diff_by_carrier$avg_schedule_diff >= 0, -0.1, 1.1),
color = "black", fontface = "bold", size = 3.5) +
scale_fill_gradient(low = "#A8D1D1", high = "#E8A0BF") +
labs(
title = "Độ chênh lệch lịch trình theo từng hãng bay",
x = "Hãng hàng không",
y = "Chênh lệch lịch trình (phút)",
caption = "Source: flight_data_no_outlier"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text.y = element_text(face = "bold"),
plot.margin = margin(10, 15, 10, 10)
) +
expand_limits(y = c(min(schedule_diff_by_carrier$avg_schedule_diff) - 5, max(schedule_diff_by_carrier$avg_schedule_diff) + 5))
Giải thích:
(1–2) Nhóm dữ liệu theo hãng hàng không.
(3) Tính trung bình chênh lệch giữa thời gian thực
tế và lịch trình (schedule_diff).
(4) Sắp xếp theo giá trị trung bình chênh lệch.
(5–15) Vẽ biểu đồ cột ngang, tô màu theo mức chênh lệch, thêm nhãn số, đặt tiêu đề và định dạng trục, căn giữa, mở rộng biên trục y.
Nhận xét:
table_time <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(total_air_time = sum(air_time, na.rm = TRUE)) %>%
mutate(percentage = total_air_time / sum(total_air_time) * 100) %>%
arrange(desc(percentage)) %>%
mutate(label = paste0(op_unique_carrier, " (", round(percentage, 1), "%)"))
ggplot(table_time, aes(x = 2, y = percentage, fill = op_unique_carrier)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar(theta = "y", start = 0) +
xlim(0.5, 2.5) +
scale_fill_manual(values = c(
brewer.pal(12, "Set3"),
"#F8766D", "#7CAE00", "#00BFC4"
)) +
geom_text(aes(label = ifelse(percentage > 3, paste0(round(percentage, 1), "%"), "")),
position = position_stack(vjust = 0.5),
size = 4, fontface = "bold", color = "black") +
labs(
title = "Tỷ trọng thơi gian bay của các hãng hàng không",
fill = "Hãng hàng không"
) +
theme_void(base_size = 14) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
legend.title = element_text(face = "bold"),
legend.text = element_text(size = 12)
)
Giải thích:
(1–2) Nhóm theo hãng hàng không.
(3) Tính tổng thời gian bay của từng hãng (bỏ NA).
(4-5) Tính tỷ lệ phần trăm thời gian bay trên tổng và sắp xếp giảm dần
(6) Tạo nhãn hiển thị tên hãng kèm phần trăm.
(7–14) Vẽ biểu đồ tròn bằng
coord_polar(), tô màu từng hãng, hiển thị % trong phần có
tỷ lệ >3%, thêm tiêu đề và định dạng legend.
Nhận xét: Biểu đồ hình vành khuyên thể hiện tỷ trọng thời gian bay của các hãng hàng không trong toàn bộ dữ liệu. Hãng WN chiếm tỷ lệ cao nhất (18.6 phần trăm), khẳng định vị thế hãng có tổng thời gian khai thác lớn nhất. Nhìn chung, biểu đồ thể hiện sự phân hóa mạnh mẽ giữa nhóm hãng lớn và nhỏ, phản ánh mức độ hoạt động và phạm vi khai thác khác biệt rõ rệt trong ngành hàng không.
schedule_diff_by_day <- flight_data_no_outlier %>%
group_by(day_of_week) %>%
summarise(avg_schedule_diff = mean(schedule_diff, na.rm = TRUE)) %>%
mutate(day_of_week = factor(day_of_week,
levels = 1:7,
labels = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday")))
ggplot(schedule_diff_by_day, aes(x = day_of_week, y = avg_schedule_diff, fill = day_of_week)) +
geom_bar(stat = "identity", color = "black", width = 0.7) +
geom_text(aes(label = round(avg_schedule_diff, 1)),
hjust = ifelse(schedule_diff_by_day$avg_schedule_diff >= 0, -0.2, 1.2),
color = "black", fontface = "bold", size = 3.5) +
scale_fill_brewer(palette = "Set3") +
labs(title = "Độ chênh lệch lịch trình theo ngày trong tuần",
x = "Ngày trong tuần", y = "Độ chênh trung bình (phút)",
caption = "Source: flight_data_no_outlier") +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text.y = element_text(face = "bold"),
legend.position = "none",
panel.grid.minor = element_blank()
) +
expand_limits(y = c(min(schedule_diff_by_day$avg_schedule_diff) - 2,
max(schedule_diff_by_day$avg_schedule_diff) + 2)) +
coord_flip()
Giải thích:
(1–2) Nhóm dữ liệu theo ngày trong tuần.
(3) Tính trung bình độ chênh lệch giữa thời gian
thực tế và lịch trình (schedule_diff).
(4–5) Đặt tên thứ trong tuần từ Monday → Sunday.
(6–15) Vẽ biểu đồ cột ngang, tô màu theo ngày, thêm nhãn số, căn chỉnh trục, mở rộng giới hạn, thêm tiêu đề và ẩn legend.
Nhận xét:
Biểu đồ cho thấy mức chênh lệch lịch trình dao động quanh -5 đến -7 phút ở tất cả các ngày trong tuần. Cụ thể, thứ Tư (-6.9 phút) và thứ Năm (-6.7 phút) có độ trễ âm lớn nhất, cho thấy các chuyến bay thường đến sớm hơn lịch trình trong hai ngày này. Trong khi đó, thứ Sáu (-5.3 phút) có chênh lệch nhỏ nhất, phản ánh lịch trình bay ổn định hơn.
total_minutes_by_day <- flight_data_no_outlier %>%
group_by(day_of_week) %>%
summarise(`Tổng thời gian bay` = sum(air_time, na.rm = TRUE), .groups = "drop") %>%
mutate(day_of_week = factor(day_of_week, levels = 1:7,
labels = c("Mon","Tue","Wed","Thu","Fri","Sat","Sun")),
Tỷ_lệ = `Tổng thời gian bay` / sum(`Tổng thời gian bay`) * 100)
ggplot(total_minutes_by_day, aes(x = "", y = Tỷ_lệ, fill = day_of_week)) +
geom_col(color = "white") +
coord_polar(theta = "y") +
geom_text(aes(label = paste0(round(Tỷ_lệ, 1), "%")),
position = position_stack(vjust = 0.5),
size = 4, fontface = "bold") +
scale_fill_brewer(palette = "Set3", name = "Ngày trong tuần") +
labs(title = "Tỷ trọng tổng thời gian bay theo ngày trong tuần",
subtitle = "Đơn vị: phút",
caption = "Nguồn: flight_data_no_outlier") +
theme_void(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
legend.position = "right",
legend.title = element_text(face = "bold"))
Giải thích:
(1–2) Nhóm dữ liệu theo ngày trong tuần.
(3) Tính tổng thời gian bay (bỏ giá trị thiếu).
(4–5) Đặt tên thứ (Mon–Sun) và tính tỷ lệ phần trăm tổng thời gian bay.
(6–17) Vẽ biểu đồ tròn thể hiện tỷ trọng thời gian
bay theo ngày, thêm nhãn %, màu Set3, tiêu đề và chú thích
rõ ràng.
Nhận xét: Tổng thời gian bay được phân bố tương đối đồng đều giữa các ngày trong tuần, dao động từ 12.5 đến 15.7 phần trăm.
flight_data_no_outlier <- flight_data_no_outlier %>%
mutate(dep_hour = floor(crs_dep_time / 100))
delay_by_hour <- flight_data_no_outlier %>%
group_by(dep_hour) %>%
summarise(
avg_depdelay = mean(dep_delay, na.rm = TRUE),
avg_arrdelay = mean(arr_delay, na.rm = TRUE)
) %>%
tidyr::pivot_longer(cols = c(avg_depdelay, avg_arrdelay),
names_to = "delay_type", values_to = "delay_value")
ggplot(delay_by_hour, aes(x = dep_hour, y = delay_value, color = delay_type)) +
geom_line(size = 1.2) +
geom_point(size = 2.8) +
scale_color_manual(values = c("#E8A0BF", "#A8D1D1"),
labels = c("Departure", "Arrival")) +
labs(title = "Độ trễ trung bình theo giờ khởi hành trong ngày",
x = "Giờ khởi hành", y = "Độ trễ trung bình (phút)",
color = "Loại độ trễ") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Giải thích:
(2) Tạo biến dep_hour từ thời gian khởi
hành dự kiến (crs_dep_time) làm tròn xuống theo giờ.
(3–6) Nhóm theo giờ khởi hành và tính trung bình độ trễ khởi hành và độ trễ khi đến.
(7-8) Dùng pivot_longer() để gộp hai
loại trễ thành một cột.
(9–14) Vẽ biểu đồ đường so sánh độ trễ trung bình theo giờ trong ngày, tô màu theo loại trễ, đặt tiêu đề và căn giữa.
Nhận xét: Độ trễ trung bình biến thiên rõ rệt theo giờ khởi hành. Cụ thể, cả hai loại trễ đều tăng mạnh vào khoảng 4–5 giờ sáng, đạt đỉnh lần lượt ở 15.2 phút (departure) và 16.7 phút (arrival) — nhiều khả năng do tắc nghẽn giờ đầu ngày. Từ 6 giờ đến 10 giờ sáng, độ trễ giảm xuống mức thấp nhất, sau đó tăng dần trở lại từ 12–20 giờ.
library(maps)
us_map <- map_data("state")
flight_state <- flight_data_no_outlier %>%
group_by(origin_state_nm) %>%
summarise(total_flights = n()) %>%
mutate(region = tolower(origin_state_nm))
map_merged <- left_join(us_map, flight_state, by = "region")
ggplot(map_merged, aes(long, lat, group = group, fill = total_flights)) +
geom_polygon(color = "white", size = 0.2) +
coord_fixed(1.3) +
scale_fill_gradient(low = "#CFE2F3", high = "#08306B", name = "Số chuyến bay") +
labs(title = "Phân bố số lượng chuyến bay theo bang khởi hành",
subtitle = "Tổng số chuyến bay trong 2 tháng đầu năm 2024",
caption = "Source: flight_data_no_outlier",
x = "", y = "") +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5, color = "gray30"),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank()
)
Giải thích:
(1) Nạp gói maps để lấy dữ liệu bản đồ
các bang Hoa Kỳ.
(2) Tạo dữ liệu us_map chứa toạ độ biên
giới các bang.
(3–5) Nhóm theo bang khởi hành, đếm số chuyến bay, đổi tên bang về chữ thường để khớp với dữ liệu bản đồ.
(7) Gộp dữ liệu bản đồ với dữ liệu số chuyến bay theo bang.
(8–14) Vẽ bản đồ tô màu theo số chuyến bay, dùng màu xanh đậm cho giá trị cao, thêm tiêu đề, phụ đề, và loại bỏ trục.
Nhận xét: Phân bố số chuyến bay giữa các bang không đồng đều, tập trung chủ yếu ở các bang ven biển và khu vực có trung tâm hàng không lớn. Các bang Texas, California và Florida ghi nhận số chuyến bay cao nhất (trên 90.000 chuyến), phản ánh vai trò đầu mối giao thông quốc gia. Ngược lại, các bang miền Trung và miền Bắc như Montana, Wyoming có lượng chuyến bay thấp nhất (dưới 20.000 chuyến). Xu hướng này cho thấy hoạt động hàng không tập trung mạnh tại các khu vực có dân cư và kinh tế phát triển.
ggplot(flight_data_no_outlier, aes(x = distance, y = arr_delay)) +
geom_point(alpha = 0.4, color = "#00A6A6", size = 2) +
geom_smooth(method = "lm", se = TRUE, color = "#D81159", linewidth = 1.2) +
labs(title = "Mối quan hệ giữa khoảng cách bay và độ trễ khi đến",
subtitle = "Quan sát xu hướng chuyến bay dài hơn có xu hướng trễ hơn không",
x = "Khoảng cách bay (dặm)", y = "Độ trễ khi đến (phút)", caption = "Nguồn: flight_data_no_outlier") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5, color = "gray30"))
Giải thích:
(1) Ánh xạ trục x = khoảng cách bay, y = độ trễ khi đến.
(2) Vẽ điểm phân tán, màu xanh, độ trong suốt 0.4.
(3) Thêm đường hồi quy tuyến tính
(geom_smooth(method="lm")) để thể hiện xu
hướng.
(4–6) Đặt tiêu đề, phụ đề, nhãn trục và chú thích nguồn dữ liệu.
(7–9) Chọn giao diện tối giản, căn giữa tiêu đề và phụ đề.
Nhận xét: Phần lớn các chuyến bay có độ trễ nhỏ, tập trung gần trục hoành. Một số điểm ngoại lệ có độ trễ cực cao (trên 1000 phút) nhưng phân bố rải rác, không tập trung theo khoảng cách cụ thể. Điều này gợi ý rằng độ trễ khi đến không phụ thuộc đáng kể vào độ dài chuyến bay, mà có thể chịu ảnh hưởng bởi yếu tố khác như thời tiết, hãng hàng không hoặc tình trạng sân bay.
flight_count_by_carrier <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(so_chuyen_bay = n()) %>%
mutate(ty_trong = so_chuyen_bay / sum(so_chuyen_bay)) %>%
arrange(desc(ty_trong))
ggplot(flight_count_by_carrier, aes(x = reorder(op_unique_carrier, -ty_trong), y = ty_trong, fill = op_unique_carrier)) +
geom_col(show.legend = FALSE) +
scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
labs(title = "Tỷ trọng chuyến bay theo hãng hàng không",
x = "Hãng hàng không", y = "Tỷ trọng (%)") +
theme_minimal()
Giải thích:
(1–3) Nhóm dữ liệu theo hãng hàng không và đếm số chuyến bay.
(4) Tính tỷ trọng (%) số chuyến bay của từng hãng.
(5) Sắp xếp giảm dần theo tỷ trọng.
(6–9) Vẽ biểu đồ cột thể hiện tỷ trọng chuyến bay, hiển thị trục y dạng phần trăm, thêm tiêu đề và bố cục tối giản.
Nhận xét: Biểu đồ cho thấy sự chênh lệch rõ rệt về thị phần khai thác chuyến bay giữa các hãng. Trong đó hãng WN (Southwest Airlines) chiếm tỷ trọng cao nhất, khoảng trên 20 phần trăm trên tổng số chuyến bay, khẳng định vị thế dẫn đầu trong khai thác nội địa.
speed_trend <- flight_data_no_outlier %>%
group_by(day_period, weekend_flight) %>%
summarise(`Vận tốc TB` = mean(speed_mph, na.rm = TRUE), .groups = "drop") %>%
mutate(weekend_flight = factor(weekend_flight, labels = c("Weekday", "Weekend")),
day_period = factor(day_period, levels = c("Morning", "Afternoon", "Evening", "Night")))
ggplot(speed_trend, aes(x = day_period, y = `Vận tốc TB`, color = weekend_flight, group = weekend_flight)) +
geom_line(linewidth = 1.1) +
geom_point(size = 3.8, shape = 21, fill = "white", stroke = 1) +
geom_text(aes(label = round(`Vận tốc TB`, 1),
vjust = ifelse(weekend_flight == "Weekday", 1.6, -0.8),
color = weekend_flight),
fontface = "bold", size = 3.8, show.legend = FALSE) +
scale_color_manual(values = c("#0073C2FF", "#EFC000FF")) +
coord_cartesian(ylim = range(speed_trend$`Vận tốc TB`) + c(-5, 5)) +
labs(title = "Xu hướng vận tốc trung bình theo thời điểm trong ngày",
subtitle = "So sánh giữa chuyến bay ngày thường và cuối tuần",
x = "Thời điểm trong ngày", y = "Vận tốc trung bình (dặm/giờ)",
caption = "Nguồn: flight_data_no_outlier") +
theme(plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
plot.subtitle = element_text(size = 12, color = "gray40", hjust = 0.5),
axis.text.x = element_text(face = "bold"),
legend.position = "bottom", legend.title = element_blank(),
panel.grid.minor = element_blank())
Giải thích:
(1–2) Nhóm dữ liệu theo khung giờ và loại ngày bay.
(3) Tính vận tốc trung bình (mph) của từng nhóm, bỏ NA.
(4) Gán nhãn: Weekday và Weekend, sắp xếp thứ tự khung giờ.
(6–13): Vẽ biểu đồ đường so sánh vận tốc trung bình giữa ngày thường và cuối tuần; thêm điểm đánh dấu nhãn số và tô màu riêng cho từng nhóm.
(14–23): Giới hạn trục y để biểu đồ cân đối, thêm tiêu đề – phụ đề – nhãn trục, chỉnh font đậm và căn giữa tiêu 658 đề; legend đặt ở dưới giúp bố cục hài hòa, dễ đọc.
Nhận xét: Biểu đồ cho thấy vận tốc trung bình của các chuyến bay tương đối ổn định trong ngày, dao động quanh 406–411 dặm/giờ. Trong ngày thường (Weekday), tốc độ tăng nhẹ từ 407.3 mph buổi sáng lên 408.4 mph buổi chiều, rồi giảm dần còn 406.6 mph buổi tối. Với cuối tuần (Weekend), xu hướng tương tự nhưng cao hơn một chút, đạt đỉnh 410.5 mph buổi chiều và duy trì quanh 408 mph vào các thời điểm khác.
avg_taxi_out <- flight_data_no_outlier %>%
group_by(dep_hour) %>%
summarise(mean_taxi_out = mean(taxi_out, na.rm = TRUE))
ggplot(avg_taxi_out, aes(x = dep_hour, y = mean_taxi_out)) +
geom_area(fill = "#AED6F1", alpha = 0.6) + geom_line(color = "#1A5276", linewidth = 1.2) +
geom_point(size = 2, color = "#154360") +
geom_text(aes(label = round(mean_taxi_out, 1)),
vjust = -0.8, size = 3.5, fontface = "bold") +
geom_hline(yintercept = mean(avg_taxi_out$mean_taxi_out),
color = "darkred", linetype = "dashed") +
labs(title = "Thời gian taxi-in trung bình theo giờ khởi hành",
subtitle = "Quan sát xu hướng thời gian lăn bánh khi hạ cánh theo khung giờ bay",
x = "Giờ khởi hành",
y = "Thời gian taxi-in trung bình (phút)",
caption = "Nguồn: flight_data_no_outlier") +
ylim(0, 25) +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
plot.subtitle = element_text(size = 11, hjust = 0.5),
axis.text = element_text(size = 10),
axis.title = element_text(size = 12, face = "bold")
)
Giải thích:
(1–2) Nhóm dữ liệu theo giờ khởi hành và tính trung bình thời gian taxi-out.
(4–15) Vẽ biểu đồ vùng kết hợp đường và điểm, thêm nhãn giá trị, đường trung bình toàn bộ (màu đỏ, nét đứt), đặt tiêu đề, giới hạn trục y và định dạng văn bản.
Nhận xét:
Biểu đồ cho thấy thời gian taxi-in trung bình của các chuyến bay dao động trong khoảng 15–20 phút tùy theo giờ khởi hành.
Giai đoạn sáng sớm (0h–4h) có thời gian taxi-in ngắn nhất, khoảng 14–16 phút, do lưu lượng bay thấp, sân bay thông thoáng.
Từ 5h–9h sáng, thời gian taxi-in tăng mạnh lên trên 19–20 phút, đạt đỉnh vào khoảng 7h — đây là khung giờ cao điểm sáng, nhiều chuyến bay hạ cánh cùng lúc gây tắc nghẽn đường lăn.
Sau 10h, thời gian taxi-in giảm dần và ổn định quanh mức 17–18 phút cho đến cuối ngày.
Đường trung bình (đỏ đứt đoạn) nằm khoảng 17.8 phút, cho thấy phần lớn thời điểm có thời gian taxi-in cao hơn mức trung bình, đặc biệt buổi sáng.
delay_distance <- flight_data_no_outlier %>%
group_by(distance_level) %>%
summarise(`Độ trễ TB (phút)` = mean(dep_delay, na.rm = TRUE), .groups = "drop")
ggplot(delay_distance, aes(x = reorder(distance_level, `Độ trễ TB (phút)`),
y = `Độ trễ TB (phút)`, fill = `Độ trễ TB (phút)`)) +
geom_col(width = 0.6, color = "white", show.legend = FALSE) +
geom_text(aes(label = round(`Độ trễ TB (phút)`, 1)),
hjust = -0.2, size = 4, fontface = "bold") +
scale_fill_gradient(low = "#AED6F1", high = "#1A5276") +
coord_flip(ylim = c(0, max(delay_distance$`Độ trễ TB (phút)`) * 1.3)) +
geom_hline(yintercept = mean(delay_distance$`Độ trễ TB (phút)`),
color = "darkgreen", linetype = "dashed", linewidth = 0.8) +
labs(title = "Độ trễ khởi hành trung bình theo nhóm quãng đường bay",
subtitle = "Biểu đồ cột ngang thể hiện độ trễ tăng theo độ dài quãng đường",
x = "Nhóm quãng đường bay", y = "Độ trễ trung bình (phút)",
caption = "Nguồn: flight_data_no_outlier") +
theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 12, color = "gray40", hjust = 0.5),
axis.text = element_text(size = 12),
axis.title = element_text(size = 12, face = "bold"),
panel.grid.minor = element_blank())
Giải thích:
(1–2) Nhóm dữ liệu theo mức quãng đường bay.
(3) Tính độ trễ khởi hành trung bình cho từng nhóm.
(4–15) Vẽ biểu đồ cột ngang, tô màu theo giá trị trễ, hiển thị nhãn số, thêm đường trung bình toàn bộ (xanh lá, nét đứt), tiêu đề và phụ đề mô tả xu hướng.
Nhận xét: Biểu đồ cho thấy độ trễ khởi hành trung bình tăng dần theo độ dài quãng đường bay: Độ trễ khởi hành có mối tương quan dương nhẹ với độ dài quãng đường bay, cho thấy các chuyến bay dài thường chịu ảnh hưởng bởi khâu chuẩn bị và điều phối phức tạp hơn (nhiên liệu, hành khách, kỹ thuật). Tuy nhiên, mức chênh lệch không quá lớn, phản ánh hệ thống khai thác nhìn chung ổn định giữa các tuyến.
flight_data_no_outlier <- flight_data_no_outlier %>%
mutate(dep_hour = floor(dep_time / 100))
ggplot(flight_data_no_outlier, aes(x = dep_hour, fill = op_unique_carrier)) +
geom_density(alpha = 0.6) +
facet_wrap(~ op_unique_carrier, scales = "free_y") +
labs(title = "Phân bố thời gian khởi hành theo từng hãng hàng không",
x = "Giờ khởi hành", y = "Mật độ") +
theme_minimal(base_family = "TimesVN") +
theme(legend.position = "none",
plot.title = element_text(size = 16, face = "bold", hjust = 0.5))
Giải thích:
(1–2) Tạo biến
dep_hour bằng cách làm tròn giờ khởi hành
xuống bội số 100.
(3–9) Vẽ biểu đồ mật độ
(density) thể hiện phân bố giờ khởi hành của các hãng, chia ô
riêng cho từng hãng (facet_wrap), thêm tiêu đề và ẩn
legend.
Nhận xét:
Biểu đồ thể hiện phân bố thời gian khởi hành của các hãng hàng không có sự khác biệt rõ rệt về khung giờ hoạt động:
Phần lớn các hãng như AA, DL, UA, WN, NK tập trung khởi hành dày đặc từ 6h đến 20h, phản ánh lịch bay thương mại tập trung ban ngày.
Một số hãng như HA, G4, F9 có đặc điểm phân bố lệch sáng sớm hoặc chiều tối, do khai thác các tuyến ngắn và đặc thù vùng địa lý.
Các hãng MQ, 9E, OO có mật độ cao hơn vào buổi sáng (5h–10h), thể hiện đặc trưng của các chuyến bay nội địa nối chuyến (regional flights).
ggplot(flight_data_no_outlier, aes(x = dep_delay, y = arr_delay)) +
geom_point(alpha = 0.5, color = "#3498DB") +
geom_smooth(method = "lm", color = "red", linewidth = 1) +
labs(title = "Mối quan hệ giữa độ trễ khởi hành và độ trễ đến",
x = "Độ trễ khởi hành (phút)", y = "Độ trễ đến (phút)") +
theme_minimal(base_family = "TimesVN") +
theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5))
Giải thích:
(1) Ánh xạ trục x = độ trễ khởi hành, y = độ trễ khi đến.
(2) Vẽ các điểm phân tán, màu xanh, độ trong suốt 0.5.
(3) Thêm đường hồi quy tuyến tính màu đỏ để thể hiện xu hướng.
(4–6) Đặt tiêu đề, nhãn trục và định dạng kiểu chữ.
Nhận xét: Biểu đồ cho thấy mối quan hệ tuyến tính rất chặt chẽ giữa độ trễ khởi hành (dep_delay) và độ trễ khi đến (arr_delay)
delay_heat <- flight_data_no_outlier %>%
group_by(month, day_of_week) %>%
summarise(mean_delay = mean(arr_delay, na.rm = TRUE))
ggplot(delay_heat, aes(x = factor(month), y = factor(day_of_week), fill = mean_delay)) +
geom_tile(color = "white") +
scale_fill_gradient(low = "skyblue", high = "violet") + geom_text(aes(label = round(mean_delay, 1)), color = "black", size = 3) + labs(title = "Trung bình độ trễ theo tháng và ngày trong tuần",
x = "Tháng", y = "Ngày trong tuần", fill = "Độ trễ (phút)") +
theme_minimal(base_family = "TimesVN")
Giải thích:
(1–2) Nhóm dữ liệu theo tháng và ngày trong tuần, tính trung bình độ trễ khi đến.
(3–7) Vẽ biểu đồ nhiệt (heatmap), mỗi ô biểu thị giá trị trễ trung bình, tô màu từ xanh nhạt đến tím, thêm nhãn số, tiêu đề và nhãn trục.
Nhận xét: Biểu đồ heatmap thể hiện độ trễ trung bình của các chuyến bay theo tháng và ngày trong tuần cho thấy: Độ trễ cao nhất tập trung vào tháng 1, đặc biệt là ngày thứ 2 (16 phút) và thứ 5 (13,3 phút) – có thể do nhu cầu bay tăng mạnh sau kỳ nghỉ lễ. Sang tháng 2, độ trễ nhìn chung giảm đáng kể, nhiều ngày có giá trị gần 0 hoặc âm, cho thấy các chuyến bay đến sớm hơn lịch trình. Các ngày cuối tuần (thứ 6, 7) thường có độ trễ cao hơn so với giữa tuần, phản ánh áp lực khai thác tăng do lượng hành khách di chuyển nhiều hơn.
delay_rank <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(on_time = 100 - mean(arr_delay > 0, na.rm = TRUE) * 100) %>%
arrange(desc(on_time))
ggplot(delay_rank, aes(x = reorder(op_unique_carrier, on_time), y = on_time, fill = on_time)) +
geom_col() + geom_text(aes(label = paste0(round(on_time, 1), "%")), vjust = -0.3, size = 3.2) + scale_fill_gradient(low = "#81C784", high = "#2E7D32") +
geom_hline(yintercept = mean(delay_rank$on_time), linetype = "dashed", color = "red") +
labs(title = "Tỷ lệ đúng giờ trung bình theo hãng hàng không",
x = "Hãng hàng không", y = "Tỷ lệ đúng giờ (%)") +
theme_minimal()
Giải thích
(1–2) Nhóm dữ liệu theo hãng hàng không.
(3) Tính tỷ lệ chuyến bay đúng giờ = 100% – tỷ lệ chuyến bay trễ.
(4) Sắp xếp giảm dần theo tỷ lệ đúng giờ.
(5–12) Vẽ biểu đồ cột, hiển thị phần trăm trên cột, thêm đường trung bình (đỏ, nét đứt) và định dạng màu sắc, tiêu đề.
Nhận xét: Biểu đồ thể hiện tỷ lệ chuyến bay đúng giờ trung bình theo từng hãng hàng không, giúp đánh giá hiệu quả vận hành của các hãng. Hãng YX (77.6 phần trăm) và 9E (73.6 phần trăm) đạt tỷ lệ đúng giờ cao nhất, cho thấy quy trình khai thác và điều phối bay ổn định. Mức chênh lệch giữa hãng cao nhất và thấp nhất lên đến hơn 30 điểm phần trăm, cho thấy sự khác biệt đáng kể trong năng lực điều hành bay giữa các hãng.
avg_speed_hour <- flight_data_no_outlier %>%
group_by(dep_hour) %>%
summarise(mean_speed = mean(speed_mph, na.rm = TRUE))
ggplot(avg_speed_hour, aes(x = dep_hour, y = mean_speed)) +
geom_line(color = "#2874A6", linewidth = 1.2) +
geom_point(size = 3, color = "#1ABC9C") +
geom_text(aes(label = round(mean_speed, 1)), vjust = -0.8, size = 3) +
geom_smooth(method = "loess", color = "red", se = FALSE, linetype = "dashed") + # +4: Đường mượt
labs(title = "Tốc độ trung bình theo giờ khởi hành",
subtitle = "Quan sát sự thay đổi vận tốc trung bình của các chuyến bay trong ngày",
x = "Giờ khởi hành",
y = "Tốc độ trung bình (dặm/giờ)",
caption = "Nguồn: flight_data_no_outlier") +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
axis.text = element_text(size = 11),
axis.title = element_text(size = 12, face = "bold"))
Giải thích:
(1–2) Nhóm dữ liệu theo giờ khởi hành.
(3) Tính vận tốc trung bình (mph) cho từng giờ, bỏ giá trị thiếu.
(4–17) Vẽ biểu đồ đường kết hợp điểm, hiển thị nhãn giá trị, thêm đường mượt (loess) để quan sát xu hướng, đặt tiêu đề và định dạng trục.
Nhận xét: Biểu đồ thể hiện tốc độ trung bình (dặm/giờ) theo giờ khởi hành trong ngày giúp quan sát sự thay đổi hiệu suất bay trong 24 giờ. Hai đỉnh tốc độ rõ rệt xuất hiện vào khoảng 0h và 23–24h, đạt trên 480–498 dặm/giờ, cho thấy các chuyến bay vào ban đêm và rạng sáng thường di chuyển nhanh hơn. Đường hồi quy (màu đỏ) cho thấy xu hướng hình chữ U, với tốc độ giảm dần từ rạng sáng đến giữa ngày rồi tăng trở lại về đêm.
Tên bộ dữ liệu: Báo cáo tài chính doanh nghiệp (NVL) giai đoạn 2014–2025
Nguồn bộ dữ liệu: Báo cáo tài chính hợp nhất của Công ty Cổ phần Tập đoàn Đầu tư Địa ốc No Va (Novaland Group – mã chứng khoán: NVL), được thu thập từ Sở Giao dịch Chứng khoán Thành phố Hồ Chí Minh (HOSE), Ủy ban Chứng khoán Nhà nước (SSC) và các báo cáo tài chính kiểm toán công khai trên trang thông tin của doanh nghiệp.
Thông tin bộ dữ liệu:
Bộ dữ liệu này ghi nhận chi tiết các chỉ tiêu tài chính chủ yếu trong bảng cân đối kế toán của Novaland qua nhiều quý, từ Quý II năm 2014 đến Quý I năm 2025.
Các biến trong bộ dữ liệu phản ánh cơ cấu tài sản, cơ cấu nguồn vốn, đòn bẩy tài chính, khả năng thanh khoản và khả năng sinh lời của doanh nghiệp trong suốt giai đoạn hoạt động.
Bộ dữ liệu này thích hợp cho phân tích mô tả, so sánh thời gian, tính toán các chỉ tiêu tài chính (ROA, ROE, hệ số nợ, khả năng thanh toán) và trực quan hóa xu hướng tài chính của doanh nghiệp bằng ngôn ngữ R.
Mục đích lấy dữ liệu:
Bộ dữ liệu được sử dụng để:
Thực hiện làm sạch, xử lý và mã hóa dữ liệu tài chính trong ngôn ngữ R.
Phân tích và đánh giá hiệu quả hoạt động tài chính của NVL trong giai đoạn 2014–2025 thông qua các chỉ tiêu quan trọng như ROA, ROE, Debt Ratio, Current Ratio;
Minh họa việc ứng dụng ngôn ngữ lập trình R trong phân tích dữ liệu tài chính doanh nghiệp, bao gồm thống kê cơ bản, tạo biến mới, trực quan hóa dữ liệu và trình bày kết quả học thuật.
library(readxl)
BCTC_NVL <- read_excel("C:/Users/LENOVO/Downloads/BCTC_NVL.xlsx")
dim(BCTC_NVL)
## [1] 10 12
Giải thích:
(1) Dùng để kiểm tra kích thước của bộ dữ liệu.
Nhận xét: - Bộ dữ liệu có 10 quan sát và 12 biến.
names(BCTC_NVL)
## [1] "Năm" "Tiền và các khoản tương đương tiền"
## [3] "Tài sản ngắn hạn" "Tài sản dài hạn"
## [5] "Các khoản phải thu ngắn hạn" "Hàng tồn kho"
## [7] "Tài sản cố định hữu hình" "Đầu tư tài chính dài hạn"
## [9] "Nợ ngắn hạn" "Nợ dài hạn"
## [11] "Vốn chủ sở hữu" "Lợi nhuận sau thuế"
Giải thích:
(1) dùng để hiển thị tên các biến trong bộ dữ liệu.
Nhận xét: Kết quả cung cấp danh sách tên biến nhằm làm nền tảng cho các bước mô tả, so sánh và mô hình hóa trong phân tích thống kê sau này.
loai<- data.frame(Kieu_du_lieu = sapply((BCTC_NVL), typeof))
kable(loai, col.names = c("Tên biến", "Kiểu dữ liệu"))
| Tên biến | Kiểu dữ liệu |
|---|---|
| Năm | double |
| Tiền và các khoản tương đương tiền | double |
| Tài sản ngắn hạn | double |
| Tài sản dài hạn | double |
| Các khoản phải thu ngắn hạn | double |
| Hàng tồn kho | double |
| Tài sản cố định hữu hình | double |
| Đầu tư tài chính dài hạn | double |
| Nợ ngắn hạn | double |
| Nợ dài hạn | double |
| Vốn chủ sở hữu | double |
| Lợi nhuận sau thuế | double |
Giải thích:
(1) Tạo bảng loai xác định kiểu dữ liệu
của từng biến trong BCTC_NVL.
(2) trình bày kết quả dưới dạng bảng rõ ràng, dễ đọc.
Nhận xét:
Các biến định lượng (integer) như: month, day_of_month, day_of_week, op_carrier_fl_num, crs_dep_time, dep_time, dep_delay,… được dùng để tính trung bình, so sánh, đo lường, vẽ biểu đồ phân bố (histogram, boxplot).
Các biến định tính (character) như: fl_date, op_unique_carrier, origin, origin_city_name, origin_state_nm, dest, dest_city_name,… dùng để mô tả, phân loại, vẽ bar chart hoặc pie chart.
table(sapply(BCTC_NVL, typeof))
##
## double
## 12
Giải thích:
(1) Dùng để thống kê tần suất các kiểu dữ liệu xuất
hiện trong bộ dữ liệu BCTC_NVL.
Nhận xét:
Bộ dữ liệu có 8 biến thuộc kiểu character và 18 biến thuộc kiểu integer.
sum(duplicated(BCTC_NVL))
## [1] 0
Giải thích:
(1) đếm số lượng dòng bị trùng lặp trong bộ dữ liệu
BCTC_NVL.
Nhận xét:
head(BCTC_NVL, 5)
Giải thích:
(1) hiển thị 5 dòng đầu tiên của bộ dữ liệu
BCTC_NVL.
Nhận xét:
tail(BCTC_NVL, 5)
Giải thích:
(1) hiển thị 5 dòng cuối cùng của bộ dữ liệu
BCTC_NVL.
Nhận xét:
Việc quan sát 5 dòng cuối giúp kiểm tra tính đầy đủ, phát hiện các dữ liệu bị thiếu ở cuối bảng trước khi tiến hành phân tích thống kê.
data_dict <- data.frame(
varible_ck = c(
"nam",
"tien_va_cac_khoan_tuong_duong_tien",
"tai_san_ngan_han",
"tai_san_dai_han",
"cac_khoan_phai_thu_ngan_han",
"hang_ton_kho",
"tai_san_co_dinh_huu_hinh",
"dau_tu_tai_chinh_dai_han",
"no_ngan_han",
"no_dai_han",
"von_chu_so_huu",
"loi_nhuan_sau_thue"),
meaning_ck = c(
"Năm tài chính của báo cáo.",
"Tổng tiền mặt, tiền gửi ngân hàng và các khoản tương đương tiền có tính thanh khoản cao.",
"Tổng tài sản ngắn hạn có thể chuyển đổi thành tiền trong vòng 12 tháng.",
"Tổng tài sản dài hạn có thời gian thu hồi hoặc sử dụng trên 12 tháng.",
"Các khoản phải thu ngắn hạn từ khách hàng, tạm ứng hoặc cho vay ngắn hạn.",
"Giá trị hàng tồn kho gồm nguyên vật liệu, sản phẩm dở dang và thành phẩm chưa bán.",
"Giá trị còn lại của tài sản cố định hữu hình sau khấu hao lũy kế.",
"Giá trị các khoản đầu tư tài chính dài hạn như cổ phần, trái phiếu hoặc góp vốn.",
"Tổng nghĩa vụ tài chính phải trả trong vòng 1 năm (vay ngắn hạn, thuế, phải trả người bán…).",
"Các khoản nợ dài hạn có thời hạn thanh toán trên 1 năm.",
"Tổng vốn chủ sở hữu gồm vốn góp, thặng dư vốn và lợi nhuận giữ lại.",
"Lợi nhuận ròng sau khi trừ toàn bộ chi phí và thuế thu nhập doanh nghiệp."))
library(knitr)
library(kableExtra)
kable(data_dict,
caption = "Danh sách và ý nghĩa các biến trong bộ dữ liệu",
col.names = c("Tên biến", "Ý nghĩa"),
align = c("l", "l")) %>%
kable_styling(full_width = FALSE,
position = "center",
bootstrap_options = c("hover", "striped"))
| Tên biến | Ý nghĩa |
|---|---|
| nam | Năm tài chính của báo cáo. |
| tien_va_cac_khoan_tuong_duong_tien | Tổng tiền mặt, tiền gửi ngân hàng và các khoản tương đương tiền có tính thanh khoản cao. |
| tai_san_ngan_han | Tổng tài sản ngắn hạn có thể chuyển đổi thành tiền trong vòng 12 tháng. |
| tai_san_dai_han | Tổng tài sản dài hạn có thời gian thu hồi hoặc sử dụng trên 12 tháng. |
| cac_khoan_phai_thu_ngan_han | Các khoản phải thu ngắn hạn từ khách hàng, tạm ứng hoặc cho vay ngắn hạn. |
| hang_ton_kho | Giá trị hàng tồn kho gồm nguyên vật liệu, sản phẩm dở dang và thành phẩm chưa bán. |
| tai_san_co_dinh_huu_hinh | Giá trị còn lại của tài sản cố định hữu hình sau khấu hao lũy kế. |
| dau_tu_tai_chinh_dai_han | Giá trị các khoản đầu tư tài chính dài hạn như cổ phần, trái phiếu hoặc góp vốn. |
| no_ngan_han | Tổng nghĩa vụ tài chính phải trả trong vòng 1 năm (vay ngắn hạn, thuế, phải trả người bán…). |
| no_dai_han | Các khoản nợ dài hạn có thời hạn thanh toán trên 1 năm. |
| von_chu_so_huu | Tổng vốn chủ sở hữu gồm vốn góp, thặng dư vốn và lợi nhuận giữ lại. |
| loi_nhuan_sau_thue | Lợi nhuận ròng sau khi trừ toàn bộ chi phí và thuế thu nhập doanh nghiệp. |
Giải thích:
(1)->(14) Tạo bảng data_dict gồm hai cột “Tên biến” và “Ý nghĩa”, mô tả chi tiết nội dung của từng biến trong bộ dữ liệu BCTC_NVL.
(15)->(17) Dùng kable() và
kable_styling() để hiển thị bảng danh mục
biến, căn giữa, định dạng rõ ràng và đảm bảo tính thẩm mỹ khi
xuất ra báo cáo.
Nhận xét: Bảng kết quả giúp người đọc hiểu rõ vai trò của từng biến.
Kiểm tra xem trong toàn bộ bảng dữ liệu có tồn tại giá trị bị thiếu (NA) ở bất kỳ vị trí nào hay không:
any(is.na(BCTC_NVL))
## [1] FALSE
Giải thích:
(1) Dùng để kiểm tra xem trong bộ dữ liệu
BCTC_NVL có giá trị khuyết (NA) nào hay không.
Nhận xét: Vì kết quả trả về là FALSE nên bộ dữ liệu không bị thiếu (NA) ở bất kỳ hàng, cột nào.
colnames(BCTC_NVL) <- colnames(BCTC_NVL) %>%
stringi::stri_trans_general("Latin-ASCII") %>%
gsub(" ", "_", .) %>%
tolower()
kable(data.frame("Biến" = colnames(BCTC_NVL)), caption = "**Danh sách tên biến sau khi chuẩn hóa**",
align = "l") %>%
kable_styling(full_width = FALSE, position = "center",
bootstrap_options = c("hover", "striped"))
| Biến |
|---|
| nam |
| tien_va_cac_khoan_tuong_duong_tien |
| tai_san_ngan_han |
| tai_san_dai_han |
| cac_khoan_phai_thu_ngan_han |
| hang_ton_kho |
| tai_san_co_dinh_huu_hinh |
| dau_tu_tai_chinh_dai_han |
| no_ngan_han |
| no_dai_han |
| von_chu_so_huu |
| loi_nhuan_sau_thue |
Giải thích:
(1)–>(4) Chuẩn hóa tên cột trong
BCTC_NVL bằng cách bỏ dấu tiếng Việt, thay khoảng trắng
bằng dấu gạch dưới và chuyển về chữ thường nhằm đảm bảo tính nhất quán
khi xử lý dữ liệu.
(5)–>(8) Dùng kable() và
kable_styling() để hiển thị bảng danh sách tên cột sau
chuẩn hóa, trình bày rõ ràng, có chú thích và định dạng thẩm mỹ trong
báo cáo.
Nhận xét: Các tên cột sau khi chuẩn hóa đã được chuyển sang dạng thống nhất (không dấu, viết thường, có dấu gạch dưới), giúp thuận tiện cho việc xử lý và gọi biến trong R, tránh lỗi do ký tự đặc biệt hoặc khoảng trắng gây ra.
BCTC_NVL <- BCTC_NVL %>%
mutate(giai_doan = ifelse(nam < 2019, "Trước Covid", "Sau Covid"))
table(BCTC_NVL$giai_doan)
##
## Sau Covid Trước Covid
## 6 4
Giải thích:
(2) Tạo biến mới giai_doan, phân loại
các năm trước 2019 là “Trước Covid” và từ 2019 trở
đi là “Sau Covid”.
(3) thống kê tần suất quan sát theo từng giai đoạn.
Nhận xét: Bộ dữ liệu có 6 quan sát Sau Covid và 4 quan sát Trước Covid, tổng cộng 10 kỳ báo cáo.
BCTC_NVL$giai_doan <- as.factor(BCTC_NVL$giai_doan)
class(BCTC_NVL$giai_doan)
## [1] "factor"
Giải thích:
(1) Chuyển biến giai_doan sang kiểu
factor để phục vụ phân tích phân loại.
(2) kiểm tra kiểu dữ liệu của biến sau khi chuyển đổi.
Nhận xét: Kết quả “factor” xác nhận việc chuyển đổi đã thành công.
BCTC_NVL <- BCTC_NVL %>%
mutate(tong_tai_san = tai_san_ngan_han + tai_san_dai_han)
kable(head(BCTC_NVL[, c("nam", "tai_san_ngan_han", "tai_san_dai_han", "tong_tai_san")], 6),
caption = "Biến Tổng tài sản được tạo từ hai thành phần cấu thành**",
align = "cccc") %>%
kable_styling(full_width = FALSE, position = "center",
bootstrap_options = c("hover", "striped"))
| nam | tai_san_ngan_han | tai_san_dai_han | tong_tai_san |
|---|---|---|---|
| 2015 | 1.813329e+13 | 8.437119e+12 | 2.657041e+13 |
| 2016 | 3.028873e+13 | 6.238346e+12 | 3.652708e+13 |
| 2017 | 4.116597e+13 | 8.300996e+12 | 4.946696e+13 |
| 2018 | 5.086094e+13 | 1.905127e+13 | 6.991221e+13 |
| 2019 | 7.119482e+13 | 1.878442e+13 | 8.997924e+13 |
| 2020 | 1.142036e+14 | 3.033278e+13 | 1.445363e+14 |
Giải thích:
(1)–>(2) Tạo biến mới tong_tai_san bằng cách cộng tài sản ngắn hạn và tài sản dài hạn, phản ánh quy mô tổng tài sản của doanh nghiệp.
(3)–>(5) Dùng kable() để
hiển thị 6 dòng đầu của các cột liên quan cùng chú
thích bảng.
(6)–>(7) Áp dụng kable_styling() để
trình bày bảng gọn, căn giữa và có định dạng thẩm mỹ khi xuất báo
cáo.
Nhận xét: Biến
tong_tai_san phản ánh quy mô tổng thể của
tài sản mà doanh nghiệp sở hữu trong mỗi kỳ.
BCTC_NVL <- BCTC_NVL %>%
mutate(tong_no = no_ngan_han + no_dai_han)
kable(head(BCTC_NVL[, c("nam", "no_ngan_han", "no_dai_han", "tong_no")], 6),
caption = "Biến Tổng nợ được tạo từ nợ ngắn hạn và nợ dài hạn**",
align = "cccc") %>%
kable_styling(full_width = FALSE,
position = "center",
bootstrap_options = c("hover", "striped"))
| nam | no_ngan_han | no_dai_han | tong_no |
|---|---|---|---|
| 2015 | 3.354624e+12 | 7.120575e+12 | 1.047520e+13 |
| 2016 | 1.501122e+13 | 1.146896e+13 | 2.648019e+13 |
| 2017 | 2.265820e+13 | 1.355238e+13 | 3.621057e+13 |
| 2018 | 2.796939e+13 | 2.148269e+13 | 4.945209e+13 |
| 2019 | 1.880963e+13 | 4.670853e+13 | 6.551817e+13 |
| 2020 | 3.142734e+13 | 8.117685e+13 | 1.126042e+14 |
Giải thích:
(2) Tạo biến mới tong_no bằng cách cộng nợ ngắn hạn và nợ dài hạn, thể hiện tổng nghĩa vụ tài chính của doanh nghiệp trong từng kỳ.
(3) hiển thị 6 dòng đầu tiên của các cột liên quan, giúp minh họa quá trình tạo biến mới.
(5) Áp dụng kable_styling() để
căn giữa, làm gọn bảng và tăng tính thẩm mỹ khi trình
bày trong báo cáo.
Nhận xét: Biến tong_no
thể hiện tổng giá trị nghĩa vụ nợ của doanh nghiệp trong từng năm.
Chỉ tiêu này sẽ được sử dụng để tính tỷ lệ nợ (Debt Ratio) và đòn bẩy tài chính (Financial Leverage) trong chương tiếp theo.
Kết quả cho thấy biến mới đã được tạo chính xác, giúp hoàn thiện cấu trúc dữ liệu phục vụ cho phân tích tài chính NVL.
BCTC_NVL <- BCTC_NVL %>%
mutate(
roa = round((loi_nhuan_sau_thue / tong_tai_san) * 100, 2),
roe = round((loi_nhuan_sau_thue / von_chu_so_huu) * 100, 2))
kable(
head(BCTC_NVL[, c("nam", "roa", "roe")], 10),
caption = "Các chỉ tiêu ROA và ROE của Công ty NVL qua các năm",
align = "ccc",
col.names = c("Năm", "ROA (%)", "ROE (%)"))
| Năm | ROA (%) | ROE (%) |
|---|---|---|
| 2015 | 2.07 | 9.03 |
| 2016 | 2.61 | 9.48 |
| 2017 | 5.88 | 21.93 |
| 2018 | 8.74 | 29.85 |
| 2019 | 9.69 | 35.66 |
| 2020 | 8.34 | 37.74 |
| 2021 | 5.31 | 26.01 |
| 2022 | 5.00 | 28.76 |
| 2023 | 5.59 | 29.79 |
| 2024 | 5.59 | 28.08 |
Giải thích:
(1-3) Tạo hai biến ROA và ROE phản ánh hiệu quả sinh lời từ tài sản và vốn chủ sở hữu, làm tròn hai chữ số thập phân.
(4) Dùng kable() để hiển thị 10
dòng đầu của bảng kết quả với tiêu đề và định dạng rõ ràng.
Nhận xét: Giai đoạn 2015–2019, ROA và ROE tăng mạnh, phản ánh hiệu quả sinh lời cải thiện rõ rệt nhờ mở rộng quy mô và sử dụng vốn vay hiệu quả. Từ năm 2020, hai chỉ tiêu giảm nhẹ do ảnh hưởng Covid-19, sau đó ổn định trở lại quanh mức 5–6 phần trăm (ROA) và 28–30 phần trăm (ROE). ROE luôn cao hơn ROA, cho thấy NVL sử dụng đòn bẩy tài chính tích cực để gia tăng lợi nhuận cho cổ đông.
BCTC_NVL <- BCTC_NVL %>%
mutate(ty_le_no = round((tong_no / tong_tai_san) * 100, 2))
kable(
head(BCTC_NVL[, c("nam", "tong_no", "tong_tai_san", "ty_le_no")], 6),
caption = "Tỷ lệ nợ (Debt Ratio) của Công ty NVL qua các năm",
align = "cccc")
| nam | tong_no | tong_tai_san | ty_le_no |
|---|---|---|---|
| 2015 | 1.047520e+13 | 2.657041e+13 | 39.42 |
| 2016 | 2.648019e+13 | 3.652708e+13 | 72.49 |
| 2017 | 3.621057e+13 | 4.946696e+13 | 73.20 |
| 2018 | 4.945209e+13 | 6.991221e+13 | 70.73 |
| 2019 | 6.551817e+13 | 8.997924e+13 | 72.81 |
| 2020 | 1.126042e+14 | 1.445363e+14 | 77.91 |
Giải thích:
(2) Tạo biến ty_le_no phản ánh tỷ lệ nợ trên tổng tài sản, làm tròn hai chữ số thập phân.
(3-4) Dùng kable() để hiển thị 6 dòng
đầu của bảng kết quả.
Nhận xét: Tỷ lệ nợ của NVL tăng nhanh từ 39.4 phần trăm năm 2015 lên 77.9 phần trăm năm 2020, cho thấy doanh nghiệp ngày càng phụ thuộc vào vốn vay để mở rộng quy mô hoạt động. Mức nợ cao phản ánh rủi ro tài chính lớn hơn, nhưng cũng cho thấy NVL sử dụng đòn bẩy tài chính mạnh nhằm gia tăng lợi nhuận cho cổ đông.
BCTC_NVL <- BCTC_NVL %>%
mutate(don_bay_tai_chinh = round(tong_tai_san / von_chu_so_huu, 2))
kable(
head(BCTC_NVL[, c("nam", "tong_tai_san", "von_chu_so_huu", "don_bay_tai_chinh")], 6),
caption = "Đòn bẩy tài chính của Công ty NVL qua các năm",
col.names = c("Năm", "Tổng tài sản", "Vốn chủ sở hữu", "Đòn bẩy tài chính"),
align = c("c", "c", "c", "c"))
| Năm | Tổng tài sản | Vốn chủ sở hữu | Đòn bẩy tài chính |
|---|---|---|---|
| 2015 | 2.657041e+13 | 6.095209e+12 | 4.36 |
| 2016 | 3.652708e+13 | 1.004689e+13 | 3.64 |
| 2017 | 4.946696e+13 | 1.325639e+13 | 3.73 |
| 2018 | 6.991221e+13 | 2.046013e+13 | 3.42 |
| 2019 | 8.997924e+13 | 2.446107e+13 | 3.68 |
| 2020 | 1.445363e+14 | 3.193215e+13 | 4.53 |
Giải thích:
(2) Tạo biến don_bay_tai_chinh = tổng tài sản / vốn chủ sở hữu, làm tròn hai chữ số thập phân, thể hiện mức độ sử dụng vốn vay của doanh nghiệp.
(3-6) Dùng kable() để hiển thị
6 dòng đầu của bảng kết quả với tiêu đề và nhãn cột rõ
ràng.
Nhận xét: Giai đoạn 2015–2020, đòn bẩy tài chính của NVL dao động từ 3.4 đến 4.5 lần, cho thấy doanh nghiệp sử dụng vốn vay mạnh để mở rộng hoạt động. Chỉ tiêu tăng từ 4.36 (2015) lên 4.53 (2020) phản ánh xu hướng gia tăng phụ thuộc vào nợ vay, giúp tăng lợi nhuận cổ đông nhưng cũng làm rủi ro tài chính cao hơn.
Giúp xem mức khuếch đại lợi nhuận do nợ vay.
BCTC_NVL <- BCTC_NVL %>%
mutate(roe_roa_ratio = round(roe / roa, 2))
kable(
head(BCTC_NVL[, c("nam", "roa", "roe", "roe_roa_ratio")], 6),
caption = "Tỷ số ROE/ROA của Công ty NVL qua các năm",
col.names = c("Năm", "ROA (%)", "ROE (%)", "Tỷ lệ ROE/ROA"),
align = c("c", "c", "c", "c"))
| Năm | ROA (%) | ROE (%) | Tỷ lệ ROE/ROA |
|---|---|---|---|
| 2015 | 2.07 | 9.03 | 4.36 |
| 2016 | 2.61 | 9.48 | 3.63 |
| 2017 | 5.88 | 21.93 | 3.73 |
| 2018 | 8.74 | 29.85 | 3.42 |
| 2019 | 9.69 | 35.66 | 3.68 |
| 2020 | 8.34 | 37.74 | 4.53 |
Giải thích:
(2) Tạo biến roe_roa_ratio = ROE / ROA, làm tròn hai chữ số thập phân, phản ánh mức chênh lệch hiệu quả sinh lời giữa vốn chủ và tài sản.
(3) Dùng kable() để hiển thị 6 dòng đầu
của bảng kết quả với tiêu đề và nhãn cột rõ ràng.
Nhận xét: Tỷ lệ ROE/ROA của NVL duy trì quanh mức 3,4–4,5 lần trong giai đoạn 2015–2020, cho thấy lợi nhuận trên vốn chủ cao gấp nhiều lần so với tổng tài sản.
Giúp đo lường tỷ trọng vốn chủ trong tổng tài sản.
BCTC_NVL <- BCTC_NVL %>%
mutate(he_so_tu_tai_tro = round((von_chu_so_huu / tong_tai_san) * 100, 2))
kable(
head(BCTC_NVL[, c("nam", "von_chu_so_huu", "tong_tai_san", "he_so_tu_tai_tro")], 6),
caption = "Bảng 2.5.7. Hệ số tự tài trợ của Công ty NVL qua các năm",
col.names = c("Năm", "Vốn chủ sở hữu", "Tổng tài sản", "Hệ số tự tài trợ (%)"),
align = c("c", "c", "c", "c"))
| Năm | Vốn chủ sở hữu | Tổng tài sản | Hệ số tự tài trợ (%) |
|---|---|---|---|
| 2015 | 6.095209e+12 | 2.657041e+13 | 22.94 |
| 2016 | 1.004689e+13 | 3.652708e+13 | 27.51 |
| 2017 | 1.325639e+13 | 4.946696e+13 | 26.80 |
| 2018 | 2.046013e+13 | 6.991221e+13 | 29.27 |
| 2019 | 2.446107e+13 | 8.997924e+13 | 27.19 |
| 2020 | 3.193215e+13 | 1.445363e+14 | 22.09 |
Giải thích:
(2) Tạo biến he_so_tu_tai_tro = (vốn chủ sở hữu / tổng tài sản) × 100, làm tròn hai chữ số thập phân.
(3) hiển thị 6 dòng đầu của bảng kết quả với tiêu đề và tên cột rõ ràng.
Nhận xét: Tỷ lệ ROE/ROA của NVL duy trì quanh mức 3,4–4,5 lần trong giai đoạn 2015–2020, cho thấy lợi nhuận trên vốn chủ cao gấp nhiều lần so với tổng tài sản. Điều này phản ánh NVL sử dụng đòn bẩy tài chính hiệu quả, giúp khuếch đại lợi nhuận cho cổ đông, tuy nhiên cũng hàm ý mức độ rủi ro tài chính cao do phụ thuộc nhiều vào vốn vay.
Phân tích đặc điểm cơ bản của 3 biến định lượng: air_time, schedule_diff và distance.
quan_vars <- BCTC_NVL[, c("loi_nhuan_sau_thue", "tong_tai_san","von_chu_so_huu", "no_dai_han")]
Giải thích:
quant_vars <- flight_data_clean[, c(“loi_nhuan_sau_thue”,
“tong_tai_san”,“von_chu_so_huu”, “no_dai_han”)]: dùng để trích
4 biến định lượng từ bộ dữ liệu BCTC_NVL.
Nhận xét:
Lọc 3 biến định lượng này ra nhằm thống kê mô tả, tính trung bình, tính độ lệch chuẩn và tính khoảng của từng biến ở các bước tiếp theo.
summary(quan_vars)
## loi_nhuan_sau_thue tong_tai_san von_chu_so_huu
## Min. :5.504e+11 Min. :2.657e+13 Min. :6.095e+12
## 1st Qu.:3.707e+12 1st Qu.:5.458e+13 1st Qu.:1.506e+13
## Median :9.715e+12 Median :1.173e+14 Median :2.820e+13
## Mean :8.166e+12 Mean :1.356e+14 Mean :2.848e+13
## 3rd Qu.:1.268e+13 3rd Qu.:2.288e+14 3rd Qu.:4.391e+13
## Max. :1.349e+13 Max. :2.577e+14 Max. :4.729e+13
## no_dai_han
## Min. :7.121e+12
## 1st Qu.:1.553e+13
## Median :6.394e+13
## Mean :6.199e+13
## 3rd Qu.:1.025e+14
## Max. :1.347e+14
Giải thích: (1) Tạo đối tượng
quan_vars gồm bốn biến: Lợi nhuận sau thuế,
Tổng tài sản, Vốn chủ sở hữu và
Nợ dài hạn, dùng để phân tích và tính toán các chỉ
tiêu tài chính quan trọng.
Kết quả thống kê mô tả cho bốn biến định lượng gồm
Lợi nhuận sau thuế, Tổng tài sản,
Vốn chủ sở hữu và Nợ dài hạn phản ánh đặc điểm
tài chính nổi bật của Công ty Cổ phần Tập đoàn Đầu tư Địa ốc No Va (NVL)
trong giai đoạn. 2015–2024.
loi_nhuan_sau_thue)Giá trị lợi nhuận sau thuế dao động từ 5.504e+11 VND đến 1.349e+13 VND, với trung bình đạt 8.166e+12 VND.
Điều này cho thấy kết quả kinh doanh của NVL có xu hướng tăng trưởng đáng kể qua thời gian, phản ánh năng lực duy trì hiệu quả hoạt động và mở rộng quy mô sinh lời.
Sự chênh lệch lớn giữa giá trị cực tiểu và cực đại thể hiện giai đoạn tăng trưởng mạnh mẽ trước đại dịch và sự điều chỉnh nhẹ trong các năm sau.
tong_tai_san)Tổng tài sản của NVL có giá trị trung bình 1.356e+14 VND, dao động từ 2.657e+13 VND đến 2.577e+14⁴ VND.
Điều này phản ánh quy mô tài sản tăng nhanh qua từng năm, phù hợp với chiến lược mở rộng danh mục đầu tư và phát triển dự án của doanh nghiệp bất động sản quy mô lớn.
Độ lệch đáng kể giữa giá trị trung bình và giá trị lớn nhất cho thấy NVL liên tục gia tăng đầu tư tài sản cố định và tài sản dài hạn, góp phần mở rộng quy mô hoạt động.
von_chu_so_huu)Vốn chủ sở hữu ghi nhận giá trị trung bình 2.848e+13
VND, dao động từ 6.095e+12 VND đến 4.729e+13
VND.
Sự gia tăng ổn định của chỉ tiêu này cho thấy NVL có khả năng tích lũy lợi nhuận giữ lại và huy động vốn hiệu quả từ cổ đông.
Tuy nhiên, tốc độ tăng vốn chủ sở hữu chậm hơn tốc độ tăng tổng tài sản, hàm ý rằng doanh nghiệp sử dụng nợ vay như một công cụ tài trợ tăng trưởng chính yếu, qua đó gia tăng đòn bẩy tài chính.
no_dai_han)Nợ dài hạn của NVL có giá trị trung bình 6.20e+13
VND, với biên độ dao động rộng từ 7.12e+12 VND đến
1.35e+14 VND. Điều này cho thấy NVL phụ thuộc đáng kể vào nguồn
vốn vay dài hạn để mở rộng đầu tư và phát triển dự án, đặc trưng phổ
biến của các doanh nghiệp trong lĩnh vực bất động sản. Mức tăng nợ dài
hạn cao hơn tốc độ tăng vốn chủ sở hữu phản ánh cơ cấu tài chính thiên
về nợ, qua đó tăng hiệu quả sinh lời nhưng cũng tiềm ẩn rủi ro tài
chính.
Kết luận: Nhìn chung, NVL thể hiện hiệu quả hoạt động cao nhưng cấu trúc vốn tiềm ẩn rủi ro nợ vay, phù hợp với mô hình tài chính đặc trưng của các tập đoàn bất động sản lớn tại Việt Nam.
sapply(quan_vars, sd)
## loi_nhuan_sau_thue tong_tai_san von_chu_so_huu no_dai_han
## 5.170958e+12 9.222790e+13 1.574062e+13 4.777706e+13
Giải thích: (1) Dùng hàm
sapply() tính độ lệch chuẩn (sd) cho từng biến
trong quan_vars, giúp đánh giá mức độ biến động của các chỉ
tiêu tài chính.
Nhận xét: Độ lệch chuẩn phản ánh mức độ biến động của dữ liệu quanh giá trị trung bình.
Kết quả cho thấy các biến tài chính của NVL đều có độ lệch chuẩn cao, chứng tỏ sự thay đổi đáng kể qua các năm:
Tổng tài sản (SD = 9.222790e+13) và nợ dài hạn (SD = 4.777706e+13) biến động mạnh nhất, thể hiện quá trình mở rộng quy mô và tăng vay vốn đầu tư.
Vốn chủ sở hữu (SD = 1.574062e+13) tăng ổn định hơn, phản ánh năng lực tài chính nội tại được củng cố.
Lợi nhuận sau thuế (SD = 5.170958e+12) biến động trung bình, cho thấy hiệu quả kinh doanh thay đổi theo chu kỳ thị trường.
➡ Nhìn chung, NVL có mức biến động tài chính cao, đặc trưng của doanh nghiệp tăng trưởng nhanh và sử dụng đòn bẩy tài chính lớn.
sapply(quan_vars, var, na.rm = TRUE)
## loi_nhuan_sau_thue tong_tai_san von_chu_so_huu no_dai_han
## 2.673881e+25 8.505985e+27 2.477671e+26 2.282648e+27
Giải thích:
(1) Dùng hàm sapply() tính
phương sai (var) cho từng biến trong quan_vars.
Nhận xét: Phương sai lớn ở các biến quy mô (tài sản, nợ) chứng tỏ NVL đang trong giai đoạn mở rộng mạnh mẽ, sử dụng đòn bẩy tài chính cao.
sapply(quan_vars, function(x) max(x) - min(x))
## loi_nhuan_sau_thue tong_tai_san von_chu_so_huu no_dai_han
## 1.294384e+13 2.311645e+14 4.119581e+13 1.276224e+14
Giải thích: (1) Tính khoảng giá trị (max - min) của từng biến trong quan_vars để xác định mức dao động của dữ liệu.
Nhận xét:
Khoảng biến thiên thể hiện mức độ chênh lệch giữa giá trị lớn nhất và nhỏ nhất của mỗi biến trong giai đoạn 2015–2024.
Giá trị càng lớn → dữ liệu càng phân tán → mức độ thay đổi qua các năm càng cao.
Tổng tài sản (2.31e+14) và nợ dài hạn (1.28e+14) có khoảng biến thiên lớn nhất, phản ánh sự mở rộng quy mô hoạt động và tăng mạnh nguồn vốn vay của NVL.
Vốn chủ sở hữu (4.12e+13) cũng biến động đáng kể, cho thấy công ty tăng cường tích lũy và huy động vốn trong giai đoạn tăng trưởng.
Lợi nhuận sau thuế (1.29e+13) có mức biến động thấp hơn, thể hiện tốc độ tăng lợi nhuận ổn định hơn so với quy mô tài sản và nợ.
Giải thích chung:
(1)–>(2) Dùng geom_boxplot() để
vẽ biểu đồ hộp (boxplot) của các biến, giúp
phát hiện giá trị ngoại lai trong dữ liệu.
(3)–>(4) Thêm tiêu đề, nhãn trục và căn giữa tiêu đề để biểu đồ rõ ràng, mang tính học thuật.
ggplot(BCTC_NVL, aes(y = loi_nhuan_sau_thue)) +
geom_boxplot(fill = "#AED6F1", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: Lợi nhuận sau thuế",
y = "Lợi nhuận sau thuế (VND)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ hộp cho thấy biến
Lợi nhuận sau thuế không xuất hiện giá trị ngoại lai rõ
rệt.
ggplot(BCTC_NVL, aes(y = tong_tai_san)) +
geom_boxplot(fill = "#A9DFBF", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: Tổng tài sản",
y = "Tổng tài sản (VND)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ hộp cho thấy biến
Tổng tài sản không xuất hiện điểm ngoại lai.
ggplot(BCTC_NVL, aes(y = von_chu_so_huu)) +
geom_boxplot(fill = "#F9E79F", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: Vốn chủ sở hữu",
y = "Vốn chủ sở hữu (VND)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ hộp cho thấy biến
Vốn chủ sở hữu không xuất hiện điểm ngoại lai.
ggplot(BCTC_NVL, aes(y = no_dai_han)) +
geom_boxplot(fill = "#F5B7B1", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: Nợ dài hạn",
y = "Nợ dài hạn (VND)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ hộp cho thấy biến
Nợ dài hạn không xuất hiện giá trị ngoại lai.
ggplot(BCTC_NVL, aes(y = roa)) +
geom_boxplot(fill = "#D2B4DE", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: ROA",
y = "ROA (%)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ hộp cho thấy biến ROA
không xuất hiện giá trị ngoại lai.
ggplot(BCTC_NVL, aes(y = roe)) +
geom_boxplot(fill = "#FAD7A0", color = "black", width = 0.4) +
labs(title = "Boxplot - Kiểm tra ngoại lai: ROE",
y = "ROE (%)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Nhận xét: Biểu đồ cho thấy ROE có một
vài giá trị ngoại lai thấp, nằm ở khu vực quanh 8–10 phần trăm. Tuy
nhiên, ngoại lai không quá cực đoan, cho thấy hiệu suất vốn chủ vẫn ổn
định tổng thể, chỉ giảm trong một vài năm có biến động tài chính.
Giả sử bạn muốn phân tích yếu tố ảnh hưởng đến ROE (hiệu quả sinh lời vốn chủ).
Ta chọn các biến độc lập có ý nghĩa tài chính: tong_tai_san, no_dai_han, loi_nhuan_sau_thue, roa
library(car)
library(lmtest)
library(sandwich)
model_roe <- lm(roe ~ tong_tai_san + no_dai_han + loi_nhuan_sau_thue + roa, data = BCTC_NVL)
summary(model_roe)
##
## Call:
## lm(formula = roe ~ tong_tai_san + no_dai_han + loi_nhuan_sau_thue +
## roa, data = BCTC_NVL)
##
## Residuals:
## 1 2 3 4 5 6 7 8 9 10
## 0.1813 -0.9408 1.7952 -0.6098 -0.7293 0.8495 -1.1408 0.7295 0.1340 -0.2689
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.066e+00 1.926e+00 2.111 0.08850 .
## tong_tai_san -4.081e-14 2.910e-14 -1.402 0.21979
## no_dai_han 4.619e-14 3.074e-14 1.503 0.19327
## loi_nhuan_sau_thue 1.287e-12 5.329e-13 2.416 0.06042 .
## roa 2.333e+00 4.189e-01 5.570 0.00257 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.24 on 5 degrees of freedom
## Multiple R-squared: 0.9909, Adjusted R-squared: 0.9837
## F-statistic: 136.7 on 4 and 5 DF, p-value: 2.72e-05
Giải thích:
(4) Xây dựng mô hình hồi quy tuyến tính với ROE là biến phụ thuộc và các biến tài chính là biến độc lập.
(5) Dùng summary() để xem ý nghĩa thống
kê của mô hình.
Nhận xét: Mô hình hồi quy cho thấy ROA là biến có ảnh hưởng mạnh và có ý nghĩa nhất đến ROE (hệ số = 2.33, p < 0.01). Biến lợi nhuận sau thuế có tác động cùng chiều và gần đạt ý nghĩa thống kê (p ≈ 0.06), trong khi tổng tài sản và nợ dài hạn không có tác động rõ ràng. Mô hình có R² = 0.99, chứng tỏ độ phù hợp rất cao, giải thích gần như toàn bộ biến động của ROE.
vif(model_roe)
## tong_tai_san no_dai_han loi_nhuan_sau_thue roa
## 42.162503 12.622189 44.435827 6.300269
Giải thích:
(1) kiểm tra hiện tượng đa cộng tuyến giữa các biến độc lập trong mô hình hồi quy ROE.
Nhận xét:
Kết quả cho thấy các biến “Tổng tài sản”, “Nợ dài hạn” và “Lợi nhuận sau thuế” có giá trị VIF > 10, thể hiện hiện tượng đa cộng tuyến nghiêm trọng giữa các biến quy mô tài chính.
Ngược lại, ROA (VIF = 6.3) vẫn nằm trong ngưỡng chấp nhận được.
Điều này cho thấy mối quan hệ chặt chẽ giữa các biến quy mô (tài sản,
nợ, lợi nhuận) có thể làm sai lệch ước lượng hệ số trong mô hình hồi
quy.
bptest(model_roe)
##
## studentized Breusch-Pagan test
##
## data: model_roe
## BP = 3.2669, df = 4, p-value = 0.5142
Giải thích: **(1) kiểm định phương sai thay đổi trong mô hình hồi quy.
Nhận xét:
Kết quả kiểm định Breusch–Pagan cho thấy p-value = 0.5142 > 0.05, nên không có hiện tượng phương sai thay đổi.
dwtest(model_roe)
##
## Durbin-Watson test
##
## data: model_roe
## DW = 3.2525, p-value = 0.7676
## alternative hypothesis: true autocorrelation is greater than 0
Giải thích: (1) kiểm định Durbin–Watson, nhằm phát hiện tự tương quan của sai số trong mô hình.
Nhận xét: Từ thông kê: p-value = 0.7676 > 0.05 cho thấy phần dư của mô hình không có tự tương quan → mô hình đạt giả định độc lập phần dư.
BCTC_NVL_group <- BCTC_NVL %>%
group_by(giai_doan) %>%
summarise(
"Lợi nhuận TB" = mean(loi_nhuan_sau_thue),
"Tổng tài sản TB" = mean(tong_tai_san),
"Vốn chủ sở hữu TB" = mean(von_chu_so_huu),
"Nợ dài hạn TB" = mean(no_dai_han))
kable(
BCTC_NVL_group,
caption = "**Trung bình các chỉ tiêu tài chính của Công ty NVL theo giai đoạn Trước và Sau Covid**",
align = "c")
| giai_doan | Lợi nhuận TB | Tổng tài sản TB | Vốn chủ sở hữu TB | Nợ dài hạn TB |
|---|---|---|---|---|
| Sau Covid | 1.185765e+13 | 1.955581e+14 | 3.916299e+13 | 9.437325e+13 |
| Trước Covid | 2.629433e+12 | 4.561916e+13 | 1.246465e+13 | 1.340615e+13 |
Giải thích:
(1)–>(4) Nhóm dữ liệu theo giai đoạn và tính trung bình các chỉ tiêu tài chính chính.
(5) Dùng kable() để hiển thị bảng so
sánh trung bình giữa hai giai đoạn Trước và Sau
Covid.
qs_taisan <- quantile(BCTC_NVL$tong_tai_san, probs = c(1/3, 2/3), na.rm = TRUE)
qs_taisan
## 33.33333% 66.66667%
## 6.991221e+13 2.018335e+14
BCTC_NVL <- BCTC_NVL %>%
mutate(nhom_tai_san = case_when(
tong_tai_san <= qs_taisan[1] ~ "Thấp",
tong_tai_san <= qs_taisan[2] ~ "Trung bình",
TRUE ~ "Cao"))
BCTC_NVL %>%
count(nhom_tai_san) %>%
kable(caption = "**Số lượng năm quan sát theo nhóm quy mô tài sản**", align = "c")
| nhom_tai_san | n |
|---|---|
| Cao | 3 |
| Thấp | 4 |
| Trung bình | 3 |
Giải thích:
(1) Tính các phân vị 1/3 và 2/3 của biến tổng tài sản, làm cơ sở phân nhóm quy mô.
(2)–>(3) Dùng mutate() và
case_when() để tạo biến mới nhom_tai_san,
chia doanh nghiệp thành ba nhóm: Thấp, Trung bình và
Cao.
(4)–>(7) đếm số quan sát trong từng nhóm và
kable() để hiển thị bảng kết quả phân tổ gọn, rõ ràng trong
báo cáo.
qs_no <- quantile(BCTC_NVL$ty_le_no, probs = c(1/3, 2/3), na.rm = TRUE)
qs_no
## 33.33333% 66.66667%
## 72.81 79.60
BCTC_NVL <- BCTC_NVL %>%
mutate(nhom_no = case_when(
ty_le_no <= qs_no[1] ~ "Thấp",
ty_le_no <= qs_no[2] ~ "Trung bình",
TRUE ~ "Cao"))
BCTC_NVL %>%
count(nhom_no) %>%
kable(caption = "**Số lượng năm quan sát theo nhóm tỷ lệ nợ**", align = "c")
| nhom_no | n |
|---|---|
| Cao | 3 |
| Thấp | 4 |
| Trung bình | 3 |
Giải thích:
(1) Tính các phân vị 1/3 và 2/3 của biến tỷ lệ nợ, dùng để xác định ngưỡng phân nhóm.
(2)–>(3) Tạo biến mới nhom_no
bằng mutate() và case_when(), chia dữ liệu
thành ba nhóm: Thấp, Trung bình và Cao theo
tỷ lệ nợ.
(4)–>(7) Dùng count() để đếm
số năm quan sát trong từng nhóm và kable() để hiển
thị bảng kết quả phân tổ rõ ràng trong báo cáo.
Nhận xét Trong giai đoạn 2015–2024, Công ty NVL có 3 năm thuộc nhóm tỷ lệ nợ cao, 3 năm trung bình và 4 năm thấp.
qs_roe <- quantile(BCTC_NVL$roe, probs = c(1/3, 2/3), na.rm = TRUE)
BCTC_NVL <- BCTC_NVL %>%
mutate(Nhom_ROE = case_when(
roe <= qs_roe[1] ~ "Thấp",
roe <= qs_roe[2] ~ "Trung bình",
TRUE ~ "Cao"))
BCTC_NVL %>% count(Nhom_ROE) %>%
kable(caption = "**Phân loại theo nhóm ROE**", align = "c")
| Nhom_ROE | n |
|---|---|
| Cao | 3 |
| Thấp | 4 |
| Trung bình | 3 |
Giải thích:
(1)–>(3) Tạo biến mới Nhom_ROE
bằng mutate() và case_when(), chia doanh
nghiệp thành ba nhóm: Thấp, Trung bình và Cao
theo giá trị ROE.
(4)–>(7) Dùng count() để đếm
số quan sát trong từng nhóm và kable() để
hiển thị bảng phân loại ROE (3 tổ) rõ ràng trong báo
cáo.
Nhận xét: Trong giai đoạn 2015–2024, Công ty NVL có 3 năm đạt ROE cao, 3 năm trung bình và 4 năm thấp.
BCTC_NVL <- BCTC_NVL %>%
mutate(ty_trong_von_chu = von_chu_so_huu / tong_tai_san * 100,
nhom_cau_truc_von = ifelse(ty_trong_von_chu > 25, "Tự chủ cao", "Tự chủ thấp"))
BCTC_NVL %>% count(nhom_cau_truc_von) %>%
kable(caption = "Phân loại theo cấu trúc vốn", align = "c")
| nhom_cau_truc_von | n |
|---|---|
| Tự chủ cao | 4 |
| Tự chủ thấp | 6 |
Giải thích:
(1-3) Tạo biến ty_trong_von_chu và phân loại cấu trúc vốn thành Tự chủ cao hoặc Tự chủ thấp theo ngưỡng 25 phần trăm.
(4-6) Dùng count() và
kable() để hiển thị số quan sát của từng
nhóm.
Nhận xét: Trong giai đoạn 2015–2024, Công ty NVL có 6 năm thuộc nhóm “tự chủ thấp” và chỉ 4 năm đạt mức “tự chủ cao”.
ggplot(BCTC_NVL, aes(x = loi_nhuan_sau_thue)) +
geom_histogram(fill = "#64B5F6", color = "black", bins = 10, alpha = 0.8) +
geom_density(aes(y = ..count.. * 10), color = "red", linewidth = 1.2) +
labs(
title = "Biểu đồ phân phối Lợi nhuận sau thuế của Công ty NVL (2015–2024)",
x = "Lợi nhuận sau thuế (VND)",
y = "Tần suất (số năm)") +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Giải thích:
(1)–>(3) Dùng geom_histogram() để vẽ
biểu đồ tần suất và geom_density() để thêm đường mật độ,
thể hiện dạng phân phối của lợi nhuận sau thuế.
(4)–>(8) Gán tiêu đề, nhãn trục và căn giữa tiêu
đề bằng theme(), giúp biểu đồ rõ ràng và mang tính học
thuật.
Nhận xét: Biểu đồ cho thấy phân phối lợi nhuận sau thuế của Công ty NVL trong giai đoạn 2015–2024 không đồng đều. Phần lớn các năm có lợi nhuận ở mức rất thấp hoặc rất cao, thể hiện biến động mạnh về hiệu quả kinh doanh. Đường mật độ (màu đỏ) nằm sát trục hoành cho thấy phân phối bị lệch phải, tức là chỉ có một số năm lợi nhuận tăng đột biến trong khi đa số năm đạt mức thấp hơn nhiều.
ggplot(BCTC_NVL, aes(x = factor(nam), y = roe)) +
geom_col(fill = "#5DADE2", color = "black", width = 0.6) +
geom_text(aes(label = round(roe, 1)), vjust = -0.4, size = 4) +
geom_hline(yintercept = mean(BCTC_NVL$roe, na.rm = TRUE),
color = "darkgreen", linetype = "dashed", linewidth = 1) +
labs(title = "So sánh ROE giữa các năm của Công ty NVL",
x = "Năm", y = "ROE (%)") +
theme_minimal(base_family = "TimesVN") +
theme(
plot.title = element_text(size = 17, face = "bold", hjust = 0.5),
axis.title = element_text(size = 13, face = "bold"),
axis.text = element_text(size = 11))
Giải thích:
(1)–>(5) Vẽ biểu đồ cột (column
chart) thể hiện ROE qua các năm bằng
geom_col(), thêm nhãn giá trị bằng geom_text()
và đường trung bình ROE bằng geom_hline().
(6)–>(9) Dùng labs() để đặt tiêu đề,
nhãn trục và theme_minimal() để tạo bố cục đơn giản, căn
giữa tiêu đề và định dạng chữ rõ ràng, mang tính học thuật.
Nhận xét: ROE của NVL tăng mạnh giai đoạn 2015–2020, đạt đỉnh 37,7 phần trăm năm 2020, sau đó giảm nhẹ nhưng vẫn duy trì trên mức trung bình (26 phần trăm), phản ánh hiệu quả sinh lời ổn định và quản trị vốn tốt.
roe_roa_long <- BCTC_NVL %>%
select(nam, roa, roe) %>%
pivot_longer(cols = c(roa, roe), names_to = "Chi_tieu", values_to = "Gia_tri")
ggplot(roe_roa_long, aes(x = nam, y = Gia_tri, color = Chi_tieu)) +
geom_line(linewidth = 1.3) +
geom_point(size = 4) +
geom_text(aes(label = round(Gia_tri, 1)), vjust = -0.6, size = 4,
fontface = "bold", color = "black", show.legend = FALSE) +
geom_hline(yintercept = mean(BCTC_NVL$roa), color = "#F39C12", linetype = "dotted", linewidth = 1) +
geom_hline(yintercept = mean(BCTC_NVL$roe), color = "#2E86C1", linetype = "dashed", linewidth = 1) +
scale_color_manual(values = c("roa" = "#F39C12", "roe" = "#2E86C1"),
labels = c("ROA", "ROE")) +
scale_x_continuous(breaks = BCTC_NVL$nam) +
expand_limits(y = max(roe_roa_long$Gia_tri) * 1.1) +
labs(title = "Biến động ROA và ROE của Công ty NVL qua các năm",
subtitle = "So sánh hiệu quả sinh lời trên tài sản (ROA) và vốn chủ sở hữu (ROE)",
x = "Năm", y = "Tỷ suất (%)", color = "Chỉ tiêu",
caption = "Nguồn: Báo cáo tài chính hợp nhất NVL (2015–2024)") +
theme_minimal(base_family = "Times New Roman") +
theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 13, hjust = 0.5, color = "gray35"),
axis.title = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
legend.position = "bottom")
Giải thích:
(1)–>(4) Chuyển dữ liệu từ dạng rộng sang dài
bằng pivot_longer() để biểu đồ có thể hiển thị đồng thời
ROA và ROE theo năm.
(5)–>(10) Dùng geom_line() và
geom_point() để vẽ biểu đồ đường, thêm nhãn giá trị và hai
đường trung bình (ROA và ROE) để so sánh xu hướng.
(11)–>(12) Dùng scale_color_manual()
để tùy chỉnh màu sắc từng chỉ tiêu và labs() để đặt tiêu
đề, nhãn trục, chú thích rõ ràng.
(13)–>(16) Dùng theme() để căn giữa
tiêu đề, định dạng chữ và hiển thị chú giải dưới biểu đồ, giúp trình bày
chuyên nghiệp, dễ đọc.
Nhận xét: Biểu đồ thể hiện ROA và ROE của NVL tăng mạnh giai đoạn 2015–2019, đạt đỉnh năm 2020 (ROE ≈ 37.7 phần trăm, ROA ≈ 8.3 phần trăm), sau đó giảm nhẹ và ổn định quanh mức cao trong các năm gần đây. Điều này cho thấy hiệu quả sinh lời của doanh nghiệp cải thiện rõ rệt so với giai đoạn đầu, đồng thời duy trì khả năng sinh lợi ổn định sau COVID-19.
BCTC_NVL %>%
count(nhom_cau_truc_von) %>%
mutate(ty_le = n / sum(n)) %>%
ggplot(aes(x = "", y = ty_le, fill = nhom_cau_truc_von)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
geom_text(aes(label = percent(ty_le, accuracy = 0.1)),
position = position_stack(vjust = 0.5),
family = "Times New Roman",
size = 5,
color = "black") +
scale_fill_manual(values = c("#F4D03F", "#3498DB")) +
labs(
title = "Tỷ trọng nhóm cấu trúc vốn",
caption = "Nguồn: Tổng hợp từ báo cáo tài chính của NVL",
fill = "Nhóm cấu trúc vốn") +
theme_void(base_family = "Times New Roman") +
theme(
plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
plot.subtitle = element_text(size = 13, hjust = 0.5, color = "gray30"),
plot.caption = element_text(size = 11, color = "gray40", hjust = 1),
legend.title = element_text(face = "bold"),
legend.text = element_text(size = 12))
Giải thích:
(1)–>(3) Tính số lượng từng nhóm nhom_cau_truc_von và tỷ lệ phần trăm (ty_le).
(4) Khởi tạo biểu đồ, vẽ cột và chuyển sang dạng tròn bằng coord_polar().
(5) Thêm nhãn phần trăm vào giữa từng lát, chỉnh font và kích thước chữ.
(7) Tùy chỉnh màu, tiêu đề, chú thích và nguồn dữ liệu.
(10)–>(13) Áp dụng theme tối giản, căn giữa tiêu đề và định dạng lại phần chú thích.
Nhận xét: Biểu đồ cho thấy 60 phần trăm giai đoạn hoạt động của NVL thuộc nhóm “tự chủ tài chính thấp”, trong khi chỉ 40 phần trăm đạt mức tự chủ cao.
ggplot(BCTC_NVL, aes(x = tong_tai_san, y = loi_nhuan_sau_thue)) +
geom_point(color = "#1ABC9C", size = 4, alpha = 0.8) +
geom_smooth(method = "lm", se = FALSE, color = "#E74C3C", linewidth = 1) +
geom_text(aes(label = nam), vjust = -0.8, size = 4, color = "black") +
labs(title = "Quan hệ giữa Tổng tài sản và Lợi nhuận sau thuế của NVL",
subtitle = "Dữ liệu 2015–2024 | Xu hướng đồng biến giữa quy mô tài sản và lợi nhuận",
x = "Tổng tài sản (VND)",
y = "Lợi nhuận sau thuế (VND)") +
theme_minimal(base_family = "TimesVN") +
theme(
plot.title = element_text(size = 17, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 12, color = "gray40", hjust = 0.5),
axis.title = element_text(size = 13, face = "bold"),
axis.text = element_text(size = 11))
Giải thích:
(1) Thiết lập trục x = tổng tài sản, y = lợi nhuận sau thuế.
(2) Vẽ điểm dữ liệu màu xanh ngọc, kích thước 4, alpha = 0.8.
(3) Thêm đường hồi quy tuyến tính màu đỏ, không hiển thị sai số.
(4) Hiển thị nhãn năm trên từng điểm.
(5–8) Đặt tiêu đề, phụ đề và tên trục với đơn vị VND.
(9–14) Dùng giao diện tối giản, căn giữa tiêu đề, chỉnh cỡ và kiểu chữ.
Nhận xét: Biểu đồ cho thấy mối quan hệ tuyến tính dương rõ rệt giữa tổng tài sản và lợi nhuận sau thuế của NVL.
Khi quy mô tài sản tăng, lợi nhuận cũng tăng tương ứng, thể hiện hiệu quả sử dụng vốn và khả năng mở rộng sinh lời tốt.
ggplot(BCTC_NVL, aes(x = nam, y = roe, color = nhom_no, group = nhom_no)) +
geom_line(linewidth = 1.3) + geom_point(size = 3.5) +
geom_text(aes(label = round(roe, 1)), vjust = -1.1, size = 4, fontface = "bold", show.legend = FALSE) +
geom_hline(yintercept = mean(BCTC_NVL$roe, na.rm = TRUE),
linetype = "dotted", color = "darkgreen", linewidth = 1) +
scale_color_manual(values = c("Thấp" = "#F5B041", "Trung bình" = "#5DADE2", "Cao" = "#AF7AC5")) +
labs(
title = "Biểu đồ ROE theo nhóm tỷ lệ nợ của Công ty NVL",
subtitle = "So sánh xu hướng sinh lời trên vốn chủ giữa các nhóm nợ (2015–2024)",
x = "Năm", y = "ROE (%)", color = "Nhóm tỷ lệ nợ",
caption = "Nguồn: Báo cáo tài chính hợp nhất NVL (2015–2024)"
) +
expand_limits(y = max(BCTC_NVL$roe, na.rm = TRUE) + 5) +
theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 13, hjust = 0.5, color = "gray35"),
axis.title = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
legend.title = element_text(size = 13, face = "bold"),
legend.text = element_text(size = 12),
legend.position = "bottom")
Giải thích:
(1) Thiết lập trục x = năm, y = ROE, phân nhóm màu và đường theo nhóm nợ.
(2) Vẽ điểm dữ liệu, thêm nhãn ROE, in đậm, căn trên điểm.
(3) Thêm đường trung bình ROE toàn kỳ (màu xanh lá, nét chấm).
(4) Gán màu riêng cho ba nhóm nợ: Thấp, Trung bình, Cao.
(5–7) Đặt tiêu đề, phụ đề, tên trục, chú thích và nguồn dữ liệu.
(8–12) Mở rộng trục y, căn giữa tiêu đề, định dạng chữ và đặt legend phía dưới.
Nhận xét: Biểu đồ thể hiện xu hướng ROE thay đổi theo nhóm tỷ lệ nợ của NVL trong giai đoạn 2015–2024. Giai đoạn 2015–2020 (nhóm nợ thấp và trung bình) cho thấy ROE tăng mạnh, đạt đỉnh năm 2020 (37,7 phần trăm). Từ 2021 trở đi, khi doanh nghiệp chuyển sang nhóm nợ cao, ROE ổn định quanh mức 28–30 phần trăm.
BCTC_NVL <- BCTC_NVL %>%
arrange(nam) %>%
mutate(tangtruong = round((loi_nhuan_sau_thue / lag(loi_nhuan_sau_thue) - 1) * 100, 2))
ggplot(BCTC_NVL, aes(x = nam, y = tangtruong)) +
geom_area(fill = "#FADBD8", alpha = 0.4) + geom_line(color = "#E74C3C", linewidth = 1.3) +
geom_point(aes(size = abs(tangtruong)), color = "#C0392B", alpha = 0.8) +
geom_text(aes(label = paste0(round(tangtruong, 1), "%")),
vjust = -0.8, size = 3.5, fontface = "bold") +
geom_hline(yintercept = 0, color = "darkgreen", linetype = "dashed", linewidth = 1) +
geom_smooth(method = "loess", se = FALSE, color = "#1F618D", linetype = "dotted", linewidth = 1.1) +
scale_x_continuous(breaks = BCTC_NVL$nam) +
labs(
title = "Tốc độ tăng trưởng lợi nhuận sau thuế của Công ty NVL theo năm",
subtitle = "Giai đoạn 2015–2024, giá trị dương biểu thị tăng trưởng lợi nhuận",
x = "Năm",
y = "Tốc độ tăng trưởng (%)") +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
plot.subtitle = element_text(size = 11, hjust = 0.5, color = "gray30"),
axis.title = element_text(face = "bold"),
axis.text = element_text(size = 10),
panel.grid.minor = element_blank())
Giải thích:
(1–2) Sắp xếp dữ liệu theo năm tăng dần.
(3–4) Tạo biến tăng trưởng (%) = [(LNST hiện tại / LNST năm trước) – 1] × 100, làm tròn 2 chữ số.
(5) Vẽ vùng tô thể hiện xu hướng tăng trưởng qua các năm.
(6–8) Thêm đường, điểm, và nhãn phần trăm cho từng năm.
(9) Thêm đường tham chiếu tại mức 0% để phân biệt tăng/giảm.
(10) Vẽ đường xu hướng mượt (loess) dạng chấm.
(11–16) Đặt tiêu đề, phụ đề, tên trục, chỉnh font, căn giữa và ẩn lưới phụ.
Nhận xét: Doanh nghiệp đạt đỉnh tăng trưởng năm 2017 (205,2 phần trăm), phản ánh giai đoạn mở rộng mạnh mẽ. Từ sau 2018, tốc độ tăng trưởng giảm dần và có biến động âm nhẹ năm 2021–2024, cho thấy hiệu quả lợi nhuận ổn định hơn nhưng chậm lại, đặc biệt bị ảnh hưởng bởi bối cảnh thị trường và hậu COVID-19.
ggplot(BCTC_NVL, aes(x = nam, y = roa, color = nhom_cau_truc_von, group = nhom_cau_truc_von)) +
geom_line(linewidth = 1.3) +
geom_point(size = 3.5) +
geom_text(aes(label = round(roa, 1)), vjust = -0.6, size = 4, fontface = "bold") +
geom_smooth(method = "lm", se = FALSE, linetype = "dashed", linewidth = 1, alpha = 0.5) +
geom_hline(yintercept = mean(BCTC_NVL$roa, na.rm = TRUE),
linetype = "dotted", color = "darkgreen", linewidth = 1) +
annotate("text", x = 2020, y = mean(BCTC_NVL$roa) + 1.2,
label = "Mức trung bình ROA toàn kỳ", color = "darkgreen", size = 4, fontface = "italic") +
scale_color_manual(values = c("Tự chủ cao" = "#2874A6", "Tự chủ thấp" = "#E67E22")) +
labs(
title = "ROA theo nhóm cấu trúc vốn",
subtitle = "So sánh tỷ suất sinh lời trên tài sản (ROA) giữa các nhóm doanh nghiệp theo cấu trúc vốn",
x = "Năm",
y = "ROA (%)",
color = "Nhóm cấu trúc vốn",
caption = "Nguồn: Báo cáo tài chính hợp nhất NVL (2015–2024)") +
theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 13, hjust = 0.5, color = "gray35"),
axis.title = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
legend.title = element_text(size = 13, face = "bold"),
legend.text = element_text(size = 12),
legend.position = "bottom")
Giải thích:
(1) Thiết lập trục x = năm, y = ROA, nhóm theo nhóm cấu trúc vốn và tô màu tương ứng.
(2) Vẽ đường và điểm dữ liệu ROA qua các năm, thêm nhãn giá trị.
(3–4) Thêm đường xu hướng hồi quy tuyến tính (dạng chấm).
(5–6) Thêm đường trung bình ROA toàn kỳ (màu xanh lá, nét chấm) và chú thích.
(8) Gán màu cho hai nhóm: Tự chủ cao và Tự chủ thấp.
(9–11) Đặt tiêu đề, phụ đề, nhãn trục và chú thích nguồn dữ liệu.
(12–15) Căn giữa tiêu đề, định dạng chữ, điều chỉnh kích thước và đặt legend phía dưới.
Nhận xét: Nhóm doanh nghiệp có mức tự chủ cao (màu xanh) đạt ROA cao hơn đáng kể, đặc biệt giai đoạn 2017–2019, thể hiện hiệu quả sử dụng tài sản vượt trội. Trong khi đó, nhóm tự chủ thấp (màu cam) có ROA ổn định hơn nhưng duy trì dưới mức trung bình toàn kỳ (đường xanh lục). Đường xu hướng hồi quy tuyến tính cho thấy ROA của cả hai nhóm đều tăng nhẹ về dài hạn, song chênh lệch giữa hai nhóm vẫn rõ rệt.
BCTC_NVL %>%
group_by(nhom_tai_san) %>%
summarise(loi_nhuan_tb = mean(loi_nhuan_sau_thue, na.rm = TRUE) / 1e12) %>%
ggplot(aes(x = reorder(nhom_tai_san, loi_nhuan_tb),
y = loi_nhuan_tb, fill = nhom_tai_san)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = round(loi_nhuan_tb, 2)),
hjust = -0.2, size = 4, fontface = "bold") +
coord_flip() +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Lợi nhuận trung bình theo nhóm quy mô tài sản",
x = "Nhóm tài sản",
y = "Lợi nhuận (nghìn tỷ)") +
theme(
plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
axis.title = element_text(face = "bold", size = 13),
axis.text = element_text(size = 12),
panel.grid.minor = element_blank())
Giải thích:
(1–2) Nhóm dữ liệu theo nhóm tài sản.
(3) Tính lợi nhuận sau thuế trung bình (đơn vị nghìn tỷ, chia (10^{12})).
(4–6) Vẽ biểu đồ cột ngang, thêm nhãn số trên cột, tô màu theo nhóm tài sản.
(7–10) Đặt tiêu đề, nhãn trục, định dạng chữ đậm, căn giữa và ẩn lưới phụ.
Nhận xét: Nhóm doanh nghiệp có quy mô tài sản lớn thường đạt lợi nhuận trung bình cao hơn rõ rệt so với nhóm nhỏ, cho thấy mối quan hệ tích cực giữa quy mô tài sản và hiệu quả sinh lời.
BCTC_NVL_long <- BCTC_NVL %>%
select(nam, tong_tai_san, no_dai_han) %>%
pivot_longer(-nam, names_to="Chi_tieu", values_to="Gia_tri")
ggplot(BCTC_NVL_long, aes(x=nam, y=Gia_tri/1e12, color=Chi_tieu)) +
geom_line(size=1.2) + geom_point(size=3) +
labs(title="Biến động Tài sản và Nợ dài hạn", x="Năm", y="Giá trị (nghìn tỷ)") +
theme_minimal()
Giải thích:
(1–2) Chọn các cột năm, tổng tài sản và nợ dài hạn từ dữ liệu gốc.
(3) Dùng pivot_longer() để chuyển dữ
liệu sang dạng dài, gom hai chỉ tiêu vào một cột.
(4) Vẽ biểu đồ đường so sánh giá trị (nghìn tỷ) của hai chỉ tiêu theo năm.
(5–6) Thêm điểm dữ liệu, đặt tiêu đề, nhãn trục và dùng giao diện tối giản.
Nhận xét: Biểu đồ thể hiện biến động Tổng tài sản và Nợ dài hạn của NVL giai đoạn 2015–2024. Cả hai chỉ tiêu tăng mạnh từ 2015 đến 2021. Sau 2021, nợ dài hạn giảm rõ rệt, trong khi tổng tài sản duy trì ổn định ở mức cao.
ggplot(BCTC_NVL, aes(x=roa, y=roe)) +
geom_point(size=3, color="#2E86C1") +
geom_text(aes(label = nam), vjust = -0.7, size = 4) +
geom_smooth(method="lm", color="red") +
labs(title="Quan hệ giữa ROA và ROE", x="ROA (%)", y="ROE (%)") +
theme_minimal()
Giải thích:
(1) Thiết lập trục x = ROA, y = ROE, vẽ điểm dữ liệu màu xanh.
(2) Thêm nhãn năm cho từng điểm, căn trên vị trí điểm.
(3) Vẽ đường hồi quy tuyến tính màu đỏ thể hiện xu hướng.
(4) Đặt tiêu đề, tên trục và áp dụng giao diện tối giản.
Nhận xét: Biểu đồ cho thấy mối quan hệ tuyến tính
thuận giữa ROA và ROE của NVL giai đoạn 2015–2024. Khi ROA tăng, ROE
cũng tăng tương ứng, phản ánh hiệu quả sử dụng tài sản tác động trực
tiếp đến lợi nhuận trên vốn chủ sở hữu.
Đường hồi quy màu đỏ khẳng định xu hướng này, cho thấy doanh nghiệp vận
hành hiệu quả hơn khi tài sản được khai thác tốt.
corr_matrix <- cor(BCTC_NVL %>%
select(roa, roe, tong_tai_san, von_chu_so_huu,
no_dai_han, loi_nhuan_sau_thue),
use = "complete.obs")
ggcorrplot(corr_matrix,
lab = TRUE,
type = "lower",
colors = c("#E57373", "white", "#64B5F6")) +
ggtitle("Biểu đồ ma trận tương quan giữa các biến tài chính của NVL") +
theme_minimal(base_family = "TimesVN") +
theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5)) +
scale_x_discrete(position = "top") +
geom_hline(yintercept = 0.5, color = "gray80", linewidth = 0.3) +
geom_vline(xintercept = 0.5, color = "gray80", linewidth = 0.3)
Giải thích:
(1–2) Tính ma trận tương quan giữa các biến tài chính chính của NVL, bỏ giá trị thiếu.
(3–4) Dùng ggcorrplot() để trực quan
hóa ma trận, hiển thị nhãn giá trị, chỉ vẽ phần tam giác dưới.
(5–6) Đặt tiêu đề, chọn font TimesVN, căn giữa tiêu đề.
(7–9) Thêm đường kẻ ngang và dọc nhạt để tăng khả năng quan sát ô tương quan.
Nhận xét: Biểu đồ ma trận cho thấy các biến tài chính của NVL có mức tương quan rất cao.Tổng tài sản, vốn chủ sở hữu, nợ dài hạn và lợi nhuận sau thuế có hệ số tương quan > 0.9, thể hiện sự đồng biến chặt chẽ giữa quy mô tài chính và hiệu quả hoạt động. ROA và ROE có tương quan 0.88, phản ánh mối quan hệ tuyến tính mạnh giữa hiệu quả sử dụng tài sản và hiệu quả sinh lời trên vốn.
ggplot(BCTC_NVL, aes(x = factor(nam))) +
geom_bar(aes(y = no_dai_han/1e12, fill = "Nợ dài hạn"), stat = "identity") +
geom_bar(aes(y = von_chu_so_huu/1e12, fill = "Vốn chủ sở hữu"), stat = "identity", position = "stack") +
scale_fill_manual(values = c("Nợ dài hạn" = "#E74C3C", "Vốn chủ sở hữu" = "#3498DB")) +
labs(title = "Cấu trúc tài chính của NVL (cột chồng)",
x = "Năm", y = "Giá trị (nghìn tỷ)", fill = "Chỉ tiêu") +
theme_minimal(base_family = "arial") +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
Giải thích:
(1–2) Thiết lập trục x = năm, vẽ cột giá trị nợ dài hạn (đơn vị nghìn tỷ).
(3) Thêm cột vốn chủ sở hữu, chồng lên theo từng năm (position = “stack”).
(4) Gán màu riêng cho hai thành phần: đỏ cho Nợ dài hạn, xanh cho Vốn chủ sở hữu.
(5) Đặt tiêu đề, nhãn trục và chú thích.
(6) Dùng giao diện tối giản và căn giữa tiêu đề.
Nhận xét: Biểu đồ cho thấy cấu trúc tài chính của NVL giai đoạn 2015–2024 có xu hướng tăng trưởng mạnh cả về nợ dài hạn và vốn chủ sở hữu. Từ 2015 đến 2021, quy mô vốn tăng nhanh, thể hiện quá trình mở rộng hoạt động đầu tư và huy động vốn vay. Năm 2022 đạt đỉnh, trong đó nợ dài hạn chiếm tỷ trọng lớn, phản ánh mức độ đòn bẩy tài chính cao. Từ 2023 trở đi, nợ giảm nhẹ nhưng vốn chủ sở hữu vẫn tăng.
ggplot(BCTC_NVL, aes(x = roe)) +
geom_density(fill = "#AED6F1", alpha = 0.6, color = "darkblue") +
geom_vline(aes(xintercept = mean(roe, na.rm = TRUE)),
color = "red", linetype = "dashed", linewidth = 1) +
geom_vline(aes(xintercept = median(roe, na.rm = TRUE)),
color = "darkgreen", linetype = "dotted", linewidth = 1) +
labs(title = "Phân bố ROE của Công ty NVL (2015–2024)",
x = "ROE (%)", y = "Mật độ") +
theme_minimal(base_family = "TimesVN")
Giải thích:
(1) Vẽ biểu đồ mật độ của ROE, tô màu xanh nhạt, viền xanh đậm.
(2) Thêm đường trung bình ROE (đỏ, nét đứt).
(3) Thêm đường trung vị ROE (xanh lá, nét chấm).
(4–5) Đặt tiêu đề và nhãn trục, dùng giao diện tối giản với font TimesVN.
Nhận xét: Biểu đồ mật độ cho thấy ROE của Công ty NVL giai đoạn 2015–2024 phân bố lệch phải nhẹ, tập trung quanh mức 25–30 phần trăm, đây là vùng có mật độ cao nhất. Đường đứt màu đỏ (trung bình) thấp hơn đường xanh (trung vị) → phân bố có đuôi phải dài hơn, phản ánh một vài năm có ROE cao bất thường (như 2019–2020). Nhìn chung, hiệu quả sinh lời trên vốn chủ của NVL duy trì ổn định ở mức cao, dù có dao động nhẹ qua các năm.
roa_summary <- BCTC_NVL %>%
group_by(giai_doan) %>%
summarise(mean_roa = mean(roa, na.rm = TRUE),
sd_roa = sd(roa, na.rm = TRUE))
ggplot(roa_summary, aes(x = giai_doan, y = mean_roa, fill = giai_doan)) +
geom_col(width = 0.6, color = "black", alpha = 0.7) +
geom_errorbar(aes(ymin = mean_roa - sd_roa, ymax = mean_roa + sd_roa),
width = 0.15, linewidth = 0.8) +
geom_text(aes(label = round(mean_roa, 2)), vjust = -0.6, size = 4) +
labs(title = "So sánh ROA trước và sau Covid",
x = "Giai đoạn", y = "ROA trung bình (%)") +
theme_minimal(base_family = "TimesVN")
Giải thích:
(1–3) Nhóm dữ liệu theo giai đoạn, tính ROA trung bình và độ lệch chuẩn cho từng nhóm.
(4) Vẽ biểu đồ cột thể hiện ROA trung bình, tô màu theo giai đoạn.
(5–6) Thêm thanh sai số (error bar) ±1 độ lệch chuẩn quanh giá trị trung bình.
(7) Hiển thị nhãn giá trị ROA trên cột.
(8) Đặt tiêu đề, tên trục và dùng giao diện tối giản.
Nhận xét Biểu đồ thể hiện ROA trung bình của Công ty NVL tăng nhẹ sau giai đoạn Covid (từ khoảng 4,32 lên 6,59 phần trăm). Tuy nhiên, độ lệch chuẩn lớn (thanh sai số dài) cho thấy biến động hiệu quả sử dụng tài sản giữa các năm còn cao, phản ánh quá trình phục hồi chưa thật sự ổn định.
ggplot(BCTC_NVL, aes(x = nam, y = roe)) +
geom_line(color = "#3498DB", linewidth = 1.3) +
geom_point(size = 3, color = "#1F618D") + geom_text(aes(label = round(roe, 1)), vjust = -0.7, size = 4) +
geom_smooth(method = "loess", color = "red", se = FALSE, linetype = "dashed") +
labs(title = "Xu hướng dài hạn của ROE của Công ty NVL (2015–2024)",
x = "Năm", y = "ROE (%)") +
scale_x_continuous(breaks = BCTC_NVL$nam) + theme_minimal(base_family = "TimesVN") +
theme(
plot.title = element_text(size = 17, face = "bold", hjust = 0.5),
axis.title = element_text(size = 13, face = "bold"),
axis.text.x = element_text(size = 11, angle = 0, vjust = 0.5))
Giải thích:
(1) Thiết lập trục x = năm, y = ROE, vẽ đường xu hướng chính màu xanh dương.
(2) Thêm điểm dữ liệu và nhãn giá trị ROE cho từng năm.
(3) Thêm đường mượt (loess) màu đỏ, dạng gạch đứt để làm nổi bật xu hướng.
(4–5) Đặt tiêu đề, nhãn trục và chia mốc trục x theo năm.
(6–7) Dùng giao diện tối giản, căn giữa tiêu đề và định dạng kích thước chữ trục.
Nhận xét:
Giai đoạn 2015–2020, ROE tăng mạnh từ 9 lên 37,7 phần trăm, thể hiện hiệu quả sinh lời trên vốn chủ sở hữu được cải thiện rõ rệt nhờ mở rộng quy mô tài sản và lợi nhuận tăng nhanh. Từ năm 2021 trở đi, ROE có xu hướng giảm và dao động quanh mức 28–30 phần trăm, phản ánh sự chững lại trong hiệu quả đầu tư và áp lực chi phí tài chính.
→ Nhìn chung, ROE của NVL vẫn duy trì ở mức cao ổn định, chứng tỏ doanh nghiệp có khả năng sinh lời tốt và sử dụng vốn hiệu quả dù thị trường biến động.
BCTC_NVL <- BCTC_NVL %>%
arrange(nam) %>%
mutate(loi_nhuan_luy_ke = cumsum(loi_nhuan_sau_thue / 1e12))
ggplot(BCTC_NVL, aes(x = nam, y = loi_nhuan_luy_ke)) +
geom_area(fill = "#5DADE2", alpha = 0.5) +
geom_line(color = "#1B4F72", linewidth = 1.3) +
geom_point(size = 3, color = "#154360") +
geom_text(aes(label = round(loi_nhuan_luy_ke, 1)), vjust = -0.6, size = 3.5) +
labs(title = "Tăng trưởng tích lũy lợi nhuận sau thuế (nghìn tỷ VND)", x = "Năm",
y = "LNST lũy kế") +
scale_x_continuous(breaks = BCTC_NVL$nam) +
theme_minimal(base_family = "TimesVN")
Giải thích:
(1–2) Sắp xếp dữ liệu theo năm tăng dần.
(3) Tạo biến lợi nhuận lũy kế bằng tổng tích lũy của lợi nhuận sau thuế (đơn vị nghìn tỷ).
(4–5) Vẽ biểu đồ vùng thể hiện xu hướng tích lũy, kết hợp đường và điểm.
(6) Thêm nhãn giá trị lũy kế trên mỗi điểm.
(7–9) Đặt tiêu đề, nhãn trục, chia mốc theo năm và dùng giao diện tối giản.
Nhận xét: Biểu đồ cho thấy lợi nhuận sau thuế lũy kế của Công ty NVL tăng mạnh và liên tục trong giai đoạn 2015–2024, phản ánh xu hướng tăng trưởng bền vững về hiệu quả kinh doanh.
ggplot(BCTC_NVL, aes(x = nam, y = tong_tai_san / 1e12)) +
geom_area(fill = "#FADBD8", alpha = 0.6) +
geom_line(color = "#1B4F72", linewidth = 1.3) +
geom_point(size = 3, color = "#154360") +
geom_text(aes(label = round(tong_tai_san / 1e12, 1)), vjust = -0.9, size = 3.5) +
labs(title = "Tổng tài sản tích lũy của Công ty NVL (nghìn tỷ VND)", x = "Năm", y = "Tổng tài sản") +
scale_x_continuous(breaks = BCTC_NVL$nam) +
theme_minimal(base_family = "TimesVN")
Giải thích
(1) Thiết lập trục x = năm, y = tổng tài sản (nghìn tỷ), vẽ vùng tô màu hồng nhạt.
(2–3) Thêm đường và điểm biểu diễn giá trị tổng tài sản theo năm.
(4) Hiển thị nhãn số liệu trên mỗi điểm.
(5–6) Đặt tiêu đề, nhãn trục, chia mốc năm và dùng giao diện tối giản.
Nhận xét: Biểu đồ thể hiện tổng tài sản tích lũy của Công ty NVL giai đoạn 2015–2024 có xu hướng tăng mạnh liên tục đến năm 2022, từ 26,6 nghìn tỷ lên 257,7 nghìn tỷ đồng – tức tăng gần 10 lần chỉ trong 7 năm. Sau năm 2022, tổng tài sản giảm nhẹ còn khoảng 237,8 nghìn tỷ đồng
roe_group <- BCTC_NVL %>%
group_by(giai_doan, nhom_no) %>%
summarise(ROE_tb = mean(roe, na.rm = TRUE), .groups = "drop")
ggplot(roe_group, aes(x = giai_doan, y = ROE_tb, group = nhom_no, color = nhom_no)) +
geom_line(linewidth = 1.3) + geom_point(size = 3) + geom_text(aes(label = round(ROE_tb, 1)), vjust = -0.6, size = 3.5) +
scale_color_manual(values = c("#AF7AC5", "#5DADE2", "#F4D03F")) +
labs(title = "Biến động ROE trung bình theo nhóm tỷ lệ nợ", x = "Giai đoạn", y = "ROE (%)", color = "Nhóm nợ") + # +5
theme_minimal(base_family = "TimesVN")
Giải thích:
(1–3) Nhóm dữ liệu theo giai đoạn và nhóm nợ và tính ROE trung bình cho từng nhóm.
(4–5) Vẽ biểu đồ đường thể hiện biến động ROE giữa các nhóm, thêm điểm và nhãn giá trị.
(6) Gán màu thủ công cho từng nhóm nợ.
(7–8) Đặt tiêu đề, tên trục, chú thích và áp dụng giao diện tối giản.
Nhận xét:
Trước Covid, nhóm nợ thấp đạt 35,7 phần trăm, nhóm trung bình đạt 31,9 phần trăm, còn nhóm nợ cao ở mức 28,9 phần trăm.
Sau Covid, ROE của nhóm trung bình giảm mạnh xuống 21,9 phần trăm, nhóm nợ thấp giảm còn 26,1 phần trăm, trong khi nhóm nợ cao gần như ổn định.
ggplot(BCTC_NVL, aes(x = nam, y = roa)) +
geom_line(color = "#1F618D", linewidth = 1.3) +
geom_point(size = 3.5, color = "#117864") + geom_text(aes(label = round(roa, 2)), vjust = -0.6, size = 4, color = "black") +
geom_smooth(method = "loess", color = "red", se = FALSE, linetype = "dashed",
linewidth = 1.1) +
labs(
title = "Xu hướng dài hạn của ROA của Công ty NVL (2015–2024)",
subtitle = "Tỷ suất sinh lời trên tổng tài sản (ROA) qua 10 năm",
x = "Năm",
y = "ROA (%)",
caption = "Nguồn: Báo cáo tài chính hợp nhất NVL (2015–2024)") + theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 13, hjust = 0.5, color = "gray30"),
axis.title = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.caption = element_text(size = 10, color = "gray40"))
Giải thích:
(1) Thiết lập trục x = năm, y = ROA, vẽ đường chính màu xanh đậm.
(2) Thêm điểm dữ liệu và định dạng màu, kích thước.
(3) Hiển thị nhãn giá trị ROA trên từng điểm.
(4) Thêm đường mượt (loess) màu đỏ, nét đứt, biểu diễn xu hướng dài hạn.
(5–6) Đặt tiêu đề, phụ đề, nhãn trục và chú thích nguồn dữ liệu.
(7–10) Căn giữa tiêu đề, chỉnh kích thước chữ, màu và kiểu chữ cho các thành phần đồ thị.
Nhận xét: Biểu đồ cho thấy tỷ suất sinh lời trên tổng tài sản (ROA) của Công ty NVL tăng mạnh giai đoạn 2015–2019, đạt đỉnh 9,69 phần trăm năm 2019, phản ánh hiệu quả sử dụng tài sản đạt mức cao nhất. Từ 2020–2021, ROA giảm còn 5,1 phần trăm do ảnh hưởng của dịch Covid-19 và chi phí tài chính tăng, sau đó ổn định quanh mức 5,5 phần trăm trong các năm gần đây.