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 <- read.csv("C:/Users/TO UYEN/Downloads/flight_data.csv")
dim(flight_data)
## [1] 1048575 26
Giải thích:
- dim():
dùng để kiểm tra kích thước của bộ dữ liệu.
- Giá trị đầu tiên là số
hàng trong bảng dữ liệu, tức là số quan sát hay số chuyến bay.
- Giá
trị thứ hai là số cột trong bảng dữ liệu, tức là số biến hay đặc điểm
được ghi nhận cho mỗi chuyến bay.
Nhận xét:
- Bộ dữ liệu có 1.048.575
quan sát và 26 biến.
data_dict <- data.frame(
"Tên biến" = 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.",
"Thời điểm bánh xe chạm đất tại sân bay đến.",
"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)."))
library(knitr)
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. |
| wheels_on | Thời điểm bánh xe chạm đất tại sân bay đến. |
| 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:
-
data_dict: là bảng dữ liệu mới.
-
data.frame(): dùng để tạo một bảng dữ liệu dạng khung,
mỗi cột là một vector.
- kable(): dùng để hiển thị
bảng dưới dạng đẹp và dễ đọc.
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.
sapply(flight_data, typeof)
## month day_of_month day_of_week fl_date
## "integer" "integer" "integer" "character"
## op_unique_carrier op_carrier_fl_num origin origin_city_name
## "character" "integer" "character" "character"
## origin_state_nm dest dest_city_name dest_state_nm
## "character" "character" "character" "character"
## crs_dep_time dep_time dep_delay taxi_out
## "integer" "integer" "integer" "integer"
## wheels_off wheels_on taxi_in crs_arr_time
## "integer" "integer" "integer" "integer"
## arr_time arr_delay crs_elapsed_time actual_elapsed_time
## "integer" "integer" "integer" "integer"
## air_time distance
## "integer" "integer"
Giải thích:
-
sapply(flight_data, typeof): kiểm tra kiểu dữ liệu của
từng cột trong bảng flight_data.
- typeof(): dùng
để kiểm tra 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, typeof))
##
## character integer
## 8 18
Giải thích:
-
sapply(flight_data, typeof): kiểm tra kiểu dữ liệu của
từng cột trong bảng flight_data.
- table(): đếm tần
suất xuất hiện của mỗi kiểu dữ liệu.
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))
## [1] 0
Giải thích:
-
duplicated(flight_data): dùng để kiểm tra các dòng
trùng lặp trong bảng dữ liệu.
+ Nếu kết quả là TRUE thì có sự trùng
lặp với dòng trước đó.
+ Nếu kết quả là FALSE thì không có sự trùng
lặp với dòng trước đó.
- sum(): dùng để đếm tổng
giá trị TRUE.
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.
library(knitr)
kable(head(flight_data, 10))
| 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 01/01/2024 | 9E | 4814 | JFK | New York, NY | New York | DTW | Detroit, MI | Michigan | 1252 | 1247 | -5 | 31 | 1318 | 1442 | 7 | 1508 | 1449 | -19 | 136 | 122 | 84 | 509 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4815 | MSP | Minneapolis, MN | Minnesota | CLE | Cleveland, OH | Ohio | 1015 | 1001 | -14 | 20 | 1021 | 1249 | 6 | 1325 | 1255 | -30 | 130 | 114 | 88 | 622 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4817 | JFK | New York, NY | New York | RIC | Richmond, VA | Virginia | 1415 | 1411 | -4 | 21 | 1432 | 1533 | 8 | 1601 | 1541 | -20 | 106 | 90 | 61 | 288 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4817 | RIC | Richmond, VA | Virginia | JFK | New York, NY | New York | 1650 | 1643 | -7 | 13 | 1656 | 1747 | 12 | 1841 | 1759 | -42 | 111 | 76 | 51 | 288 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4818 | DTW | Detroit, MI | Michigan | MKE | Milwaukee, WI | Wisconsin | 1015 | 1010 | -5 | 21 | 1031 | 1016 | 4 | 1034 | 1020 | -14 | 79 | 70 | 45 | 237 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4822 | JAX | Jacksonville, FL | Florida | LGA | New York, NY | New York | 1410 | 1403 | -7 | 14 | 1417 | 1559 | 4 | 1627 | 1603 | -24 | 137 | 120 | 102 | 833 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4822 | LGA | New York, NY | New York | JAX | Jacksonville, FL | Florida | 955 | 947 | -8 | 26 | 1013 | 1218 | 13 | 1244 | 1231 | -13 | 169 | 164 | 125 | 833 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4823 | CHS | Charleston, SC | South Carolina | LGA | New York, NY | New York | 1140 | 1135 | -5 | 8 | 1143 | 1309 | 5 | 1338 | 1314 | -24 | 118 | 99 | 86 | 641 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4823 | LGA | New York, NY | New York | CHS | Charleston, SC | South Carolina | 815 | 810 | -5 | 14 | 824 | 1005 | 8 | 1044 | 1013 | -31 | 149 | 123 | 101 | 641 |
| 1 | 1 | 1 | 01/01/2024 | 9E | 4828 | ITH | Ithaca/Cortland, NY | New York | JFK | New York, NY | New York | 1300 | 1248 | -12 | 12 | 1300 | 1343 | 12 | 1419 | 1355 | -24 | 79 | 67 | 43 | 189 |
Giải thích:
-
head(flight_data, 10): dùng để hiển thị 10 dòng đầu
tiên của bộ dữ liệu.
- kable(): dùng để hiển thị
bảng dưới dạng đẹp và dễ đọc.
Nhận xét:
- Việc quan sát 10 dòng đầu
giúp hiểu cấu trúc dữ liệu trước khi phân tích thống kê.
library(knitr)
kable(tail(flight_data, 10))
| 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 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1048566 | 2 | 29 | 4 | 29/02/2024 | AA | 1610 | JFK | New York, NY | New York | MIA | Miami, FL | Florida | 730 | 732 | 2 | 15 | 747 | 1029 | 8 | 1041 | 1037 | -4 | 191 | 185 | 162 | 1089 |
| 1048567 | 2 | 29 | 4 | 29/02/2024 | AA | 1611 | PHX | Phoenix, AZ | Arizona | LAS | Las Vegas, NV | Nevada | 825 | 824 | -1 | 18 | 842 | 827 | 6 | 839 | 833 | -6 | 74 | 69 | 45 | 255 |
| 1048568 | 2 | 29 | 4 | 29/02/2024 | AA | 1612 | DCA | Washington, DC | Virginia | MIA | Miami, FL | Florida | 1351 | 1406 | 15 | 24 | 1430 | 1642 | 15 | 1641 | 1657 | 16 | 170 | 171 | 132 | 919 |
| 1048569 | 2 | 29 | 4 | 29/02/2024 | AA | 1612 | MIA | Miami, FL | Florida | DCA | Washington, DC | Virginia | 959 | 1007 | 8 | 21 | 1028 | 1243 | 5 | 1238 | 1248 | 10 | 159 | 161 | 135 | 919 |
| 1048570 | 2 | 29 | 4 | 29/02/2024 | AA | 1613 | MIA | Miami, FL | Florida | SJU | San Juan, PR | Puerto Rico | 1004 | 1001 | -3 | 23 | 1024 | 1325 | 4 | 1344 | 1329 | -15 | 160 | 148 | 121 | 1045 |
| 1048571 | 2 | 29 | 4 | 29/02/2024 | AA | 1613 | SJU | San Juan, PR | Puerto Rico | MIA | Miami, FL | Florida | 1455 | 1447 | -8 | 24 | 1511 | 1640 | 7 | 1646 | 1647 | 1 | 171 | 180 | 149 | 1045 |
| 1048572 | 2 | 29 | 4 | 29/02/2024 | AA | 1614 | PHX | Phoenix, AZ | Arizona | MIA | Miami, FL | Florida | 2255 | 59 | 124 | 12 | 111 | 647 | 3 | 502 | 650 | 108 | 247 | 231 | 216 | 1972 |
| 1048573 | 2 | 29 | 4 | 29/02/2024 | AA | 1615 | JAX | Jacksonville, FL | Florida | CLT | Charlotte, NC | North Carolina | 2018 | 2014 | -4 | 20 | 2034 | 2128 | 10 | 2143 | 2138 | -5 | 85 | 84 | 54 | 328 |
| 1048574 | 2 | 29 | 4 | 29/02/2024 | AA | 1616 | CLT | Charlotte, NC | North Carolina | MCI | Kansas City, MO | Missouri | 900 | 1104 | 124 | 12 | 1116 | 1210 | 7 | 1033 | 1217 | 104 | 153 | 133 | 114 | 808 |
| 1048575 | 2 | 29 | 4 | 29/02/2024 | AA | 1616 | MCI | Kansas City, MO | Missouri | CLT | Charlotte, NC | North Carolina | 1123 | 1307 | 104 | 13 | 1320 | 1559 | 22 | 1428 | 1621 | 113 | 125 | 134 | 99 | 808 |
Giải thích:
-
tail(flight_data, 10): dùng để hiển thị 10 dòng cuối
cùng của bộ dữ liệu.
- kable(): dùng để hiển thị
bảng dưới dạng đẹp và dễ đọc.
Nhận xét:
- Việc quan sát 10 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$op_unique_carrier))
## [1] 15
Giải thích:
-
flight_data$op_unique_carrier: truy cập vào cột
“op_unique_carrier” trong bảng dữ liệu. - unique():
dùng để xác định có bao nhiêu hãng bay khác nhau .
-
length(): dùng để đếm tổng số hãng bay duy nhất xuất
hiện.
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.
table(flight_data$month)
##
## 1 2
## 547271 501304
Giải thích:
-
flight_data$month: truy cập vào cột “month” trong bảng
dữ liệu.
- table(): dùng để đếm số lần xuất hiện
của từng giá trị khác nhau trong một biến.
Nhận xét:
- Từ kết quả ta thấy có
547.271 chuyến bay vào tháng 1 và 501.304 chuyến bay vào tháng 2.
library(dplyr)
library(DT)
datatable(as.data.frame(table(flight_data$dest)),
colnames = c("Điểm đến", "Số chuyến bay"),
caption = "Tổng số chuyến bay theo điểm đến")
Giải thích:
-
table(flight_data$dest): đếm số chuyến bay của từng
điểm đến.
- as.data.frame(): chuyển kết quả thành
bảng.
- datatable(): hiển thị ở bảng đẹp, có phân
chia thành nhiều trang.
Nhận xét:
- Số chuyến bay của các điểm
khác có sự chênh lệch lớn cho thấy mức độ hoạt động không đồng đều giữa
các sân bay, phản ánh sự khác biệt về như cầu đi lại hoặc tầm quan trọng
của từng sân bay.
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))
## [1] TRUE
Giải thích:
-
is.na(): dùng để kiểm tra từng ô trong bộ dữ liệu xem
có bị thiếu giá trị hay không.
+ Kết quả là TRUE nếu ô đó bị thiếu
(NA).
+ Kết quả là FALSE nếu ô đó có giá trị.
-
any(): dùng để kiểm tra xem toàn bộ dữ liệu có ít nhất
một giá trị TRUE hay không.
+ Kết quả là TRUE nếu có ít nhất một giá
trị bị thiếu.
+ Kết quả là FALSE nếu không có giá trị nào bị
thiếu.
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 (NA) ở 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))
## 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:
-
colsums(is.na()): dùng để tính tổng số giá trị TRUE
(NA) trong từng cột.
Nhận xét:
- Các cột như: month,
day_of_month, day_of_week, fl_date, op_unique_carrier,
op_carrier_fl_num, origin, origin_city_name,… có giá trị 0. Đây là các
cột không bị thiếu dữ liệu.
- Các cột như: dep_time, dep_delay,
taxi_out, Wheels_off, Wheels_on, taxi_in, arr_time, arr_delay,
crs_elapsed_time, actual_elapsed_time, air_time có nhiều giá trị bị
thiếu. Nghĩa là có nhiều chuyến bay không có thông tin về giờ hoặc thời
gian thực tế.
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)
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:
-
flight_data_clean <- na.omit(flight_data): dùng để
tạo ra một bộ dữ liệu mới tên là flight_data_clean bằng cách loại bỏ tất
cả các quan sát bị NA.
-
colSums(is.na(flight_data_clean)): dùng để kiểm tra lại
toàn bộ dữ liệu sau khi làm sạch.
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:
-
as.factor(): chuyển đổi biến op_unique_carrier từ dạng
ký tự (character) sang dạng phân loại (factor), giúp R hiểu rằng các giá
trị trong biến là các nhóm phân biệt đại diện cho từng hãng hàng
không.
- class() được dùng để kiểm tra lại kiểu dữ
liệu sau khi chuyển đổi; kết quả “factor” xác nhận việc chuyển đổi đã
thành công.
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:
-
as.character(): chuyển đổi biến op_carrier_fl_num từ
dạng số nguyên (integer) sang kiểu ký tự (character), giúp R hiểu rằng
các giá trị trong biến là chuỗi định danh chứ không phải giá trị số
học.
- class(): được sử dụng để kiểm tra lại kiểu
dữ liệu sau khi chuyển đổi; kết quả “character” xác nhận rằng việc
chuyển đổi đã thành công.
Nhận xét:
- Kết quả “character” xác
nhận việc chuyển đổi đã thành công.
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:
-
ifelse(): trong R được sử dụng để tạo biến mới
weekend_flight
- Nếu giá trị day_of_week thuộc tập {6, 7}, hàm trả
về giá trị 1 (tức là chuyến bay diễn ra vào cuối tuần).Ngược lại, hàm
trả về 0 (tức là chuyến bay diễn ra trong ngày thường).
-
table(): được dùng để thống kê tần suất của hai nhóm
chuyến bay cuối tuần và trong tuần.
Nhận xét:
-Trong bộ dữ liệu có tổng
cộng 269.107 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.
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) nhằm phục vụ phân tích xu hướng trễ chuyến bay theo thời
điểm.
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:
-
ifelse(): được sử dụng để gán nhãn cho từng khoảng thời
gian cụ thể:
Từ 05:00 đến trước 12:00 → “Morning”
Từ 12:00 đến
trước 18:00 → “Afternoon”
Từ 18:00 đến trước 22:00 → “Evening”
Các trường hợp còn lại (22:00 – 05:00) → “Night”
-
as.factor(): chuyển biến day_period sang dạng factor để
R hiểu đây là biến phân loại.
- summary(): Hiển
thị số lượng chuyến bay trong từng nhóm thời điểm.
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.
Công thức tính tốc độ
trung bình:
\[
\text{speed_mph} = \frac{\text{distance}}{\text{air_time} / 60}
\]
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:
- Vận tốc trung bình của
chuyến bay (speed_mph) bằng quãng đường bay (distance) chia cho thời
gian bay thực tế (air_time) đã được chuyển đổi sang đơn vị giờ.
-
summary() dùng để mô tả thống kê cơ bản của biến mới
tạo (gồm giá trị nhỏ nhất, trung vị, trung bình, lớn nhất, và các tứ
phân vị), giúp nhận biết phạm vi dao động và xu hướng chung của tốc độ
bay trong toàn bộ dữ liệu.
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 mph 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.
library(dplyr)
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:
- Gói
dplyr được nạp để sử dụng các hàm xử lý dữ liệu như
%>% và filter().
- quantile() dùng để tính các
phân vị thứ nhất (Q1) và thứ ba (Q3) của biến speed_mph.
- Từ đó,
hai ngưỡng loại ngoại lệ được xác định: Lower bound và Upper bound. Các
quan sát nằm ngoài khoảng này bị xem là ngoại lệ.
-
filter() được dùng để giữ lại các giá trị speed_mph
thõa mãn điều kiện, tạo ra bộ dữ liệu mới flight_data_no_outlier.
-
summary() cung cấp các thống kê mô tả giúp kiểm tra lại
kết quả sau khi loại ngoại lệ.
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.
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.
library(dplyr)
convert_to_minutes <- function(x) {
hour <- floor(x / 100)
minute <- x %% 100
total_minutes <- hour * 60 + minute
return(total_minutes)
}
flight_data_no_outlier <- flight_data_no_outlier %>%
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)
)
View(flight_data_no_outlier)
Giải thích: - hour <- floor(x /
100): lấy phần giờ của biến thời gian.
- minute
<- x %% 100: lấy phần phút.
- total_minutes
<- hour * 60 + minute: Quy đổi tổng thời gian sang phút.
- return(total_minutes): trả về kết quả tính được.
- convert_to_minutes(): chuyển đổi thời gian dạng
giờ–phút sang tổng số phút trong ngày. -
crs_dep_time_min: giờ khởi hành dự kiến (phút)
-
dep_time_min: giờ khởi hành thực tế (phút)
-
wheels_off_min: thời điểm cất cánh thực tế (phút)
- wheels_on_min: thời điểm hạ cánh thực tế (phút)
- crs_arr_time_min: giờ đến dự kiến (phút)
-
arr_time_min: giờ đến thực tế (phút)
-
mutate(): tạo thêm các biến mới
→ Mỗi cột được
tính bằng cách gọi hàm convert_to_minutes() vừa định nghĩa ở trên. -
View(flight_data_no_outlier): Mở bảng dữ liệu kết quả
trong cửa sổ Data Viewer của RStudio.
Sau khi đã tạo biến day_period để phân loại thời điểm cất cánh của
chuyến bay (sáng, trưa, chiều, tối), bước này tiến hành tổng hợp dữ liệu
nhằm đánh giá tỷ lệ các chuyến bay bị trễ theo từng khung giờ.
flight_delay_period <- flight_data_no_outlier %>%
group_by(day_period) %>%
summarise(
total_flights = n(),
delayed_flights = sum(arr_delay > 0, na.rm = TRUE),
delay_rate = delayed_flights / total_flights
)
head(flight_delay_period)
Giải thích:
-
group_by() để nhóm dữ liệu theo biến day_period, từ đó
tính toán số lượng và tỷ lệ chuyến bay bị trễ trong từng khung giờ.
- head() dùng để hiển thị những dòng đầu tiên của bảng
kết quả.
Nhận xét:
- Phân tích cho thấy tỷ lệ
trễ chuyến bay tăng dần từ sáng đến đêm, phản ánh ảnh hưởng tích lũy của
các yếu tố vận hành hàng không trong ngày. Cụ thể, tỷ lệ trễ trung bình
tăng từ 22.43% buổi sáng lên 41.57% ban đêm, tương ứng mức tăng
19.14%.
Phân tích đặc điểm cơ bản của 3 biến định lượng: dep_delay,
arr_delay và distance.
quant_vars <- flight_data_no_outlier[, c("dep_delay", "arr_delay", "distance")]
Giải thích:
- quant_vars <-
flight_data_no_outlier[, c(“dep_delay”, “arr_delay”,
“distance”)]: dùng để trích 3 biến định lượng từ bộ 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)
## dep_delay arr_delay distance
## Min. : -96.00 Min. :-117.000 Min. : 31
## 1st Qu.: -6.00 1st Qu.: -17.000 1st Qu.: 406
## Median : -2.00 Median : -7.000 Median : 699
## Mean : 11.52 Mean : 5.494 Mean : 839
## 3rd Qu.: 8.00 3rd Qu.: 9.000 3rd Qu.:1072
## Max. :3125.00 Max. :3136.000 Max. :5095
Giải thích:
-
summary(): dùng để tính các thống kê mô tả cơ bản như:
min, 1st quartile, median, mean, 3rd quartile, max.
Nhận xét:
- Biến dep_delay (Độ
trễ khi khởi hành - phút):
+ Giá trị trung bình (Mean) của
độ trễ khởi hành là 11.52 phút, trung vị (Median) là -2 phút, nghĩa là
một nửa số chuyến bay khởi hành sớm hơn hoặc đúng giờ.
+ Giá trị lớn
nhất lên đến 3125 phút cho thấy một số trường hợp khởi hành trễ bất
thường, có thể là do thời tiết xấu, sự cố kỹ thuật, hoặc hoãn chuyến
dài.
+ Khoảng tứ phân vị từ -6 đến 8 phút phản ánh phần lớn các
chuyến bay chỉ dao động trong khoảng ±10 phút quanh giờ dự kiến, tức là
khá ổn định về thời gian cất cánh.
→ Như vậy, dữ liệu của biến
dep_delay cho thấy đa số chuyến bay khởi hành sớm hoặc đúng giờ, nhưng
có một số ít chuyến trễ nghiêm trọng làm kéo trung bình lên cao.
-
Biến arr_delay (Độ trễ khi hạ cánh - phút):
+ Giá
trị trung bình là 5.494 phút, trung vị là -7 phút, nghĩa là phần lớn
chuyến bay đến nơi sớm hơn kế hoạch.
+ Giá trị lớn nhất lên đến
3136 phút cho thấy tồn tại một số chuyến trễ rất lớn.
+ Khoảng tứ
phân vị từ -17 đến 9 phút phản ánh phần lớn các chuyến bay đến dao động
trong khoảng ±15 phút quanh giờ dự kiến.
→ Như vậy, dữ liệu của biến
arr-delay cho thấy tình trạng tương tự độ trễ khi khởi hành, đa số đúng
giờ hoặc sớm và có một số chuyến bị trễ lớn.
- Biến
distance (Khoảng cách bay - dặm):
+ Giá trị trung bình 839
dặm và trung vị 699 dặm cho thấy phần lớn chuyến bay là chuyến bay ngắn
đến trung bìnhn.
+ Giá trị lớn nhất 5095 dặm phản ánh sự tồn tại
của một số chuyến bay đường dài.
+ Khoảng tứ phân vị từ 406 đến
1072 dặm cho thấy các chuyến bay có độ dài trung bình khoảng 600–700
dặm.
sapply(quant_vars, sd)
## dep_delay arr_delay distance
## 56.23152 59.03097 584.93699
Giải thích:
- sd:
tính độ lệch chuẩn - đo mức độ phân tán của dữ liệu quanh giá trị trung
bình.
- sapply(quant_vars, sd): lấy từng cột trong
quant_vas và áp dụng hàm sd lên nó.
Nhận xét:
- Biến
dep_delay: có độ lệch chuẩn 56.23152 phút cao hơn nhiều so với
giá trị trung bình 11.52 phút, thể hiện thời gian trễ khởi hành có biến
động khá lớn. Phản ánh sự không ổn định trong quá trình khởi hành.
-
Biến arr_delay: có độ lệch chuẩn 59.03097 phút cũng cao
hơn nhiều so với giá trị trung bình 5.494 phút, cho thấy mức dao động
cao hơn độ trễ khởi hành, do đó thời gian đến của các chuyến bay cũng
thiếu ổn định.
- Biến distance: có độ lệch chuẩn
584.93699 dặm thấp hơn so với giá trị trung bình 839 dặm cho thấy sự
chênh lệch lớn giữa các chặng bay. Phản ánh sự đa dạng trong hoạt động
hàng không.
sapply(quant_vars, function(x) max(x) - min(x))
## dep_delay arr_delay distance
## 3221 3253 5064
Giải thích:
-
max(x)-min(x): tính khoảng biến thiên giữa giá trị lớn
nhất và nhỏ nhất của mỗi biến định lượng.
-
function(x): lấy từng cột trong quant_vars và thực hiện
phép tính để ra khoảng biến thiên.
Nhận xét:
- Biến
dep_delay: có khoảng biến thiên là 3221 phút, cho thấy sự khác
biệt rất lớn giữa chuyến bay khởi hành sớm nhất và muộn nhất.
-
Biến arr_delay: có khoảng biến thiên 3253 phút, cho
thấy tình trạng trễ khi đến nơi cũng có biến động mạnh.
-
Biến distance: có khoảng biến thiên 5064 dặm, cho thấy
mức độ đa dạng về độ dài hành trình.
qual_vars <- flight_data_no_outlier[, c("op_unique_carrier", "origin", "dest")]
Giải thích:
- qual_vars <-
flight_data_no_outlier[, c(“op_unique_carrier”, “origin”,
“dest”)]: dùng để trích 3 biến định lượng từ bộ dữ liệu
flight_data_no_outlier.
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.
Giải thích:
-
table(): tạo bảng tần số tuyệt đối thể hiện số lần xuất
hiện của từng giá trị của biến.
- as.data.frame():
Chuyển bảng tần suất từ dạng table sang dạng data frame, giúp dễ xử lý
và hiển thị hơn.
- datatable(): Dùng gói DT để hiển
thị bảng động, đẹp và có thể chia trang, sắp xếp, tìm kiếm.
-
pageLength=10: hiển thị 10 dòng mỗi trang.
-
caption: thêm tiêu đề cho bảng.
table_carrier <- as.data.frame(table(flight_data_no_outlier$op_unique_carrier))
datatable(table_carrier,
options = list(pageLength = 10),
caption = "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ự chênh lệch lớn.
table_origin <- as.data.frame(table(flight_data_no_outlier$origin))
datatable(table_origin,
options = list(pageLength = 10),
caption = "Bảng tần suất sân bay xuất phát")
Nhận xét:
- Số lượng sân bay xuất phát
là 334, cho thấy mạng lưới hoạt động hàng không rất rộng, bao phủ nhiều
địa điểm.
- Một số sân bay có tần suất chuyến bay rất cao như ABQ
với 3.338 chuyến, chứng tỏ đó là các trung tâm hàng không lớn.
-
Ngược lại, các sân bay như ADK, ADQ chỉ có vài chục chuyến bay phản ánh
vai trò nhỏ hoặc hoạt động hạn chế trong mạng lưới.
→ Phân bố tần
suất này không đồng đều, thể hiện sự tập trung hoạt động vào một số sân
bay lớn.
table_dest <- as.data.frame(table(flight_data_no_outlier$dest))
datatable(table_dest,
options = list(pageLength = 10),
caption = "Bảng tần suất sân bay đến")
Nhận xét:
- Có 334 sân bay đến, cho
thấy phạm vi bay rộng khắp các khu vực.
- Một số sân bay có tần
suất chuyến bay đến rất cao, chẳng hạn như ABQ với 3.333 chuyến bay, thể
hiện vai trò là các trung tâm hàng không lớn.
- Các sân bay như ADK
hay ADQ có tần suất thấp (dưới 200 chuyến), phản ánh vai trò nhỏ hoặc ít
được khai thác trong mạng lưới bay.
- Phân bố số chuyến bay đến
không đồng đều giữa các sân bay, cho thấy hoạt động hàng không tập trung
chủ yếu vào một số điểm đến lớn.
Giải thích:
-
table(): tạo bảng tần số tuyệt đối.
-
prop.table(): chuyển sang bảng tần số tương đối.
-
round(…,2): làm tròn 2 chữ số thập phân.
-
datatable(): hiển thị ở dạng đẹp, có thể lật sang trang
khác.
table_carrier_rel <- as.data.frame(round(prop.table(table(flight_data_no_outlier$op_unique_carrier)) * 100, 2))
datatable(table_carrier_rel,
options = list(pageLength = 10),
caption = "Bảng tần suất tương đối (%) của hãng hàng không thực hiện chuyến bay")
Nhận xét:
- Hãng WN chiếm 20.96% tổng
số chuyến bay, là hãng có quy mô hoạt động lớn nhất trong bộ dữ liệu.
- AA với 14.59% và DL với 14.02%, cùng với UA với 10.56% và OO với
9.91% cho thấy đây là các hãng hàng không lớn, chiếm phần lớn thị phần
vận tải.
- Các hãng như B6, MQ, NK và YX dao động khoảng 3–4%, thể
hiện quy mô khai thác ở mức vừa phải.
- Các hãng như HA, G4 chỉ
chiếm 1–2%, phản ánh quy mô nhỏ hoặc khai thác ở các tuyến hạn chế.
→ Kết quả này có thể sử dụng để so sánh mức độ chậm chuyến hoặc huỷ
chuyến theo quy mô hãng, hay đánh giá mức độ cạnh tranh trong thị trường
hàng không.
table_origin_rel <- as.data.frame(round(prop.table(table(flight_data_no_outlier$origin)) * 100, 2))
datatable(table_origin_rel,
options = list(pageLength = 10),
caption = "Bảng tần suất tương đối (%) của các sân bay xuất phát")
Nhận xét:
- Bảng có 334 sân bay.
- Việc phân tích toàn bộ bảng có thể giúp xác định các sân bay trọng
điểm, các sân bay ít hoạt động, từ đó cho thấy phân bố không đều trong
mạng lưới hàng không.
table_dest_rel <- as.data.frame(round(prop.table(table(flight_data_no_outlier$dest)) * 100, 2))
datatable(table_dest_rel,
options = list(pageLength = 10),
caption = "Bảng tần suất tương đối (%) của các sân bay đến")
Nhận xét:
- Bảng có 334 sân bay.
- Phân bố tần suất tương đối khá không đồng đều, khi chỉ một số sân bay
có tỷ trọng cao, trong khi đa số sân bay có tần suất rất nhỏ, phản ánh
sự tập trung của các chuyến bay vào một số điểm đến chính, nhiều sân bay
khác chỉ đóng vai trò thứ yếu.
library(DT)
delay_by_day <- flight_data_no_outlier %>%
group_by(day_of_week) %>%
summarise(
avg_dep_delay = round(mean(dep_delay), 2),
median_dep_delay = round(median(dep_delay), 2),
total_flights = n()
) %>%
arrange(day_of_week)
datatable(
delay_by_day,
options = list(pageLength = 10)
)
Giải thích:
- delay_by_day
<- flight_data_no_outlier: tạo biến mới có tên delay_by_day
từ bộ dữ liệu flight_data_no_outlier.
- %>%:
chuyển kết quả của bước này sang bước tiếp theo. -
group_by(day_of_week): Nhóm dữ liệu theo ngày trong
tuần.
- avg_dep_delay = round(mean(dep_delay),
2),: Tính độ trễ khởi hành trung bình (mean(dep_delay)) của mỗi
nhóm. Sau đó làm tròn 2 chữ số thập phân bằng round().
-
median_dep_delay = round(median(dep_delay), 2),: Tính
độ trễ khởi hành trung vị. Cũng làm tròn 2 chữ số.
-
total_flights = n(): Đếm tổng số chuyến bay trong từng
nhóm.
- summarise(): Bắt đầu hàm tóm tắt thống kê
cho từng nhóm.
- arrange(day_of_week): Sắp xếp
bảng kết quả theo thứ tự tăng dần của ngày trong tuần (1 → 7).
-
options = list(pageLength = 10): hiển thị 10 dòng mỗi
trang.
- datatable(): hiển thị bảng đẹp, có thể
sắp xếp và lật trang.
Nhận xét:
- Về độ trễ trung
bình (avg_dep_delay):
+ Các giá trị dao động từ 7.84 đến
14.06 phút, cho thấy nhìn chung các chuyến bay chỉ bị trễ nhẹ.
+
Ngày Thứ Hai (day_of_week = 2) có độ trễ trung bình cao nhất (14.06
phút) – đây có thể là do lưu lượng bay lớn vào đầu tuần khi nhu cầu di
chuyển tăng.
+ Ngày Thứ Tư (3) và Thứ Năm (4) lại có mức trễ trung
bình thấp nhất (7.87 và 7.84 phút) – gợi ý rằng giữa tuần là thời điểm
hệ thống hàng không hoạt động ổn định hơn.
- Về độ trễ trung
vị (median_dep_delay):
+ Các giá trị trung vị nằm quanh -2
đến -3 phút, tức là một nửa số chuyến bay thực tế khởi hành sớm hơn 2–3
phút.
+ Điều này phản ánh rằng mặc dù có một số chuyến bay bị trễ
đáng kể nhưng phần lớn các chuyến vẫn đúng hoặc sớm giờ khởi hành.
-
Về tổng số chuyến bay (total_flights):
+ Tổng số
chuyến bay giữa các ngày trong tuần khá đồng đều, dao động quanh
140.000–158.000 chuyến.
+ Ngày Thứ Hai (1) có số lượng chuyến bay
cao nhất (158.769 chuyến), phù hợp với xu hướng nhu cầu di chuyển tăng
đầu tuần.
+ Ngày Thứ Sáu (6) có ít chuyến bay hơn (123.143 chuyến)
— có thể do các tuyến bay được phân bổ ít hơn vào cuối tuần.
library(DT)
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))
datatable(
head(carrier_delay, 20),
options = list(pageLength = 10))
Giải thích:
-
group_by(): nhóm dữ liệu theo hãng bay
(op_unique_carrier).
- %>%: chuyển kết quả của
bước trước làm đầu vào cho bước sau. - summarise():
tính toán giá trị tổng hợp cho từng nhóm.
- avg_depdelay =
mean(dep_delay): tính độ trễ trung bình khi khởi hành của mỗi
hãng với tên mới là avg_depdelay.
- avg_arrdelay =
mean(arr_delay): tính độ trễ trung bình khi đến của mỗi hãng
với tên mới là avg_arrdelay.
- arrange(): sắp xếp
dữ liệu theo thứ tự giảm dần (desc) của biến avg_depdelay.
-
datatable(): tạo bảng dữ liệu có thể tìm kiếm, sắp xếp
và lật trang.
- head(carrier_delay, 20): Lấy 20
dòng đầu tiên của bảng carrier_delay.
- options =
list(pageLength = 10): Mỗi trang của bảng sẽ hiển thị 10 dòng
dữ liệu.
Nhận xét:
- Kết quả cho thấy hãng AA
có độ trễ trung bình lớn nhất ở cả hai giai đoạn cất cánh và hạ cánh,
cho thấy tình trạng chậm chuyến xảy ra thường xuyên hơn so với các hãng
khác.Ngược lại, hãng YX có độ trễ trung bình thấp nhất, cho thấy khả
năng duy trì lịch trình cất cánh đúng giờ tốt nhất của hãng.
library(DT)
origin_time_stats <- flight_data_no_outlier %>%
group_by(origin_city_name) %>%
summarise(
total_flights = n(),
min_time = min(actual_elapsed_time),
max_time = max(actual_elapsed_time),
mean_time = mean(actual_elapsed_time),
median_time = median(actual_elapsed_time)
) %>%
arrange(desc(total_flights))
datatable(
head(origin_time_stats, 20),
options = list(pageLength = 10))
Giải thích:
-
origin_time_stats <- flight_data_no_outlier %>%:
tạo biến mới có tên origin_time_stats lấy từ flight_data_no_outlier.
- group_by(origin_city_name) %>%: nhóm dữ liệu
theo thành phố xuất phát.
- total_flights = n():
tổng số chuyến bay xuất phát từ thành phố đó.
- min_time =
min(actual_elapsed_time): thời gian bay ngắn nhất.
-
max_time = max(actual_elapsed_time): thời gian bay dài
nhất.
- mean_time = mean(actual_elapsed_time):
thời gian bay trung bình.
- median_time =
median(actual_elapsed_time): thời gian bay trung vị.
-
summarise(): tính các chỉ tiêu thống kê mô tả cho mỗi
thành phố.
- arrange(desc(total_flights)): Sắp xếp
kết quả theo thứ tự giảm dần của biến total_flights.
-
head(origin_time_stats, 20): chỉ lấy 20 thành phố có
nhiều chuyến bay nhất.
- options = list(pageLength =
10): thiết lập hiển thị 10 dòng mỗi trang.
-
datatable(): Bảng kết quả cho phép người xem tìm kiếm,
sắp xếp và lật trang.
Nhận xét:
- Atlanta (GA) là thành phố
có số lượng chuyến bay xuất phát lớn nhất với 49.667 chuyến, tiếp theo
là Chicago (IL) với 47.465 chuyến và Dallas/Fort Worth (TX) với 44.431
chuyến.
- Về thời gian bay, giá trị trung bình (mean_time) dao động
từ khoảng 120 đến 190 phút, trong khi thời gian trung vị (median_time)
thường thấp hơn, cho thấy phần lớn các chuyến bay có độ dài vừa phải,
chỉ một số ít chuyến đường dài kéo giá trị trung bình tăng lên.
-
Các thành phố như Los Angeles (CA), Boston (MA) hay Miami (FL) có thời
gian bay trung bình cao nhất (trên 180 phút), phản ánh vị trí địa lý xa
hơn so với trung tâm. Ngược lại, các thành phố như Charlotte (NC) và
Detroit (MI) có thời gian bay trung bình thấp hơn (khoảng 120–135 phút),
chủ yếu phục vụ các chặng bay ngắn trong khu vực.
library(dplyr)
flight_diff_stats <- flight_data_no_outlier %>%
mutate(time_diff = actual_elapsed_time - crs_elapsed_time) %>%
group_by(op_unique_carrier) %>%
summarise(
total_flights = n(),
mean_diff = round(mean(time_diff), 2),
median_diff = median(time_diff),
min_diff = min(time_diff),
max_diff = max(time_diff)
) %>%
arrange(desc(mean_diff))
datatable(
head(flight_diff_stats, 20),
options = list(pageLength = 10)
)
Giải thích:
- mutate(time_diff
= actual_elapsed_time - crs_elapsed_time): tạo biến mới
time_diff thể hiện chênh lệch giữa thời gian thực tế và dự kiến.
-
group_by(op_unique_carrier): Gom nhóm dữ liệu theo mã
hãng hàng không.
- total_flights = n(): Tổng số
chuyến bay của hãng.
- mean_diff = round(mean(time_diff),
2): Độ chênh lệch trung bình (âm: bay nhanh hơn dự kiến; dương:
bay lâu hơn dự kiến) và tròn làm 2 chữ số thập phân.
-
median_diff = median(time_diff): Giá trị chênh lệch
trung vị.
- min_diff, max_diff: Chênh lệch nhỏ
nhất và lớn nhất trong từng hãng.
-
arrange(desc(mean_diff)): Sắp xếp danh sách hãng theo
thứ tự giảm dần của độ chênh lệch trung bình.
-
datatable(…): Hiển thị bảng kết quả tương tác, giúp xem
chi tiết 20 hãng đầu tiên.
Nhận xét:
- Hầu hết các hãng hàng
không có mean_diff âm, chứng tỏ phần lớn chuyến bay thực tế ngắn hơn
thời gian dự kiến, tức là thời gian bay được lên kế hoạch khá chặt chẽ
và có độ dự phòng.
- Hãng HA có độ lệch trung bình gần bằng 0
(–0.01), thể hiện sự ổn định và chính xác cao trong dự báo thời gian
bay.
- Ngược lại, các hãng như DL, YX, và 9E có mean_diff lớn âm
(từ –7.8 đến –8.06 phút), cho thấy thời gian thực tế thường ngắn hơn dự
kiến khoảng 7–8 phút, có thể do tuyến bay thuận lợi hoặc kế hoạch dự
kiến dư thời gian.
- Một số giá trị max_diff rất lớn (như 500 phút
ở YX) cho thấy vẫn tồn tại các chuyến bay bất thường, có thể do thời
tiết xấu hoặc lý do kỹ thuật.
library(dplyr)
library(tidyr)
library(ggplot2)
carrier_delay_long <- carrier_delay %>%
pivot_longer(
cols = c(avg_depdelay, avg_arrdelay),
names_to = "delay_type",
values_to = "delay_value"
)
carrier_delay_long$delay_type <- factor(carrier_delay_long$delay_type,
levels = c("avg_depdelay", "avg_arrdelay"))
ggplot(carrier_delay_long, aes(x = op_unique_carrier, y = delay_value, fill = delay_type)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
geom_text(aes(label = round(delay_value, 1)),
position = position_dodge(width = 1),
vjust = -0.5, size = 3.2) +
geom_hline(yintercept = mean(carrier_delay_long$delay_value, na.rm = TRUE),
color = "darkgreen", linetype = "dashed", size = 1) +
labs(
x = "Airline",
y = "Average Delay (minutes)",
title = "Average Departure and Arrival Delays per Airline",
subtitle = "Comparison of delay performance across airlines",
caption = "Source: flight_data_no_outlier"
) +
scale_fill_manual(
values = c("avg_depdelay" = "#FFB7C5", "avg_arrdelay" = "#A7D8F0"),
labels = c("avg_depdelay" = "Departure delay", "avg_arrdelay" = "Arrival delay")
) +
theme_minimal(base_size = 13) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(face = "bold", size = 15),
plot.subtitle = element_text(size = 12, face = "italic", color = "gray30"),
legend.position = "right"
)
Giải thích:
- library(dplyr),
library(tidyr), library(ggplot2):
+ Gọi ba thư viện hỗ trợ
xử lý dữ liệu và trực quan hóa.
+ dplyr: thao tác
dữ liệu dạng bảng (lọc, nhóm, tính trung bình).
+
tidyr: chuyển đổi định dạng dữ liệu từ wide sang long
để dễ vẽ biểu đồ.
+ ggplot2: tạo biểu đồ chuyên
nghiệp, dễ tùy chỉnh.
- pivot_longer(): Chuyển dữ
liệu từ dạng wide (các cột avg_depdelay, avg_arrdelay) thành dạng long,
giúp ggplot có thể hiểu delay_type (loại trễ) như một biến phân loại và
delay_value là giá trị tương ứng.
- geom_bar(stat =
“identity”, position = “dodge”): Vẽ biểu đồ cột nhóm (mỗi hãng
có hai cột – trễ khởi hành và trễ đến).
- position =
“dodge” giúp hai cột hiển thị cạnh nhau thay vì chồng lên
nhau.
- geom_text(): Hiển thị giá trị cụ thể trên
đỉnh mỗi cột để người xem dễ nhận biết mức trễ trung bình.
-
geom_hline(): Thêm đường ngang biểu thị trung bình toàn
bộ độ trễ, giúp so sánh từng hãng với mức trung bình ngành.
-
labs(): Thiết lập tiêu đề, nhãn trục và chú thích nguồn
dữ liệu, giúp biểu đồ rõ ràng và mang tính học thuật.
-
scale_fill_manual(): Tùy chỉnh màu sắc cho hai loại độ
trễ:
+ Màu đỏ gạch (firebrick) cho trễ khởi hành.
+ Màu xanh
thép (steelblue) cho trễ đến.
+ Đồng thời đổi nhãn hiển thị trong
chú giải (legend).
- theme_minimal() và theme():
Tạo giao diện tối giản, dễ đọc, đồng thời chỉnh góc nghiêng nhãn trục x,
vị trí legend, và định dạng tiêu đề.
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. Trong đó, một số hãng ghi nhận
mức độ trễ cao nhất trên 16 phút, trong khi một số hãng khác đạt mức trễ
rất thấp, thậm chí âm, phản ánh khả năng vận hành hiệu quả và đúng
giờ.
- 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.
library(dplyr)
library(ggplot2)
library(tidyr)
delay_weekend_month <- flight_data_no_outlier %>%
filter(month %in% c(1, 2)) %>%
group_by(month, weekend_flight) %>%
summarise(
avg_depdelay = mean(dep_delay, na.rm = TRUE),
avg_arrdelay = mean(arr_delay, na.rm = TRUE)
) %>%
pivot_longer(
cols = c(avg_depdelay, avg_arrdelay),
names_to = "delay_type",
values_to = "delay_value"
) %>%
mutate(
delay_type = factor(delay_type,
levels = c("avg_depdelay", "avg_arrdelay")),
weekend_flight = factor(weekend_flight,
levels = c(0, 1),
labels = c("Weekday", "Weekend"))
)
ggplot(delay_weekend_month, aes(x = weekend_flight, y = delay_value, fill = delay_type)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
geom_text(aes(label = round(delay_value, 1)),
position = position_dodge(width = 1),
vjust = -0.3, size = 3.2) +
geom_hline(yintercept = mean(delay_weekend_month$delay_value, na.rm = TRUE),
color = "darkgreen", linetype = "dashed", size = 1) +
facet_wrap(~ month, ncol = 2, labeller = labeller(month = c(`1` = "January", `2` = "February"))) +
scale_fill_manual(
values = c("avg_depdelay" = "#F8AFA6", "avg_arrdelay" = "#CBB2FE"),
labels = c("Departure delay", "Arrival delay")
) +
geom_point(aes(group = delay_type), size = 2, color = "black", position = position_dodge(width = 1)) +
labs(
x = "Flight Type",
y = "Average Delay (minutes)",
title = "Average Departure and Arrival Delays: Weekday vs Weekend (Jan & Feb)",
subtitle = "Comparison between weekday and weekend performance across the first two months",
caption = "Source: flight_data_no_outlier"
) +
theme_minimal(base_size = 13) +
theme(
axis.text.x = element_text(face = "bold"),
plot.title = element_text(face = "bold", size = 15),
plot.subtitle = element_text(size = 12, face = "italic", color = "gray30"),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
Giải thích:
- group_by(month,
weekend_flight): chia dữ liệu thành các nhóm theo tháng (1, 2,
…) và loại chuyến bay (ngày thường hoặc cuối tuần).
-
summarise(…): tính độ trễ trung bình khi khởi hành
(avg_depdelay) và độ trễ trung bình khi đến (avg_arrdelay) trong từng
nhóm.
- pivot_longer() biến dữ liệu từ dạng rộng
(wide) sang dạng dài (long).
- cols = c(avg_depdelay,
avg_arrdelay): chỉ định hai cột sẽ được gom lại.
-
names_to = “delay_type”: tạo một cột mới ghi loại độ
trễ (“avg_depdelay” hay “avg_arrdelay”).
- values_to =
“delay_value”: chứa giá trị trung bình tương ứng của từng loại
trễ.
- ggplot(…): khởi tạo biểu đồ với dữ liệu.
- aes(…): ánh xạ các biến lên trục:
- x =
factor(weekend_flight) → chia cột thành Weekday và Weekend.
- y = delay_value → độ trễ trung bình.
-
fill = delay_type → màu khác nhau cho khởi hành và
đến.
- geom_bar(stat = “identity”): mỗi cột thể
hiện đúng giá trị delay_value (không đếm tần suất).
-
position = “dodge”: đặt hai cột cạnh nhau (thay vì
chồng lên nhau).
- geom_text(…): hiển thị số liệu
trên đầu cột (làm tròn 1 chữ số).
- geom_hline(…):
thêm đường ngang biểu thị mức trung bình chung của tất cả độ trễ.
-
linetype = “dashed”: nét đứt để phân biệt.
-
color = “darkgreen”: tô màu xanh lá để nổi bật.
-
facet_wrap(~ month): tách biểu đồ thành hai ô nhỏ — một
cho tháng 1, một cho tháng 2.
- ncol = 2: hiển thị
theo 2 cột (đặt hai tháng cạnh nhau).
- labeller:
đổi nhãn trục từ “1” → “January”, “2” → “February” cho dễ hiểu.
-
scale_fill_manual(…): tự đặt màu cho từng loại độ trễ
(xanh cho khởi hành, đỏ cho đến).
- labs(…): đặt
tiêu đề, nhãn trục và chú thích nguồn dữ liệu
-
theme_minimal(): dùng giao diện đơn giản, hiện đại.
- theme(…): điều chỉnh vị trí chữ, font và vị trí
legend ở dưới biểu đồ.
Nhận xét:
- Biểu đồ cho thấy nhìn
chung các chuyến bay trong tháng 1 có mức độ trễ cao hơn so với tháng 2,
đặc biệt là độ trễ khởi hành với trung bình trên 15 phút. Ngoài ra, các
chuyến bay cuối tuần thường bị trễ nhiều hơn ngày thường, phản ánh tình
trạng tăng nhu cầu di chuyển và tần suất khai thác cao vào cuối tuần.
Tổng thể, xu hướng độ trễ giảm dần sang tháng 2 cho thấy tình hình khai
thác bay đã ổn định hơn sau giai đoạn cao điểm đầu năm.
library(dplyr)
library(ggplot2)
library(tidyr)
flight_data_no_outlier <- flight_data_no_outlier %>%
mutate(
day_period = case_when(
dep_time >= 500 & dep_time < 1200 ~ "Morning",
dep_time >= 1200 & dep_time < 1700 ~ "Afternoon",
dep_time >= 1700 & dep_time < 2100 ~ "Evening",
TRUE ~ "Night"
)
)
carrier_delay <- flight_data_no_outlier %>%
group_by(month, weekend_flight, day_period) %>%
summarise(
avg_depdelay = mean(dep_delay, na.rm = TRUE),
avg_arrdelay = mean(arr_delay, na.rm = TRUE)
) %>%
pivot_longer(
cols = c(avg_depdelay, avg_arrdelay),
names_to = "delay_type",
values_to = "delay_value"
)
ggplot(carrier_delay, aes(x = day_period, y = delay_value, fill = delay_type)) +
geom_bar(stat = "identity", position = "dodge", color = "black") + # Layer 1: Bar chart
geom_text(aes(label = round(delay_value, 1)), # Layer 2: Labels
position = position_dodge(width = 1),
vjust = -0.4, size = 3) +
geom_hline(yintercept = mean(carrier_delay$delay_value, na.rm = TRUE), # Layer 3: Mean line
color = "darkgreen", linetype = "dashed", size = 1) +
facet_grid(month ~ weekend_flight, # Layer 4: Split by month & weekend
labeller = labeller(
month = c("1" = "Month 1", "2" = "Month 2"),
weekend_flight = c("0" = "Weekday", "1" = "Weekend")
)) +
scale_fill_manual( # Layer 5: Colors and legend
values = c("avg_depdelay" = "#E8A0BF", "avg_arrdelay" = "#A8D1D1"),
labels = c("avg_depdelay" = "Departure delay", "avg_arrdelay" = "Arrival delay")
) +
labs( # Layer 6: Titles and labels
x = "Time of Day",
y = "Average Delay (minutes)",
title = "Average Flight Delays by Time of Day and Month",
subtitle = "Comparison of Departure and Arrival Delays across Months and Weekends",
caption = "Source: flight_data_no_outlier"
) +
theme_minimal(base_size = 13) + # Layer 7: Theme customization
theme(
plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
plot.subtitle = element_text(size = 12, color = "gray30", hjust = 0.5),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_blank(),
legend.position = "bottom"
)
Giải thích:
Nhận xét:
library(ggplot2)
library(dplyr)
# Tính giá trị trung bình để thêm chú thích
avg_points <- flight_data_no_outlier %>%
group_by(op_unique_carrier) %>%
summarise(mean_distance = mean(distance, na.rm = TRUE),
mean_delay = mean(arr_delay, na.rm = TRUE))
ggplot(flight_data_clean, aes(x = distance, y = arr_delay)) +
# 🟢 Lớp 1: Nền mờ để tạo khung trực quan
geom_rect(aes(xmin = 0, xmax = Inf, ymin = -10, ymax = 10),
fill = "lightblue", alpha = 0.1, inherit.aes = FALSE) +
# 🔵 Lớp 2: Điểm dữ liệu chính
geom_point(aes(color = op_unique_carrier, size = air_time), alpha = 0.6) +
# 🔴 Lớp 3: Đường hồi quy tuyến tính (trend line)
geom_smooth(aes(color = op_unique_carrier), method = "lm", se = FALSE, size = 1) +
# 🟣 Lớp 4: Đường trung bình toàn bộ (mean line)
geom_hline(yintercept = mean(flight_data_clean$arr_delay, na.rm = TRUE),
color = "red", linetype = "dashed", size = 0.8) +
# 🟠 Lớp 5: Chú thích trung bình cho từng hãng
geom_text(data = avg_points,
aes(x = mean_distance, y = mean_delay, label = op_unique_carrier),
color = "black", size = 3, fontface = "bold", vjust = -1) +
# 🟡 Lớp 6: Tùy chỉnh chủ đề trực quan
theme_light(base_size = 12) +
# ⚫ Lớp 7: Tiêu đề, nhãn trục, chú giải
labs(title = "Mối quan hệ giữa khoảng cách, độ trễ và thời gian bay của các hãng hàng không",
subtitle = "Kích thước điểm thể hiện thời gian bay; màu sắc phân biệt theo hãng",
x = "Khoảng cách bay (miles)",
y = "Độ trễ khi đến (phút)",
color = "Hãng hàng không",
size = "Thời gian bay (phút)") +
theme(plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
plot.subtitle = element_text(size = 11, hjust = 0.5))
library(ggplot2)
library(dplyr)
table_dest <- flight_data_no_outlier %>%
group_by(dest, op_unique_carrier) %>%
summarise(Freq = n(), .groups = "drop")
top_dest <- table_dest %>%
group_by(dest) %>%
summarise(total = sum(Freq)) %>%
arrange(desc(total)) %>%
slice_head(n = 6) %>%
pull(dest)
dest_summary <- table_dest %>%
filter(dest %in% top_dest) %>%
group_by(dest) %>%
mutate(percentage = Freq / sum(Freq) * 100)
ggplot(dest_summary, aes(x = "", y = percentage, fill = op_unique_carrier)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
facet_wrap(~dest, ncol = 3) +
labs(title = "Tỷ trọng chuyến bay theo điểm đến và hãng hàng không (Top 6)",
fill = "Hãng hàng không", y = NULL, x = NULL) +
theme_void() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "bottom"
)
geom_text(aes(label = paste0(round(percentage, 1), "%")),
position = position_stack(vjust = 0.5),
size = 3, color = "white")
## mapping: label = ~paste0(round(percentage, 1), "%")
## geom_text: parse = FALSE, check_overlap = FALSE, size.unit = mm, na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_stack
Giải thích:
- dplyr:
dùng để gom nhóm, tóm tắt, lọc, và xử lý dữ liệu.
-
ggplot2: dùng để vẽ biểu đồ (ở đây là biểu đồ tròn theo
từng điểm đến).
- (group_by(dest,
op_unique_carrier) → nhóm dữ liệu theo điểm đến (dest) và hãng
hàng không (op_unique_carrier).
- summarise(Freq = n())
→ đếm số chuyến bay (n()) trong mỗi nhóm.
-
group_by(dest) và summarise(total = sum(Freq)) → tính
tổng số chuyến bay đến mỗi điểm đến.
-
arrange(desc(total)) → sắp xếp theo thứ tự giảm
dần.
- slice_head(n = 6) → chọn ra 6 điểm đến có
nhiều chuyến bay nhất.
- pull(dest) → lấy tên các
điểm đến đó để dùng tiếp.
- filter(dest %in%
top_dest) → chỉ giữ lại những dòng thuộc 6 điểm đến được
chọn.
- mutate(percentage = Freq / sum(Freq) *
100)→ tính tỷ lệ phần trăm số chuyến bay của từng hãng trong
cùng một điểm đến.
- aes(x = ““, y = percentage, fill =
op_unique_carrier) → Không cần trục x cụ thể (để trống), trục y
là phần trăm, màu theo hãng hàng không. - geom_col(width = 1,
color =”white”) Tạo các cột (dạng “miếng bánh”), viền trắng để
dễ phân biệt.
- coord_polar(theta = “y”): Biến biểu
đồ cột thành biểu đồ tròn (pie chart). - facet_wrap(~dest, ncol
= 3) Vẽ nhiều biểu đồ tròn, mỗi biểu đồ tương ứng với một điểm
đến (tối đa 6 điểm, chia thành 3 cột).
- labs():
Đặt tiêu đề và chú thích.
- theme_void(): Loại bỏ
trục, khung, lưới (làm biểu đồ tròn gọn gàng hơn).
-
theme(…): Căn giữa tiêu đề, in đậm, điều chỉnh vị trí
chú thích ở phía dưới.
Nhận xét: Biểu đồ trên thể hiện cơ cấu thị
phần chuyến bay của các hãng hàng không đến 6 điểm đến có lượng chuyến
bay cao nhất trong bộ dữ liệu. Mỗi hình tròn biểu thị một điểm đến là
ATL, CLT, DEN, DFW, ORD, PHX, trong đó các lát cắt thể hiện tỷ trọng (%)
chuyến bay của từng hãng hàng không tại điểm đến đó.
- Các màu sắc
khác nhau đại diện cho từng hãng hàng không, giúp dễ dàng so sánh mức độ
hoạt động của từng hãng ở mỗi sân bay.
- Biểu đồ cho thấy tại một
số sân bay lớn như ATL, CLT, DFW, có một hãng hàng không chiếm ưu thế rõ
rệt, thể hiện tính tập trung cao trong khai thác chuyến bay.
-
Ngược lại, ở các sân bay như ORD hoặc PHX, tỷ lệ các hãng phân bố đa
dạng hơn, thể hiện mức cạnh tranh cao hơn giữa các hãng.
- Việc
phân tích tỷ trọng này giúp xác định sân bay “trọng điểm” của từng hãng
hàng không, cũng như đánh giá mức độ tập trung hay phân tán trong mạng
lưới bay nội địa.