在data.table中有一个问题:如何选择与另一个data.table中相匹配的行。

5

给定两个数据表(tbl_Atbl_B),我想选择在tbl_B中有匹配行的所有tbl_A中的行,并且我希望代码具有表达性。如果为data.tables定义了%in%运算符,那么像这样就是理想的:

subset <- tbl_A[tbl_A %in% tbl_B]

我能想到很多实现我所需的方法,例如:

# double negation (set differences)
subset <- tbl_A[!tbl_A[!tbl_B,1,keyby=a]]

# nomatch with keyby and this annoying `[,V1:=NULL]` bit
subset <- tbl_B[,1,keyby=.(a=x)][,V1:=NULL][tbl_A,nomatch=0L]

# nomatch with !duplicated() and setnames()
subset <- tbl_B[!duplicated(tbl_B),.(x)][tbl_A,nomatch=0L]; setnames(subset,"x","a")

# nomatch with !unique() and setnames()
subset <- unique(tbl_B)[,.(x)][tbl_A,nomatch=0L]; setnames(subset,"x","a")

# use of a temporary variable (Thanks @Frank)
subset <- tbl_A[, found := FALSE][tbl_B, found := TRUE][(found)][,found:=NULL][]

但每个表达式都很难阅读,而且乍一看不清楚代码在做什么。有没有更加惯用/富有表现力的方法来完成这个任务呢?

为了举例说明,这里有一些玩具数据表:

# toy tables
tbl_A  <- data.table(a=letters[1:5],
                     b=1:5,
                     c=rnorm(5))
tbl_B  <- data.table(x=letters[3:7],
                     y=13:17,
                     z=rnorm(5))
# both tables might have multiple rows with the same key fields.  
tbl_A <- rbind(tbl_A,tbl_A)
tbl_B <- rbind(tbl_B,tbl_B)
setkey(tbl_A,a)
setkey(tbl_B,x)

期望的结果包含与tbl_B中至少一行匹配的tbl_A中的行:

   a b          c
1: c 3 -0.5403072
2: c 3 -0.5403072
3: d 4 -1.3353621
4: d 4 -1.3353621
5: e 5  1.1811730
6: e 5  1.1811730

1
tbl_A[, found := FALSE][tbl_B, found := TRUE] ? 顺便提一下,关于 %in% 运算符的问题/请求,请在 https://github.com/Rdatatable/data.table/issues/2279 上开启。 - Frank
你是想要半连接运算符吗? - Scott Ritchie
是的,确切无误。 - Jthorpe
2个回答

2

添加2个选项

tbl_A[fintersect(tbl_A[,.(a)], tbl_B[,.(a=x)])]

并且

tbl_A[unique(tbl_A[tbl_B, nomatch=0L, which=TRUE])]

0

我不确定它的表达力有多好(如果不行请见谅),但似乎这个能用:

tbl_A[,.(a,b,c,any(a == tbl_B[,x])), by = a][V4==TRUE,.(a,b,c)]

我相信它可以被改进 - 我昨天才知道了 any(),还在测试它 :)


欢迎来到SO!感谢您的回复,但我不会特别称呼它为表达性(不易一眼理解),而且可能不是特别快,因为它没有利用键。此外,对于具有数百列和多个键的表格,它需要大量输入... - Jthorpe
嘿,Jthorpe。感谢你的欢迎和反馈。你是对的,即使它可以简化为tbl_A[,.(a,b,c,any(a == tbl_B[,x])), by = a][V4==TRUE],但它仍然没有利用键。至于表达力 - 我不得不谷歌一下,我还有很多东西要学习... - ErrHuman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接