Trong quá trình xử lý, làm sạch dữ liệu, chúng ta sẽ thường gặp phải
vấn đề dữ liệu bị missing. Nguyên nhân có thể do dữ liệu không đầy đủ
hoặc có sai sót trong quá trình nhập liệu… Trong bài viết này, mình sẽ
hướng dẫn các bạn một số mẹo để xử lý giá trị missing (missing values)
trong R.
Vậy, làm thế nào để xử lý missing values?
Câu trả lời là: Trước tiên cần phải hiểu rõ bản chất của missing values, rồi sau đó sẽ đưa ra giải pháp phù hợp để xử lý missing values.
Thông thường, có 2 cách để xử lý missing values:
Cách 1: Loại bỏ missing values
(trong trường hợp missing values đó không quan trọng đối với dữ liệu của
chúng ta hoặc số lượng missing values quá ít - chỉ chiếm khoảng dưới 3%
tổng số quan sát trong 1 biến nhất định).
Cách 2: Thay thế missing values
bằng một giá trị khác. Việc thay thế bằng giá trị nào sẽ phụ thuộc vào
việc bản chất của missing values trong những trường hợp đó là
gì.
Câu hỏi đặt ra lúc này là: Vậy thì nếu cần phải thay thế missing values bằng một giá trị khác, thì nên thay thế bằng giá trị nào?
Câu trả lời là:
Trường hợp biến có missing values là biến số - numeric
variable: Có thể thay thế missing values bằng những giá trị
như: 0, median, mean, v.v. tùy
vào từng trường hợp nhất định.
Trường hợp biến có missing values là biến
categorical: Có thể nhóm những trường hợp missing
values vào 1 nhóm, đặt tên là Missing.
Sau đây, mình sẽ hướng dẫn các bạn xử lý những trường hợp missing
values nêu trên bằng R, sử dụng dữ liệu giả lập sau:
data <- data.frame(
name = c("Viet", "Nam", "Hai", "Phong", "Ha", "Giang", "Bac", "Ninh", "Ha", "Long"),
age = as.numeric(c(sample(22:25, 7, replace=TRUE),NA,NA,NA)),
income_mil_VND = c(NA, NA, sample(6:15, 6, replace = FALSE),80, NA),
province = c("Hai Phong", "Ha Noi", "Hai Duong", NA, "Bac Giang",
"Bac Ninh", "Yen Bai", "Ca Mau", "Quang Ninh", "Quang Binh")
)
data## name age income_mil_VND province
## 1 Viet 22 NA Hai Phong
## 2 Nam 23 NA Ha Noi
## 3 Hai 25 15 Hai Duong
## 4 Phong 24 13 <NA>
## 5 Ha 23 9 Bac Giang
## 6 Giang 22 8 Bac Ninh
## 7 Bac 22 11 Yen Bai
## 8 Ninh NA 6 Ca Mau
## 9 Ha NA 80 Quang Ninh
## 10 Long NA NA Quang Binh
Dữ liệu bao gồm thông tin về thu nhập hàng tháng (triệu đồng) và quê quán của 10 người có độ tuổi từ 22-25.
Summary dữ liệu, chúng ta có kết quả sau:
library(dplyr)
data %>% str## 'data.frame': 10 obs. of 4 variables:
## $ name : chr "Viet" "Nam" "Hai" "Phong" ...
## $ age : num 22 23 25 24 23 22 22 NA NA NA
## $ income_mil_VND: num NA NA 15 13 9 8 11 6 80 NA
## $ province : chr "Hai Phong" "Ha Noi" "Hai Duong" NA ...
data %>% summary## name age income_mil_VND province
## Length:10 Min. :22.0 Min. : 6.00 Length:10
## Class :character 1st Qu.:22.0 1st Qu.: 8.50 Class :character
## Mode :character Median :23.0 Median :11.00 Mode :character
## Mean :23.0 Mean :20.29
## 3rd Qu.:23.5 3rd Qu.:14.00
## Max. :25.0 Max. :80.00
## NA's :3 NA's :3
Biến tuổi (age) và biến thu nhập
(income_mil_VND) đều có 3 quan sát bị missing
(NA) trên tổng số 10 quan sát -> tỷ lệ quan sát bị
missing là 30%, vì vậy chúng ta cần phải thay thế những giá trị bị
missing này bằng 1 giá trị nào đó khác.
Đối với biến tuổi, qua 1 số chỉ số thống kê cơ bản ở trên chúng ta có
thể thấy không có sự chênh lệnh đáng kể về độ tuổi giữa những quan sát,
không có trường hợp “outlier”, do vậy, chúng ta có thể thay thế những
giá trị missing của biến tuổi bằng giá trị trung bình
(mean).
data <- data %>%
# Tạo thêm biến mới (age_new) để có thể so sánh với biến cũ (age)
mutate(age_new = case_when(
is.na(age) ~ ceiling(mean(age, na.rm = T)),
TRUE ~ age
))
data## name age income_mil_VND province age_new
## 1 Viet 22 NA Hai Phong 22
## 2 Nam 23 NA Ha Noi 23
## 3 Hai 25 15 Hai Duong 25
## 4 Phong 24 13 <NA> 24
## 5 Ha 23 9 Bac Giang 23
## 6 Giang 22 8 Bac Ninh 22
## 7 Bac 22 11 Yen Bai 22
## 8 Ninh NA 6 Ca Mau 23
## 9 Ha NA 80 Quang Ninh 23
## 10 Long NA NA Quang Binh 23
Như vậy, missing values của biến tuổi đã được thay thế bằng giá trị trung bình của biến tuổi (mean = 23 làm tròn thành 23).
Còn đối với biến thu nhập, chúng ta thấy rằng 3/4 số người có mức thu
nhập hàng tháng dưới 14 triệu đồng, trong khi đó có 1 người thu nhập lên
đến 80 triệu đồng/tháng (outlier). Do đó, chúng ta không nên thay thế
missing values của biến thu nhập bằng giá trị trung bình như trường hợp
biến tuổi, vì điều đó sẽ không phản ánh đúng bản chất của dữ liệu. Thay
vào đó, chúng ta nên thay thế missing values trong trường hợp này bằng
giá trị trung vị (median).
data <- data %>%
# Thêm biến mới (income_new)
mutate(income_new = case_when(
is.na(income_mil_VND) ~ median(income_mil_VND, na.rm=T),
TRUE ~ income_mil_VND
))
data## name age income_mil_VND province age_new income_new
## 1 Viet 22 NA Hai Phong 22 11
## 2 Nam 23 NA Ha Noi 23 11
## 3 Hai 25 15 Hai Duong 25 15
## 4 Phong 24 13 <NA> 24 13
## 5 Ha 23 9 Bac Giang 23 9
## 6 Giang 22 8 Bac Ninh 22 8
## 7 Bac 22 11 Yen Bai 22 11
## 8 Ninh NA 6 Ca Mau 23 6
## 9 Ha NA 80 Quang Ninh 23 80
## 10 Long NA NA Quang Binh 23 11
Như vậy, missing values của biến thu nhập đã được thay thế bằng giá trị trung vị của biến thu nhập (median = 11).
Trường hợp cuối cùng, đối với biến quê quán (province),
chỉ có 1 missing values. Nếu như chúng ta thấy rằng quan sát này không
quan trọng thì có thể loại bỏ quan sát này, bằng câu lệnh sau đây:
data2 <- data %>%
# Chỉ lấy những quan sát mà province không bị missing
filter(!is.na(province))
data2## name age income_mil_VND province age_new income_new
## 1 Viet 22 NA Hai Phong 22 11
## 2 Nam 23 NA Ha Noi 23 11
## 3 Hai 25 15 Hai Duong 25 15
## 4 Ha 23 9 Bac Giang 23 9
## 5 Giang 22 8 Bac Ninh 22 8
## 6 Bac 22 11 Yen Bai 22 11
## 7 Ninh NA 6 Ca Mau 23 6
## 8 Ha NA 80 Quang Ninh 23 80
## 9 Long NA NA Quang Binh 23 11
Như vậy, chúng ta đã vừa bỏ đi 1 quan sát của tập dữ liệu (từ 10 quan sát còn 9).
Có 1 cách khác để xử lý missing values trong trường hợp này mà các
bạn có thể sử dụng trong trường hợp các bạn vẫn muốn giữ lại quan sát
nói trên. Đó là nhóm quan sát bị missing vào 1 nhóm tên là
Missing như sau:
data <- data %>%
# Do biến province là biến factor, nên chúng ta cần transform biến này về dạng character trước
mutate(province = province %>% as.character) %>%
# Tạo thêm biến mới (province_new)
mutate(province_new = case_when(
is.na(province) ~ "Missing",
TRUE ~ province
) %>% as.factor)Như vậy, chúng ta đã vừa thay thế giá trị missing của biến quê quán
(province) thành Missing.
Sau khi làm sạch dữ liệu, chúng ta có thể loại bỏ những biến cũ
age, income_mil_VND và province
đi để dữ liệu được clean.
data <- data %>%
select(-c(age,income_mil_VND,province))
data## name age_new income_new province_new
## 1 Viet 22 11 Hai Phong
## 2 Nam 23 11 Ha Noi
## 3 Hai 25 15 Hai Duong
## 4 Phong 24 13 Missing
## 5 Ha 23 9 Bac Giang
## 6 Giang 22 8 Bac Ninh
## 7 Bac 22 11 Yen Bai
## 8 Ninh 23 6 Ca Mau
## 9 Ha 23 80 Quang Ninh
## 10 Long 23 11 Quang Binh
Vừa rồi, chúng ta đã được làm quen với một số tricks để xử lý missing values.
Chúc các bạn học tập và làm việc hiệu quả!