使用data.table,我想根据另一个表对子表进行子集化。
DT1 <- data.table( A = c(1:5,1:2), B = c(1,1,1,2,2,2,3), C = c(1:3))
DT2 <- data.table( A = c(1, 2, 3), B = c(1,3,1), D = c(4:6))
输出应仅包含第一个表的列。
A B C
1: 1 1 1
2: 2 3 1
3: 3 1 3
使用合并功能,我得到两个表的列
merge(DT1, DT2, by = c("A", "B"))
A B C D
1: 1 1 1 4
2: 2 3 1 5
3: 3 1 3 6
由于我的数据集有更多列,我正在寻找一种方法来获得没有合并函数的结果,但是使用data.table语法[i,j,by]。 但是,通过对第一个表进行子集化,它无法正确合并。
DT1[A %in% DT2[,A] & B %in% DT2[, B]]
A B C
1: 1 1 1
2: 2 1 2 < wrong
3: 3 1 3
4: 2 3 1
DT1[A == DT2[,A] & B == DT2[, B]]
A B C
1: 1 1 1
2: 3 1 3
Warning messages:
1: In A == DT2[, A] :
longer object length is not a multiple of shorter object length
2: In B == DT2[, B] :
longer object length is not a multiple of shorter object length
有没有办法像使用merge一样获取正确的行,但使用data.table语法[]?
答案 0 :(得分:2)
我们进行连接,然后进行子集
nm1 <- names(DT1)
DT1[DT2, on = .(A, B)][, ..nm1]
# A B C
#1: 1 1 1
#2: 2 3 1
#3: 3 1 3
此外,这是来自semi_join
dplyr
的情况
dplyr::semi_join(DT1, DT2, by = c('A', 'B'))
# A B C
#1 1 1 1
#2 2 3 1
#3 3 1 3
答案 1 :(得分:2)
按照@ akrun的回答,您可以识别联接中的行并使用它们对表进行子集化:
w = sort(DT1[DT2, on=.(A,B), which=TRUE, nomatch=0])
DT1[w]
# A B C
# 1: 1 1 1
# 2: 3 1 3
# 3: 2 3 1
或更紧凑
DT1[sort(DT1[DT2, on=.(A,B), which=TRUE, nomatch=0])]
如果你想在DT2的顺序中保留行,请不要排序;如果您想要包含不匹配的行,请跳过nomatch=0
。
答案 2 :(得分:2)
setkey(DT1, A,B,C)
DT1[DT2]
# not quite right
A B C
1: 1 1 4
2: 2 3 5
3: 3 1 6
# so join just on the two shared columns
DT1[ DT2[,list(A,B)] ]
A B C
1: 1 1 1
2: 2 3 1
3: 3 1 3
查看DT2[,list(A,B)]
并查看在列表中命名所需列(不带引号)是获取列子集的常用方法。