File này bổ sung một số ý mà video Biến yếu tố là gì? https://www.youtube.com/watch?v=f_N3xgDCyjs chưa được trình bày đầy đủ về câu chuyện factor này.

Cụ thể, trong quá trình làm việc, bạn cần thay đổi levels cho các thành phần trong biến yếu tố factor thì việc set level sẽ ảnh hưởng đến cấu trúc của data frame làm thay đổi luôn vị trí của cột factor (!) còn các cột khác vẫn giữa nguyên.

Để khắc phục chuyện này ta cần chuyển levels ngay thời điểm chuyển factor (ngay trong lệnh factor()) chứ không nên tách ra hai bước tạo factor rồi mới set level là sẽ bị đổi thứ tự dòng.

Ta xét kỹ qua ví dụ sau:

## Bạn có 1 data frame như sau

df <- data.frame(x = c("a", "a", "a", "d", "d", "d", "c", "c", "c", "b", "b", "b"),
                 y = c("a1", "a2", "a3", "d1", "d2", "d3", "c1", "c2", "c3", "b1", "b2", "b3"),
                 z = c(101, 102, 103, 401, 402, 403, 301, 302, 303, 201, 202, 203)
                 )

df
##    x  y   z
## 1  a a1 101
## 2  a a2 102
## 3  a a3 103
## 4  d d1 401
## 5  d d2 402
## 6  d d3 403
## 7  c c1 301
## 8  c c2 302
## 9  c c3 303
## 10 b b1 201
## 11 b b2 202
## 12 b b3 203

Trường hợp 1: Dùng lệnh as.factor

Giờ mình sẽ chuyển cột x trong df thành factor.

df -> df1 ## Ta sẽ chuyển `factor` trên df1 để thuận tiện đối chiếu với df gốc.

df1$x <- as.factor(df1$x) ## sử dụng lệnh as.factor()

levels(df1$x) ## level của các thành phần trong df1$x được sắp xếp mặt định theo alphabet
## [1] "a" "b" "c" "d"
unclass(df1$x)
##  [1] 1 1 1 4 4 4 3 3 3 2 2 2
## attr(,"levels")
## [1] "a" "b" "c" "d"
df1 ## cấu trúc df1 và df y chang nhau.
##    x  y   z
## 1  a a1 101
## 2  a a2 102
## 3  a a3 103
## 4  d d1 401
## 5  d d2 402
## 6  d d3 403
## 7  c c1 301
## 8  c c2 302
## 9  c c3 303
## 10 b b1 201
## 11 b b2 202
## 12 b b3 203
identical(as.character(df$x), as.character(df1$x))
## [1] TRUE

Trường hợp 2: Dùng lệnh as.factor, kết hợp với levels

df -> df2 

df2$x <- as.factor(df2$x, levels = c("d", "c", "b", "a")) ## Sẽ bị lỗi, vì không gán levels vào trong lệnh as.factor() được
## Error in as.factor(df2$x, levels = c("d", "c", "b", "a")): unused argument (levels = c("d", "c", "b", "a"))

Trường hợp 3: Dùng lệnh as.factor trước, sau đó mới dùng levels

df -> df3 

df3$x <- as.factor(df3$x)

levels(df3$x) ## Mặc định thì levels của các thành phần trong x xếp theo alphabet
## [1] "a" "b" "c" "d"
levels(df3$x) <- c("d", "c", "b", "a") ## Giờ ta set levels theo trật tự ngược lại.

levels(df3$x) ## Xem levels sau khi thiết lập
## [1] "d" "c" "b" "a"
df3 ## cấu trúc df3 và df KHÁC NHAU!. Cột x thay đổi vị trí, còn các cột khác thì không.
##    x  y   z
## 1  d a1 101
## 2  d a2 102
## 3  d a3 103
## 4  a d1 401
## 5  a d2 402
## 6  a d3 403
## 7  b c1 301
## 8  b c2 302
## 9  b c3 303
## 10 c b1 201
## 11 c b2 202
## 12 c b3 203
identical(as.character(df$x), as.character(df3$x))
## [1] FALSE

Trường hợp 4: Dùng lệnh factor, kết hợp với levels

df -> df4 

df4$x <- factor(df4$x, levels = c("d", "c", "b", "a")) ## lệnh factor() cho phép gán levels ngay trong câu lệnh

df4 ## cấu trúc df4 và df y chang nhau.
##    x  y   z
## 1  a a1 101
## 2  a a2 102
## 3  a a3 103
## 4  d d1 401
## 5  d d2 402
## 6  d d3 403
## 7  c c1 301
## 8  c c2 302
## 9  c c3 303
## 10 b b1 201
## 11 b b2 202
## 12 b b3 203
identical(as.character(df$x), as.character(df4$x))
## [1] TRUE

Trường hợp 5: Dùng lệnh factor trước, sau đó mới dùng levels

df -> df5 

df5$x <- factor(df5$x)

levels(df5$x) ## Mặc định thì levels của các thành phần trong x xếp theo alphabet
## [1] "a" "b" "c" "d"
levels(df5$x) <- c("d", "c", "b", "a") ## Giờ ta set levels theo trật tự ngược lại.

levels(df5$x) ## Xem levels sau khi thiết lập
## [1] "d" "c" "b" "a"
df5 ## cấu trúc df5 và df KHÁC NHAU!. Cột x thay đổi vị trí, còn các cột khác thì không.
##    x  y   z
## 1  d a1 101
## 2  d a2 102
## 3  d a3 103
## 4  a d1 401
## 5  a d2 402
## 6  a d3 403
## 7  b c1 301
## 8  b c2 302
## 9  b c3 303
## 10 c b1 201
## 11 c b2 202
## 12 c b3 203
identical(as.character(df$x), as.character(df5$x))
## [1] FALSE

Như vậy qua các trường hợp ở trên thì chỉ có trường hợp 4 là chuyện set level (với thứ tự tùy ý) là thực hiện ổn nhất.

Dù vậy, việc tăng cường kiểm tra (check and double-check) cho từng dòng lệnh khi các bạn thao tác với factor là rất cần thiết vì đây là biến khá đặc biệt khi có hình thức là dạng character nhưng mode lại là numeric và R thao tác với factor thực chất là qua numeric tương ứng với các ký tự character của biến phân loại.

Sơ kết

Trên đây là lưu ý về việc set level trong biến factor. Để học R bài bản từ A đến Z, thân mời Bạn tham gia khóa học “HDSD R để xử lý dữ liệu” để có nền tảng vững chắc về R nhằm tự tay làm các câu chuyện dữ liệu của riêng mình!

ĐĂNG KÝ NGAY: https://www.tuhocr.com/register