2017-03-31 78 views
0

我試圖在data.table中執行滾動連接,它會引入多個列,但會遍歷整個缺失的行,並且會在特定的列中滾動,即使該行存在。舉例來說,我有兩個表,A,並BRolling加入多個列以獨立排除NAs

library(data.table) 
A <- data.table(v1 = c(1,1,1,1,1,2,2,2,2,3,3,3,3), 
       v2 = c(6,6,6,4,4,6,4,4,4,6,4,4,4), 
       t = c(10,20,30,60,60,10,40,50,60,20,40,50,60), 
       key = c("v1", "v2", "t")) 

B <- data.table(v1 = c(1,1,1,1,2,2,2,2,3,3,3,3), 
       v2 = c(4,4,6,6,4,4,6,6,4,4,6,6), 
       t = c(10,70,20,70,10,70,20,70,10,70,20,70), 
       valA = c('a','a',NA,'a',NA,'a','b','a', 'b','b',NA,'b'), 
       valB = c(NA,'q','q','q','p','p',NA,'p',NA,'q',NA,'q'), 
       key = c("v1", "v2", "t")) 

B 
##  v1 v2 t valA valB 
## 1: 1 4 10 a NA 
## 2: 1 4 70 a q 
## 3: 1 6 20 NA q 
## 4: 1 6 70 a q 
## 5: 2 4 10 NA p 
## 6: 2 4 70 a p 
## 7: 2 6 20 b NA 
## 8: 2 6 70 a p 
## 9: 3 4 10 b NA 
## 10: 3 4 70 b q 
## 11: 3 6 20 NA NA 
## 12: 3 6 70 b q 

如果我不滾動連接(在這種情況下,反向連接),它翻轉所有的點當行不能被發現B,但仍包括點時存在行,但要合併的數據NA

B[A, , roll=-Inf] 

##  v1 v2 t valA valB 
## 1: 1 4 60 a q 
## 2: 1 4 60 a q 
## 3: 1 6 10 NA q 
## 4: 1 6 20 NA q 
## 5: 1 6 30 a q 
## 6: 2 4 40 a p 
## 7: 2 4 50 a p 
## 8: 2 4 60 a p 
## 9: 2 6 10 b NA 
## 10: 3 4 40 b q 
## 11: 3 4 50 b q 
## 12: 3 4 60 b q 
## 13: 3 6 20 NA NA 

我想以這樣的方式來滾動加入它滾過這些NA S以及。對於單個列中,我可以子集B以除去NA s,則與A滾:

C <- B[!is.na(valA), .(v1, v2, t, valA)][A, roll=-Inf] 

C 
##  v1 v2 t valA 
## 1: 1 4 60 a 
## 2: 1 4 60 a 
## 3: 1 6 10 a 
## 4: 1 6 20 a 
## 5: 1 6 30 a 
## 6: 2 4 40 a 
## 7: 2 4 50 a 
## 8: 2 4 60 a 
## 9: 2 6 10 b 
## 10: 3 4 40 b 
## 11: 3 4 50 b 
## 12: 3 4 60 b 
## 13: 3 6 20 b 

但對多列,我必須這樣做順序,存儲該值對於每個添加的列,然後重複。

B[!is.na(valB), .(v1, v2, t, valB)][C, roll=-Inf] 

##  v1 v2 t valB valA 
## 1: 1 4 60 q a 
## 2: 1 4 60 q a 
## 3: 1 6 10 q a 
## 4: 1 6 20 q a 
## 5: 1 6 30 q a 
## 6: 2 4 40 p a 
## 7: 2 4 50 p a 
## 8: 2 4 60 p a 
## 9: 2 6 10 p b 
## 10: 3 4 40 q b 
## 11: 3 4 50 q b 
## 12: 3 4 60 q b 
## 13: 3 6 20 q b 

上述最終結果是所期望的輸出,但對於多個列它很快變得難以處理。有更好的解決方案嗎?

回答

2

加入即將匹配了行。如果您想以多種方式匹配行,則需要多個連接。

我會使用一個循環,但添加列A(而不是創建新表C,d,......每個以下連接):

k  = key(A) 
bcols = setdiff(names(B), k) 

for (col in bcols) A[, (col) := 
    B[!.(as(NA, typeof(B[[col]]))), on=col][.SD, roll=-Inf, ..col] 
][] 

A 

    v1 v2 t valA valB 
1: 1 4 60 a q 
2: 1 4 60 a q 
3: 1 6 10 a q 
4: 1 6 20 a q 
5: 1 6 30 a q 
6: 2 4 40 a p 
7: 2 4 50 a p 
8: 2 4 60 a p 
9: 2 6 10 b p 
10: 3 4 40 b q 
11: 3 4 50 b q 
12: 3 4 60 b q 
13: 3 6 20 b q 

B[!.(NA_character_), on="valA"]是一種抗加入該行下降新手在valA。上面的代碼試圖概括這個(因爲NA需要匹配列的類型)。

+0

這很好用!我沒有立即去循環,因爲我有時會發現,如果你在R中使用循環和數據結構,你經常做錯了。但有時候我猜是不可避免的。 –

+0

爲了讓我明白髮生了什麼,你在'!is.na(col)'上對'B'進行了子集化,並且進行自卷聯接以滾動該列的數據,是嗎? '..col'是對'on ='的隱式調用嗎? –

+1

是的,反連接和!is.na一樣。下一個連接本質上是'A [,v:= B [A,v]]',除了我們可以使用'.SD'而不是第二次寫'A';所以它不是一個真正的自我加入。 '.v'符號用於選擇存儲在變量中的列(不使用'on =';鍵仍然在這裏確定連接)。 – Frank