使用data.table重新编码变量

时间:2017-06-16 13:48:16

标签: r data.table recode

我正在尝试使用data.table重新编码变量。我用谷歌搜索了近2个小时但找不到答案。

假设我有一个data.table如下:

DT <- data.table(V1=c(0L,1L,2L),
                 V2=LETTERS[1:3],
                 V4=1:12)

我想重新编码V1和V2。对于V1,我想将1s重新编码为0,将2s重新编码为1。 对于V2,我想重新编码A到T,B到K,C到D。

如果我使用dplyr,则很简单。

library(dplyr)
DT %>% 
  mutate(V1 = recode(V1, `1` = 0L, `2` = 1L)) %>% 
  mutate(V2 = recode(V2, A = "T", B = "K", C = "D"))

但我不知道如何在data.table中执行此操作

DT[V1==1, V1 := 0]
DT[V1==2, V1 := 1]
DT[V2=="A", V2 := "T"]
DT[V2=="B", V2 := "K"]
DT[V2=="C", V2 := "D"]

以上是我认为最好的代码。但必须有更好,更有效的方法来做到这一点。

修改

我改变了我想重新编码V2的方式,使我的例子更加通用。

3 个答案:

答案 0 :(得分:8)

使用data.table可以通过更新加入解决重新编码:

DT[.(V1 = 1:2, to = 0:1), on = "V1", V1 := i.to]
DT[.(V2 = LETTERS[1:3], to = c("T", "K", "D")), on = "V2", V2 := i.to]

DT转换为

    V1 V2 V4
 1:  0  T  1
 2:  0  K  2
 3:  1  D  3
 4:  0  T  4
 5:  0  K  5
 6:  1  D  6
 7:  0  T  7
 8:  0  K  8
 9:  1  D  9
10:  0  T 10
11:  0  K 11
12:  1  D 12

修改:@Frank建议使用i.to为安全起见。

解释

表达式.(V1 = 1:2, to = 0:1).(V2 = LETTERS[1:3], to = c("T", "K", "D")),分别创建查找表即时

或者,可以事先设置查找表

lut1 <- data.table(V1 = 1:2, to = 0:1)
lut2 <- data.table(V2 = LETTERS[1:3], to = c("T", "K", "D"))

lut1
   V1 to
1:  1  0
2:  2  1
lut2
   V2 to
1:  A  T
2:  B  K
3:  C  D

然后,更新加入变为

DT[lut1, on = "V1", V1 := i.to]
DT[lut2, on = "V2", V2 := i.to]

答案 1 :(得分:7)

我认为这可能就是你要找的东西。在:=的左侧,我们命名要更新的变量,在右侧,我们有我们想要更新相应变量的表达式。

DT[, c("V1","V2") := .(as.numeric(V1==2), sapply(V2, function(x) {if(x=="A") "T" 
                                                     else if (x=="B") "K" 
                                                     else if (x=="C") "D" }))]

 #   V1 V2 V4
 #1:  0  T  1
 #2:  0  K  2
 #3:  1  D  3
 #4:  0  T  4
 #5:  0  K  5
 #6:  1  D  6
 #7:  0  T  7
 #8:  0  K  8
 #9:  1  D  9
#10:  0  T 10
#11:  0  K 11
#12:  1  D 12

或者,只需在recode中使用data.table

library(dplyr)
DT[, c("V1","V2") := .(as.numeric(V1==2), recode(V2, "A" = "T", "B" = "K", "C" = "D"))]

答案 2 :(得分:1)

plyr的

mapvalues()与data.table结合使用非常好。

我在大型数据(50 mio-400 mio行)上使用它。尽管我没有将它与其他可能性进行基准测试,但是我发现清晰的语法非常有价值,因为这意味着复杂的重新编码操作中的错误更少。

library(data.table)
library(plyr)


DT <- data.table(V1=c(0L,1L,2L),
                 V2=LETTERS[1:3],
                 V4=1:12)


DT[, V1 := mapvalues(V1, from=c(1, 2), to=c(0, 1))]
DT[, V2 := mapvalues(V2, from=c('A', 'B', 'C'), to=c('T', 'K', 'D'))]

对于更复杂的重新编码操作,我将始终首先使用NA创建一个新变量,并使用另一个带有from-to向量的data.table作为变量。

在某些用例中,更多的错误是它的功能是mapvalues()保留旧变量中的那些值,而这些旧变量不在from参数中。 如果您确定所有正确的值都在from向量中,那么这是一个问题,因此data.table中不在此向量中的所有值都应改为NA。

DT <- data.table(V1=c(LETTERS[1:3], 'i dont want this value transfered'),
                 V4=1:12)
map_DT <- data.table(from=c('A', 'B', 'C'), to=c('T', 'K', 'D'))


# NA variable to begin with is good practice because it is clearer to spot an error  
DT[, V1_new := NA_character_]
DT[V1 %in% map_DT$from , V1_new := mapvalues(V1, from=map_DT$from, to=map_DT$to)][]

请注意,不推荐使用plyr,因此mapvalues函数在将来的某个时候可能会消失。由于这个原因,尽管我发现mapvalues只是读起来有点不清晰,所以建议的update-joins方法可能是一个更好的方法。尽管过时可能要过几年,否则很可能要花费很多年。但是,在决定是否将其用作工具时,要记住一些注意事项。