一个相对常见的任务是需要根据对小地图的查找为每一行分配(“映射”)手动值。
在data.table
中,最明显的方法是创建非常复杂的代码,所以我想知道我是否缺少一个能够以更清晰的编码产生这种结果的习语。
考虑这个示例,我们从一个大data.table
开始,其中Name
列包含a
,b
,c
或{{ 1}}。
d
我们现在想要在额外的列中分配分数(a = 1,b = 4,c = 6,d = 3)。也许,加入像这样的小桌子:
library(data.table)
DT = data.table(ID = 1:4000, Name = rep(letters[1:4],1000), X = rnorm(4000))
setkey(DT, ID)
但是请注意,我们不得不为DT执行此操作并将列重新排序。所以在我们做完之前,工作还没有完成:
Weights = data.table(Name = c("a", "b", "c", "d"), W = c(1,4,6,3))
setkey(DT, Name)
setkey(Weights, Name)
DT = Weights[DT]
即使最终到达那里,重量设置也存在问题,因为值和名称没有连接在一起,这就是要求输入错误。这样的事情会更好:
setkey(DT, ID)
setcolorder(DT, c("ID", "Name", "X", "W"))
但是我们怎样才能从这个列表中查找DT?
乍一看,我们可以做到
WeightList = list(a = 1, b = 3, c = 6, d = 3)
但是W列没有很好地形成,并且对它的简单操作不起作用
DT[, W := WeightList[Name]]
> DT
ID Name X W
1: 1 a -0.05006513 1
2: 2 b 0.01637769 3
3: 3 c 2.18922366 6
4: 4 d 0.18327623 3
5: 5 a -1.44108171 1
---
3996: 3996 d 0.70507702 3
3997: 3997 a 0.42989246 1
3998: 3998 b 1.31611236 3
3999: 3999 c -1.43431163 6
4000: 4000 d 0.32244477 3
答案 0 :(得分:5)
您正在为list
分配DT
列,因此无法向其添加整数(至少不首先使用unlist
)。
您可以将list
向量更改为通常的integer
/ numeric
名为的向量,您的代码也可以正常运行。例如
WeightList <- c(a = 1, b = 3, c = 6, d = 3)
或者创建此向量的更健壮的方法可能是
WeightList <- setNames(c(1, 3, 6, 3), letters[1:4])
然后,你的代码就像以前一样
DT[, W := WeightList[Name]]
答案 1 :(得分:5)
将on
参数与:=
一起使用时考虑到了这些情况,即无需重新排序(设置加入密钥)并复制整个数据。表(当你没有&#39时) ; t使用:=
)只是为了添加列。
require(data.table)
DT = data.table(ID = 1:4000, Name = rep(letters[1:4],1000), X = rnorm(4000))
setkey(DT, ID)
Weights = data.table(Name = c("a", "b", "c", "d"), W = c(1,4,6,3))
DT[Weights, W := W, on="Name"]
key(DT) # [1] "ID"
DT
通过引用更新,并保留密钥。