什么是将值映射到data.table的简洁明确的习惯用法

Cor*_*one 3 r data.table

一个相对常见的任务是需要根据对小地图的查找为每行分配("映射")手动值.

data.table最明显的方式创建非常复杂的代码,所以我想知道我是否缺少一个能够以更清晰的编码产生这种结果的习语.

考虑下面这个例子,我们有一个大的启动data.table,有一个Name含有其中任何一列a,b,c,或d.

library(data.table)

DT = data.table(ID = 1:4000, Name = rep(letters[1:4],1000), X = rnorm(4000))
setkey(DT, ID)
Run Code Online (Sandbox Code Playgroud)

我们现在想要在额外的列中分配分数(a = 1,b = 4,c = 6,d = 3).也许,加入像这样的小桌子:

Weights = data.table(Name = c("a", "b", "c", "d"), W = c(1,4,6,3))

setkey(DT, Name)
setkey(Weights, Name)

DT = Weights[DT]
Run Code Online (Sandbox Code Playgroud)

但是请注意,我们不得不为DT执行此操作并将列重新排序.所以在我们做之前,工作还没有完成:

setkey(DT, ID)
setcolorder(DT, c("ID", "Name", "X", "W"))
Run Code Online (Sandbox Code Playgroud)

即使最终到达那里,重量设置也存在问题,因为值和名称没有连接在一起,这就是要求输入错误.这样的事情会更好:

WeightList = list(a = 1, b = 3, c = 6, d = 3)
Run Code Online (Sandbox Code Playgroud)

但是,我们怎样才能从这个列表中查找到DT?

乍一看,我们可以做到

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
Run Code Online (Sandbox Code Playgroud)

但是W列的格式不好,对它的简单操作不起作用

> DT[, W + 1]
Error in W + 1 : non-numeric argument to binary operator
Run Code Online (Sandbox Code Playgroud)

Dav*_*urg 5

您正在list为其分配一个列DT,因此无法向其添加整数(unlist至少不使用第一个).

您可以将list矢量更改为通常integer/ numeric 命名向量,您的代码将正常工作.例如

WeightList <- c(a = 1, b = 3, c = 6, d = 3)
Run Code Online (Sandbox Code Playgroud)

或者更健壮的方法来创建这个向量可能是

WeightList <- setNames(c(1, 3, 6, 3), letters[1:4])
Run Code Online (Sandbox Code Playgroud)

然后,你的代码和以前一样

DT[, W := WeightList[Name]]
Run Code Online (Sandbox Code Playgroud)


Aru*_*run 5

使用on参数并考虑:=到这些情况,即不需要重新排序(设置连接键)并复制整个data.table(当你不使用时:=)只是为了添加列.

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"
Run Code Online (Sandbox Code Playgroud)

DT 通过引用更新,并保留密钥.

  • 我主张使用更详细的`W:= iW`选项;) (2认同)