在data.table中是否可以连接具有OR条件的表?
例如:
library(data.table)
X<-data.table(x=c('a','b','c','d','e','f'),y=c(1,1,2,2,3,3),z=c(10,11,12,13,14,15))
x y z
1: a 1 12
2: b 1 11
3: c 2 12
4: d 2 13
5: e 3 14
6: f 3 15
Y<-data.table(x=c('a','e','a'),z=c(12,20,14),t=c('a','b','c'))
x z t
1: a 12 a
2: e 20 b
3: a 14 c
# and i need something like this:
X[Y,on=c("x"|"z"),.(x,y,z,i.t)]
x y z t
1: a 1 10 a
2: a 1 10 c
3: b 1 11 NA
4: c 2 12 a
5: d 2 13 NA
6: e 3 14 b
7: e 3 14 c
8: f 3 15 NA
我没有找到有关在文档中加入OR的信息。 我错过了什么吗?
答案 0 :(得分:4)
OP要求结果集应包含3个子集:
x
y
X
因此,这是表X
与Y
列x
或y
之间的一种右外连接。
这可以转换为列x
和y
上的2个单独的内部联接,两个结果集的联合,以及用于添加表{{1}中的其余行的最终外部联接}}
在一个X
语句中合并后,这就变成了
data.table
内部联接由参数unique(rbindlist(list(
X[Y, on = "x", .(x, y, z, t), nomatch = 0],
X[Y, on = "z", .(x, y, z, t), nomatch = 0]
)))[X, on = .(x, y, z)]
# x y z t
#1: a 1 10 a
#2: a 1 10 c
#3: b 1 11 NA
#4: c 2 12 a
#5: d 2 13 NA
#6: e 3 14 b
#7: e 3 14 c
#8: f 3 15 NA
强制执行。联合操作使用nomatch = 0
实现。如果rbindlist(list(...))
和unique()
在x
和{{{}中的同一行匹配,则编辑 z
需要删除双重匹配1}}(thanks to filius_arator for pointing this out)。
最后的右外连接使用X
的所有行,包括那些尚未匹配的行。请注意,此联接位于Y
的三列。
答案 1 :(得分:1)
我不确定这是否是你想要的,或者它是非常data.table-esque但是目前还没有其他答案:
join1 <- merge(X, Y[,c('x', 't'), with=FALSE], all.x=TRUE)
merge(join1, Y[,c('z', 't'), with=FALSE], all.x=TRUE, by = 'z')[,
t := ifelse(!is.na(t.x), t.x, t.y)][,
t.x := NULL][,
t.y := NULL][]
,并提供:
z x y t
1: 10 a 1 a
2: 11 b 1 NA
3: 12 c 2 a
4: 13 d 2 NA
5: 14 e 3 b
6: 15 f 3 NA
编辑这里有更新的示例,这是一种方法,但我确信data.table大师应该有更好的方法:
join1 <- merge(X, Y[,c('x', 't'), with=FALSE], all.x=TRUE)
merge(join1, Y[,c('z', 't'), with=FALSE], all.x=TRUE, by = 'z')[,
id := seq(.N)][,
.(t =list( na.omit(c(t.x, t.y)))), by = c('id', 'x', 'y', 'z')][,
.(x=x, y=y, z=z, t=unlist(t)), by = c('id')][]
## id x y z t
## 1: 1 a 1 10 a
## 2: 2 a 1 10 c
## 3: 3 b 1 11 NA
## 4: 4 c 2 12 a
## 5: 5 d 2 13 NA
## 6: 6 e 3 14 b
## 7: 6 e 3 14 c
## 8: 7 f 3 15 NA