GIỚI THIỆU

Xin chào các bạn, trong quá trình phân tích dữ liệu, mình cần chuyển đổi tất cả các giá trị trong 1 cột thành nhiều cột. Đồng thời điền vào giá trị là 1 hoặc 0 tương ứng. Để thực hiện được yêu cầu này mình đã tổng hợp được một số cách để chuyển đổi với phần mềm R như sau đây.

THỰC HIỆN

Dữ liệu

Mình có dữ liệu ví dụ như data.frame df. Trong đó cột flower_color có 4 giá trị là: do, xanh, vang, trang. Yêu cầu tách 4 giá trị này thành 4 cột tương ứng

df
  id flower_color
1  1           do
2  2         xanh
3  3         vang
4  4        trang

Với lệnh model.matrix đã được load sẵn trong R

df1=model.matrix(~id+flower_color-1, df)
df1=as.data.frame(df1)
df1
  id flower_colordo flower_colortrang flower_colorvang flower_colorxanh
1  1              1                 0                0                0
2  2              0                 0                0                1
3  3              0                 0                1                0
4  4              0                 1                0                0

Với lệnh dummy.data.framedummy trong package dummies

library(dummies)
#dummy(df$flower_color)
dummy.data.frame(df, sep="_")
  id flower_color_do flower_color_trang flower_color_vang
1  1               1                  0                 0
2  2               0                  0                 0
3  3               0                  0                 1
4  4               0                  1                 0
  flower_color_xanh
1                 0
2                 1
3                 0
4                 0

Với lệnh dummy.code trong package psych

library(psych)
df1=cbind(df,dummy.code(df$flower_color))
df1
  id flower_color do trang vang xanh
1  1           do  1     0    0    0
2  2         xanh  0     0    0    1
3  3         vang  0     0    1    0
4  4        trang  0     1    0    0

Với lệnh dcast trong package reshape2

library(reshape2)
dcast(df,id~ flower_color, length)
  id do trang vang xanh
1  1  1     0    0    0
2  2  0     0    0    1
3  3  0     0    1    0
4  4  0     1    0    0

Với lệnh acm.disjonctif trong package ade4

library(ade4)
acm.disjonctif(df[2])
  flower_color.do flower_color.trang flower_color.vang flower_color.xanh
1               1                  0                 0                 0
2               0                  0                 0                 1
3               0                  0                 1                 0
4               0                  1                 0                 0

Với lệnh for

for(level in unique(df$flower_color)){
    df[paste("dummy", level, sep = "_")] <- ifelse(df$flower_color == level, 1, 0)
}
df
  id flower_color dummy_do dummy_xanh dummy_vang dummy_trang
1  1           do        1          0          0           0
2  2         xanh        0          1          0           0
3  3         vang        0          0          1           0
4  4        trang        0          0          0           1

Trường hợp đặc biệt

Như vậy có rất nhiều cách để thực hiện việc này một cách dễ dàng đối với R. Tuy nhiên trường hợp của mình phức tạp hơn ví dụ trên. Trường hợp của mình có nhiều giá trị trong cùng một ô. Ví dụ như data sau: id4 có 3 giá trị, id5 có 2 giá trị

flower_color=c("do","xanh","vang","do;trang;xanh", "xanh;vang")
id=c(1,2,3,4,5)
df=data.frame(id,flower_color)
df
  id  flower_color
1  1            do
2  2          xanh
3  3          vang
4  4 do;trang;xanh
5  5     xanh;vang

Nếu mình sử dụng cách ở trên thì R sẽ hiểu 3 giá trị do;trang;xanh là 1 giá trị. VD:

dcast(df,id~ flower_color, length)
  id do do;trang;xanh vang xanh xanh;vang
1  1  1             0    0    0         0
2  2  0             0    0    1         0
3  3  0             0    1    0         0
4  4  0             1    0    0         0
5  5  0             0    0    0         1

Hiện tại mình chưa tìm được lệnh nào nên tạm thời đã tự viết một function: b.dummy() để thực hiện cho trường hợp này của mình. script của function như sau:

b.dummy=function(df, col,sep=';'){
    column=df[,col]
    #Ham lay gia tri trong cot
    b.get.value=function(list,sep=";")
    {
        a=paste(list,collapse = sep)
        b=strsplit(a,sep)
        c=unique(b[[1]])
        return(c)
    }
    #Tao mang chua cac gia tri
    arr=b.get.value(column,sep)

    #thuc hien vong lap for
    for(level in unique(arr)){
        i=1
        for (values in  column)
        {
            values=as.character(values)
            value_list=strsplit(values,sep)
            for (value in value_list[[1]])
            {
                if(value==level){
                    df[i,paste("dummy", level, sep = "_")] =1
                    break
                }
                else
                {
                    df[i,paste("dummy", level, sep = "_")] =0
                }
            }
            i=i+1
        }
    }
    return(df)
}

Chạy function b.dummy với df=data.frame, col: tên cột cần tách, sep: dấu dùng để tách các giá trị. Trong trường hợp của mình sep=";".

b.dummy(df,"flower_color",";")
  id  flower_color dummy_do dummy_xanh dummy_vang dummy_trang
1  1            do        1          0          0           0
2  2          xanh        0          1          0           0
3  3          vang        0          0          1           0
4  4 do;trang;xanh        1          1          0           1
5  5     xanh;vang        0          1          1           0

Hàm mình viết ra tạm thời chạy ổn với trường hợp trên. Nếu bạn nào có cách nào khác xin gởi thông tin cho mình tham khảo. Cảm ơn các bạn