使用data.table在R中重新索引?

时间:2015-11-19 02:02:24

标签: r indexing data.table lookup lapply

这是我最近在R data.table

中遇到的一个常见问题

我有一个索引表,比如DT1。列x将是索引的子集。我将使用这些索引处理更大的rawtable的子表。子表通常会从1到N索引(即y列)

然后例如,我会遇到一个带有原始索引的索引对的表,我想知道相应的新索引。

这就是它的样子

DT1 <- data.table(x=c(0,3,5),y= c(11,22,33))
DT2 <- data.table(x=c(3,3,0,0,5),x=c(0,5,0,3,5))
# > DT1
#    x y
# 1: 0 11
# 2: 3 22
# 3: 5 33

# > DT2
#    x x
# 1: 3 0
# 2: 3 5
# 3: 0 0
# 4: 0 3
# 5: 5 5

这是我发现的一种曲折的方式

cbind(DT1[DT2[,1,with=FALSE],on="x"][,2,with=FALSE],DT1[DT2[,2,with=FALSE],on="x"][,2,with=FALSE])
#     y  y
# 1: 22 11
# 2: 22 33
# 3: 11 11
# 4: 11 22
# 5: 33 33

使用sapply执行此操作的更基本方法会产生相同的结果

tab=DT1$x
lookup <- function(value){DT1$y[which(tab==value)]}

colnames(DT2) <- c("x","xx")

ans <- as.data.table(cbind(sapply(DT2$x,lookup),sapply(DT2$xx,lookup)))
colnames(ans) <- c("y","y")

然而, 第一个解决方案对我来说有点难看

我不喜欢第二个,因为每次我在lapply中使用函数查找时,我都需要为tab定义一个值。 如果我必须在不同的表中查找,我可以选择创建特定于该表的新查找函数,或者在(temp)变量选项卡中存储在内存中。 也许有一种方法可以使用两个变量的函数来执行lapply  lookup <-function (tab,value) {...}?我不知道

我确定还有很多其他方法。 我不确定我对第一个解决方案做了什么。基本上data.table中的语法与(内部和外部)JOINS有关。但在最终输出中,我想保持表DT2的原始顺序。将列x设置为DT2的键会对该列进行排序,使merge之类的东西不适应那个?

我愿意听取您的最佳实施方案, - 我确信有更好的实施方案 - 而且,在处理非常大的桌子时效率最高。

2 个答案:

答案 0 :(得分:7)

惯用的 data.table 方法是在加入更新 DT2,如下所示:

require(data.table) # v1.9.6
setnames(DT2, c("a", "b")) # no duplicate names!!
for (nm in names(DT2)) {
    DT2[DT1, paste0(nm, ".val") := y, on = structure("x", names=nm)]
}
DT2[]
#    a b a.val b.val
# 1: 3 0    22    11
# 2: 3 5    22    33
# 3: 0 0    11    11
# 4: 0 3    11    22
# 5: 5 5    33    33

您可以使用lapply()隐藏循环。如果DT2代替如下(长格式,请参阅DT3):

DT3 = melt(DT2, measure = c("a", "b"), variable.name = "id", value.name = "x.val")

然后你可以这样做:

DT3[DT1, y.val := y, on = c(x.val = "x")] 

您可以使用y.val := i.y更明确地指出您对应于y参数的data.table中的i列。(当它们两者都有用时有共同的列名。)

答案 1 :(得分:1)

您可以尝试以下内容:

@teachers = Teacher.where.not(user_id: nil).order(created_at: :desc)