Tác giả: Nguyễn Hải Trường | 2019-01-15
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, Ranalytics
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: 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, Ranalytics
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 12 <NA>
## 5 Ha 23 7 Bac Giang
## 6 Giang 23 9 Bac Ninh
## 7 Bac 24 11 Yen Bai
## 8 Ninh NA 10 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 : Factor w/ 9 levels "Bac","Giang",..: 9 6 4 8 3 2 1 7 3 5
## $ age : num 22 23 25 24 23 23 24 NA NA NA
## $ income_mil_VND: num NA NA 15 12 7 9 11 10 80 NA
## $ province : Factor w/ 9 levels "Bac Giang","Bac Ninh",..: 6 4 5 NA 1 2 9 3 8 7
data %>% summary
## name age income_mil_VND province
## Ha :2 Min. :22.00 Min. : 7.00 Bac Giang:1
## Bac :1 1st Qu.:23.00 1st Qu.: 9.50 Bac Ninh :1
## Giang :1 Median :23.00 Median :11.00 Ca Mau :1
## Hai :1 Mean :23.43 Mean :20.57 Ha Noi :1
## Long :1 3rd Qu.:24.00 3rd Qu.:13.50 Hai Duong:1
## Nam :1 Max. :25.00 Max. :80.00 (Other) :4
## (Other):3 NA's :3 NA's :3 NA's :1
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 12 <NA> 24
## 5 Ha 23 7 Bac Giang 23
## 6 Giang 23 9 Bac Ninh 23
## 7 Bac 24 11 Yen Bai 24
## 8 Ninh NA 10 Ca Mau 24
## 9 Ha NA 80 Quang Ninh 24
## 10 Long NA NA Quang Binh 24
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.4285714 làm tròn thành 24).
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 13.5 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 12 <NA> 24 12
## 5 Ha 23 7 Bac Giang 23 7
## 6 Giang 23 9 Bac Ninh 23 9
## 7 Bac 24 11 Yen Bai 24 11
## 8 Ninh NA 10 Ca Mau 24 10
## 9 Ha NA 80 Quang Ninh 24 80
## 10 Long NA NA Quang Binh 24 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 7 Bac Giang 23 7
## 5 Giang 23 9 Bac Ninh 23 9
## 6 Bac 24 11 Yen Bai 24 11
## 7 Ninh NA 10 Ca Mau 24 10
## 8 Ha NA 80 Quang Ninh 24 80
## 9 Long NA NA Quang Binh 24 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 12 Missing
## 5 Ha 23 7 Bac Giang
## 6 Giang 23 9 Bac Ninh
## 7 Bac 24 11 Yen Bai
## 8 Ninh 24 10 Ca Mau
## 9 Ha 24 80 Quang Ninh
## 10 Long 24 11 Quang Binh
Như vậy, 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ả với Ranalytics.vn
!