2017-05-04 66 views
1

隨着data.table,我想根據另一個表子集。子集data.table另一個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 

有沒有辦法讓像合併正確的行,但使用data.table語法[]?

回答

2

繼@ akrun的回答semi_join的情況下,您可以識別的行加入並將它們用於表的子集:

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

我們做一個連接,然後子集

nm1 <- names(DT1) 
DT1[DT2, on = .(A, B)][, ..nm1] 
# A B C 
#1: 1 1 1 
#2: 2 3 1 
#3: 3 1 3 

此外,這是從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

或'DT1 [DT1 [DT2,on =。(A,B),which = TRUE,nomatch = 0]]' – Frank

+1

@Frank從來沒有想過'哪個'路線。偉大的選擇。如果你想發佈作爲答案,請繼續 – akrun

+0

智能方式無鑰匙加入。 on =參數對我來說是新的。謝謝!如果第二個表具有不同的列名,例如'DT3 < - data.table(E = c(1,2,3),F = c(1,3,1),D = c(4: 6))' –

1
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)],看到在列表命名所需的列(不帶引號)是獲得列的子集的常用方法。