2015-09-03 50 views
1

我需要跨5個taables進行合併,每個taables都有一個公用密鑰,具有相同名稱的許多列以及具有唯一名稱的列數橫跨每張桌子。命名多個合併的列的默認行爲...並更改它

我發現,多個表合併後,列名的唯一性會出現問題......處理此問題並強制使用唯一列名的最佳方法是什麼?

library(data.table) 
DT1<-data.table(IDs=c(1,1,2,3,4,10), V1=c(1,2,3,4,5,6)) 
DT2<-data.table(IDs=c(1,2,3,6,10), V2=c(6,7,8,9,10)) 
DT3<-data.table(IDs=c(3,4,7,8,10), V2=c(1,2,3,4,5)) 
DT4<-data.table(IDs=c(4,7,6,8,10), V2=c(10,11,12,13,14)) 
DT5<-data.table(IDs=c(4,7,6,8,10), V2=c(20,21,22,23,24)) 
tmp<-merge(DT1, DT2, by="IDs") 
tmp 
tmp<-merge(tmp, DT3, by="IDs") 
tmp 
tmp<-merge(tmp, DT4, by="IDs") 
tmp 
tmp<-merge(tmp, DT5, by="IDs") 
tmp 

通知的處理,如果列名,會發生什麼,在最後一種情況......我結束了重複的列名,當我試圖訪問的價值,我只得到了第一個值。

> tmp 
    IDs V1 V2 
1: 1 1 6 
2: 1 2 6 
3: 2 3 7 
4: 3 4 8 
5: 10 6 10 
> tmp<-merge(tmp, DT3, by="IDs") 
> tmp 
    IDs V1 V2.x V2.y 
1: 3 4 8 1 
2: 10 6 10 5 
> tmp<-merge(tmp, DT4, by="IDs") 
> tmp 
    IDs V1 V2.x V2.y V2 
1: 10 6 10 5 14 
> tmp<-merge(tmp, DT5, by="IDs") 
> tmp 
    IDs V1 V2.x V2.y V2.x V2.y 
1: 10 6 10 5 14 24 
> tmp$V2.x 
[1] 10 
+0

,如果你不需要使用使用make.unique()'allow.cartesian = TRUE'(我沒有在您的示例數據中看到),那麼您可以通過引用您的第一個數據集來加入列,並將名稱分配給新列。我很忙,要回答它,但它是這樣的:'DT1 [DT2,new_col:= i.V2] [DT3,new_col2:= i.V2] [...]'。 – jangorecki

+0

我需要這個導致內部連接。如果我遵循你的代碼,我認爲我們得到了一個完整的外連接? – tcs

回答

3

data.table一般允許重複名稱。在這種情況下,它也模仿merge.data.frame行爲。

您可以在合併結果的名字

setnames(tmp, make.unique(names(tmp))) 
# IDs V1 V2.x V2.y V2.x.1 V2.y.1 
# 1 10 6 10 5  14  24 

tmp$V2.x 
# [1] 10 
tmp$V2.y.1 
# [1] 24 

或使用Reducex[y]語法沿着如下

# requires 1.9.5+ for the `on=` syntax. Else you've to setkey() first 
Reduce(function(x, y) x[y, on="IDs", nomatch=0L], mget(paste0("DT", 1:5))) 
# IDs V1 V2 i.V2 i.V2.1 i.V2.2 
# 1: 10 6 10 5  14  24 
+0

謝謝。這解決了重複的問題。有沒有簡單的方法來設置命名約定?在我的情況下,我想更改每個重複的變量以使其具有命名機制,例如V2.1,V2.2,V2.3和V2.4。 – tcs

+0

您可以將它們重命名爲任何您想要的。檢查'?setnames' – Arun

+0

是的,這是真的 - 公平的。我正在合併300多個變量,所以我一直在尋找的是一種方法,它改變了合併函數的命名方案/方法。我不喜歡依賴於任意的命名約定(即將來可能發生的變化,因此打破代碼),或手動編碼一堆重命名。 – tcs