我正在尝试使用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的方式,使我的例子更加通用。
答案 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)
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方法可能是一个更好的方法。尽管过时可能要过几年,否则很可能要花费很多年。但是,在决定是否将其用作工具时,要记住一些注意事项。