1. Thông tin cơ bản về bộ dữ liệu

1.1 Nạp các thư viện cần thiết

library(tidyverse)
library(dplyr)      
library(ggplot2)    
library(readxl)

1.2 Đọc file dữ liệu

d <- read_excel("C:/Users/hoang/Downloads/US_Accidents_March23_reduced_500k_pd.xlsx")

Bộ dữ liệu về US_Accidents gồm có 500.001 dữ liệu, trong đó có các biến (Mã định danh duy nhất cho mỗi vụ tai nạn, Nguồn thu thập dữ liệu, Mức độ nghiêm trọng của tai nạn (1–4), Vĩ độ, Kinh độ, Tên đường, Thành phố, Quận, Bang, Mã bưu điện, Quốc gia, Mã sân bay, Nhiệt độ, Độ ẩm, Áp suất khí quyển, Tầm nhìn, Hướng gió, Tốc độ gió, Tình trạng thời tiết).

2. Tổng quan dữ liệu

2.1 Xem kích thước bộ dữ liệu

dim(d)
## [1] 500001     19

Bộ dữ liệu có 500001 quan sát và 19 biến

2.2 Xem có những cột nào trong data.frame

str(d) 
## tibble [500,001 × 19] (S3: tbl_df/tbl/data.frame)
##  $ ID               : chr [1:500001] "A-1" "A-2" "A-3" "A-4" ...
##  $ Source           : chr [1:500001] "Source2" "Source2" "Source2" "Source2" ...
##  $ Severity         : num [1:500001] 3 2 2 3 2 3 2 3 2 3 ...
##  $ Start_Lat        : num [1:500001] 39.9 39.9 39.1 39.7 39.6 ...
##  $ Start_Lng        : num [1:500001] -84.1 -82.8 -84 -84.2 -84.2 ...
##  $ Street           : chr [1:500001] "I-70 E" "Brice Rd" "State Route 32" "I-75 S" ...
##  $ City             : chr [1:500001] "Dayton" "Reynoldsburg" "Williamsburg" "Dayton" ...
##  $ County           : chr [1:500001] "Montgomery" "Franklin" "Clermont" "Montgomery" ...
##  $ State            : chr [1:500001] "OH" "OH" "OH" "OH" ...
##  $ Zipcode          : chr [1:500001] "45424" "43068-3402" "45176" "45417" ...
##  $ Country          : chr [1:500001] "US" "US" "US" "US" ...
##  $ Airport_Code     : chr [1:500001] "KFFO" "KCMH" "KI69" "KDAY" ...
##  $ Temperature(F)   : num [1:500001] 36.9 37.9 36 35.1 36 37.9 34 34 33.3 37.4 ...
##  $ Humidity(%)      : num [1:500001] 91 100 100 96 89 97 100 100 99 100 ...
##  $ Pressure(in)     : num [1:500001] 29.7 29.6 29.7 29.6 29.6 ...
##  $ Visibility(mi)   : num [1:500001] 10 10 10 9 6 7 7 7 5 3 ...
##  $ Wind_Direction   : chr [1:500001] "Calm" "Calm" "SW" "SW" ...
##  $ Wind_Speed(mph)  : num [1:500001] 4.6 1.2 3.5 4.6 3.5 3.5 3.5 3.5 1.2 4.6 ...
##  $ Weather_Condition: chr [1:500001] "Light Rain" "Light Rain" "Overcast" "Mostly Cloudy" ...

Bộ dữ liệu có 500.001 quan sát và 19 biến.

Các biến bao gồm thông tin về địa điểm (thành phố, tiểu bang, tọa độ), điều kiện thời tiết (nhiệt độ, độ ẩm, áp suất, tầm nhìn, hướng gió, tốc độ gió) và mức độ nghiêm trọng của tai nạn (Severity).

Dữ liệu gồm cả biến định tính (chuỗi ký tự như City, State, Weather_Condition) và biến định lượng (các giá trị số như Temperature, Humidity, Pressure).

Nhìn chung, cấu trúc dữ liệu đầy đủ, phù hợp để thực hiện các bước xử lý, phân tổ và phân tích thống kê tiếp theo.

2.3 Tên và ý nghĩa các biến

names(d)
##  [1] "ID"                "Source"            "Severity"         
##  [4] "Start_Lat"         "Start_Lng"         "Street"           
##  [7] "City"              "County"            "State"            
## [10] "Zipcode"           "Country"           "Airport_Code"     
## [13] "Temperature(F)"    "Humidity(%)"       "Pressure(in)"     
## [16] "Visibility(mi)"    "Wind_Direction"    "Wind_Speed(mph)"  
## [19] "Weather_Condition"
data.frame(
  Variable = c("ID","Severity","Start_Lat","Start_Lng","Street","City","County","State","Zipcode","Country","Airport_Code","Temperature(F)","Humidity(%)","Pressure(in)","Visibility(mi)","Wind_Direction","Wind_Speed(mph)","Weather_Condition"),
  Meaning = c("Mã định danh duy nhất cho từng vụ tai nạn",
              "Mức độ nghiêm trọng của vụ tai nạn (1 = nhẹ nhất, 4 = nghiêm trọng nhất)",
              "Vĩ độ nơi bắt đầu vụ tai nạn (Latitude)",
              "Kinh độ nơi bắt đầu vụ tai nạn (Longitude)",
              "Tên con đường xảy ra tai nạn",
              "Thành phố nơi tai nạn được ghi nhận",
              "Hạt (County) quản lý khu vực xảy ra tai nạn",
              "Bang (State) nơi xảy ra tai nạn (ký hiệu 2 chữ viết tắt)",
              "Mã bưu chính của khu vực tai nạn",
              "Quốc gia xảy ra tai nạn (thường là US)",
              "Mã sân bay gần nhất (tham chiếu vị trí tai nạn)",
              "Nhiệt độ (độ F) tại thời điểm tai nạn",
              "Độ ẩm không khí (%) tại thời điểm tai nạn",
              "Áp suất khí quyển (inch thủy ngân)",
              "Tầm nhìn của tài xế (mile)",
              "Hướng gió tại thời điểm tai nạn (ví dụ: N, SW, E...)",
              "Tốc độ gió (mile/giờ)",
              "Điều kiện thời tiết (ví dụ: Rain, Clear, Fog, Snow...)"),
  stringsAsFactors = FALSE)

2.4 Thống kê mô tả cơ bản

summary(d)
##       ID               Source             Severity       Start_Lat    
##  Length:500001      Length:500001      Min.   :1.000   Min.   :25.43  
##  Class :character   Class :character   1st Qu.:2.000   1st Qu.:32.81  
##  Mode  :character   Mode  :character   Median :2.000   Median :34.25  
##                                        Mean   :2.375   Mean   :35.93  
##                                        3rd Qu.:3.000   3rd Qu.:40.13  
##                                        Max.   :4.000   Max.   :48.20  
##                                                                       
##    Start_Lng          Street              City              County         
##  Min.   :-123.81   Length:500001      Length:500001      Length:500001     
##  1st Qu.:-118.10   Class :character   Class :character   Class :character  
##  Median : -95.54   Mode  :character   Mode  :character   Mode  :character  
##  Mean   : -97.59                                                           
##  3rd Qu.: -81.57                                                           
##  Max.   : -70.57                                                           
##                                                                            
##     State             Zipcode            Country          Airport_Code      
##  Length:500001      Length:500001      Length:500001      Length:500001     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##  Temperature(F)    Humidity(%)      Pressure(in)   Visibility(mi)   
##  Min.   :-77.80   Min.   :  4.00   Min.   : 0.12   Min.   :  0.000  
##  1st Qu.: 55.00   1st Qu.: 49.00   1st Qu.:29.90   1st Qu.: 10.000  
##  Median : 66.20   Median : 66.00   Median :30.00   Median : 10.000  
##  Mean   : 64.67   Mean   : 64.53   Mean   :30.00   Mean   :  9.228  
##  3rd Qu.: 77.00   3rd Qu.: 82.00   3rd Qu.:30.11   3rd Qu.: 10.000  
##  Max.   :161.60   Max.   :100.00   Max.   :33.04   Max.   :111.000  
##  NA's   :7237     NA's   :7902     NA's   :5730    NA's   :10530    
##  Wind_Direction     Wind_Speed(mph)  Weather_Condition 
##  Length:500001      Min.   :  0.00   Length:500001     
##  Class :character   1st Qu.:  5.80   Class :character  
##  Mode  :character   Median :  8.10   Mode  :character  
##                     Mean   :  8.91                     
##                     3rd Qu.: 11.50                     
##                     Max.   :822.80                     
##                     NA's   :89030

Kết quả thống kê mô tả cho thấy bộ dữ liệu có các biến định lượng như Severity, Temperature(F), Humidity(%), Pressure(in), Visibility(mi), Wind_Speed(mph) và nhiều biến định tính về địa điểm, thời tiết.

Mức độ nghiêm trọng (Severity) dao động từ 1-4, với giá trị trung bình khoảng 2,37. Cho thấy phần lớn các vụ tai nạn có mức độ trung bình.

Nhiệt độ trung bình khoảng 64,7°F, dao động khá rộng từ -77,8°F đến 161,6°F, thể hiện dữ liệu thu thập trên nhiều vùng khí hậu khác nhau.

Độ ẩm trung bình khoảng 64,5%, cao nhất là 100%.

Áp suất trung bình quanh mức 30 inHg, trong khoảng hợp lý của điều kiện khí quyển thông thường.

Tầm nhìn (Visibility) chủ yếu quanh 10 dặm, nhưng có giá trị cực đại bất thường 111 dặm, có thể là ngoại lệ.

Tốc độ gió trung bình 8,9 mph, tuy nhiên có giá trị lớn nhất 822,8 mph, nhiều khả năng là dữ liệu lỗi cần xử lý.

Một số biến như Temperature(F), Humidity(%), Pressure(in), Visibility(mi), Wind_Speed(mph) có giá trị bị thiếu (NA).

Nhìn chung, dữ liệu có phân bố hợp lý, nhưng cần xử lý giá trị thiếu và loại bỏ các giá trị ngoại lai trước khi phân tích tiếp theo.

3. Xử lý dữ liệu bị thiếu và trùng

3.1 Kiểm tra giá trị bị thiếu

colSums(is.na(d))
##                ID            Source          Severity         Start_Lat 
##                 0                 0                 0                 0 
##         Start_Lng            Street              City            County 
##                 0                 0                22                 0 
##             State           Zipcode           Country      Airport_Code 
##                 0                58                 0                60 
##    Temperature(F)       Humidity(%)      Pressure(in)    Visibility(mi) 
##              7237              7902              5730             10530 
##    Wind_Direction   Wind_Speed(mph) Weather_Condition 
##              4139             89030             10176

Kết quả kiểm tra giá trị khuyết cho thấy bộ dữ liệu có một số biến chứa nhiều giá trị bị thiếu (NA).

Các biến City, Zipcode, Airport_Code có một lượng nhỏ giá trị thiếu, dao động từ 22 đến 60 dòng, không đáng kể so với toàn bộ dữ liệu.

Tuy nhiên, các biến Temperature(F), Humidity(%), Pressure(in), Visibility(mi), Wind_Direction, Wind_Speed(mph), Weather_Condition có số lượng NA rất lớn (từ 4.000 đến gần 90.000 giá trị).

→ Điều này cho thấy dữ liệu thời tiết còn thiếu sót đáng kể, có thể do không thu thập được tại một số vị trí hoặc thời điểm.

→ Cần xử lý giá trị thiếu bằng cách xoá những dòng có NA trước khi tiến hành phân tích hoặc xây dựng mô hình thống kê.

3.2 Xoá những dòng có NA

ds <- na.omit(d)

3.3 Kiểm tra số quan sát bị trùng lặp

sum(duplicated(ds))
## [1] 0

Vậy không có giá trị nào trùng lặp

4. Phân tổ dữ liệu

4.1 Phân tổ theo nhiệt độ

ds <- ds %>%
  mutate(Temp_Group = cut(`Temperature(F)`,
                          breaks = c(-Inf, 32, 60, 80, Inf),
                          labels = c("Lạnh", "Mát", "Ấm", "Nóng")))
table(ds$Temp_Group) 
## 
##   Lạnh    Mát     Ấm   Nóng 
##  19339 112847 186719  86449

Nhóm “Ấm” (60–80°F) chiếm số vụ tai nạn cao nhất, cho thấy phần lớn tai nạn xảy ra trong điều kiện thời tiết dễ chịu và phổ biến — có thể vì đây là thời điểm có lưu lượng xe cao nhất (186719 vụ tai nạn).

Nhóm “Mát” (32–60°F) đứng thứ hai (112834 vụ tai nạn), cũng phản ánh điều kiện thời tiết thuận lợi cho việc di chuyển.

Nhóm “Nóng” (>80°F) chiếm tỷ lệ trung bình (86449 vụ tai nạn), có thể do ảnh hưởng của nhiệt độ cao làm giảm khả năng tập trung của tài xế.

Nhóm “Lạnh” (<32°F) có ít vụ tai nạn nhất (19339 vụ tai nạn), có thể vì ít phương tiện lưu thông trong điều kiện lạnh giá hoặc người dân hạn chế di chuyển.

4.2 Phân tổ độ ẩm

ds <- ds %>%
  mutate(Humi_Group = cut(`Humidity(%)`,
                          breaks = c(-Inf, 40, 70, Inf),
                          labels = c("Thấp", "Vừa", "Cao")))
table(ds$Humi_Group)
## 
##   Thấp    Vừa    Cao 
##  63881 182722 158751

Kết quả phân loại độ ẩm cho thấy phần lớn các vụ tai nạn xảy ra trong điều kiện độ ẩm trung bình (40–70%), với 182.722 vụ, chiếm khoảng 44,5% tổng số quan sát.

Tiếp theo là nhóm độ ẩm cao (>70%) với 158.738 vụ (khoảng 38,7%), phản ánh rằng khi độ ẩm tăng cao — thường kèm theo mưa hoặc sương mù — nguy cơ tai nạn vẫn đáng kể.

Ngược lại, nhóm độ ẩm thấp (<40%) chỉ ghi nhận 63.881 vụ (tương đương 15,6%) — mức thấp nhất, cho thấy điều kiện thời tiết khô ráo, tầm nhìn tốt giúp giảm rủi ro xảy ra tai nạn.

4.3 Đơn giản hóa điều kiện thời tiết

ds <- ds %>%
  mutate(Weather_Simple = case_when(
    str_detect(Weather_Condition, "Rain|Thunderstorm") ~ "Mưa",
    str_detect(Weather_Condition, "Snow|Sleet") ~ "Tuyết",
    str_detect(Weather_Condition, "Fog|Mist") ~ "Sương mù",
    str_detect(Weather_Condition, "Clear|Fair") ~ "Trời quang",
    str_detect(Weather_Condition, "Cloud|Overcast") ~ "Nhiều mây",
    TRUE ~ "Khác"
  ))
table(ds$Weather_Simple)
## 
##       Khác        Mưa  Nhiều mây   Sương mù      Tuyết Trời quang 
##       5552      25884     206798       1230       4182     161708

Kết quả cho thấy phần lớn các vụ tai nạn xảy ra trong nhóm “Khác” với 370.110 vụ, chiếm tỷ lệ áp đảo (trên 85%) — nhóm này chủ yếu bao gồm các điều kiện thời tiết bình thường hoặc không được ghi nhận rõ ràng.

Trong khi đó, điều kiện “Mưa” ghi nhận 25.875 vụ (khoảng 6%) — phản ánh rằng mặt đường trơn trượt và tầm nhìn kém có thể góp phần làm tăng rủi ro tai nạn.

Các điều kiện “Sương mù” (5.174 vụ, 1,2%) và “Tuyết” (4.182 vụ, 1%) có số lượng tương đối nhỏ, cho thấy các hiện tượng thời tiết cực đoan này ít xảy ra hơn, nhưng vẫn tiềm ẩn nguy hiểm cao khi xuất hiện.

5. Phân tích các biến trong dữ liệu

5.1 Biến theo nhiệt độ

ggplot(ds, aes(x = Temp_Group)) +
  geom_bar(fill = "tomato") +
  labs(title = "Phan bo nhiet do khi xay ra tai nan",
       x = "Nhóm nhiet do",
       y = "So luong vu tai nan")

5.2 Biến theo độ ẩm

ggplot(ds, aes(x = Humi_Group)) +
  geom_bar(fill = "skyblue") +
  labs(title = "Phan bo do am khi xay ra tai nan",
       x = "Nhom do am",
       y = "So luong vu tai nan")

5.3 Biến theo thời tiết

ggplot(ds, aes(x = Weather_Simple)) +
  geom_bar(fill = "orange") +
  labs(title = "Phan bo theo thoi tiet khi xay ra tai nan",
       x = "Nhom thoi tiet",
       y = "So luong vu tai nann")