子集data.table由另一个data.table而不合并所有列

时间:2017-05-04 06:05:49

标签: r merge data.table subset

使用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语法[]?

3 个答案:

答案 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)]并查看在列表中命名所需列(不带引号)是获取列子集的常用方法。