2017-02-10 102 views
2

我有兩個大型數據集,d1d2,我想合併基於任何變量idAidB匹配。高效地合併兩個數據集匹配一個變量或另一個

兩者都存在於兩個數據集中,但都可以包含錯誤和缺失值(NAs),或者指向其他數據集中的不同觀察值。例如波紋管。

期望的結果列於下面。基本上,比賽在idA或idB上進行,如果是重複比賽,則應優先考慮與idB比賽的idA比賽。

實際數據集相當大(約10億)。

是否有有效的方法來實現R?

此外,是否有這種SQL連接的技術術語?

library(tidyverse) 
library(data.table) 

d1 <- read.table(text= 
"idA idB value1 
A 10 500 
B 1 111 
C 4 234 
D NA 400 
E 7 500 
NA 3 700 
Z 5 543 
Q 9 567 
U 23 723 
", 
header=T) %>% data.table 


d2 <- read.table(text= 
"idA idB value2 
A 10 11 
B 1 12 
L 21 15 
D 15 12 
E 8 17 
M 3 18 
N 5 13 
Z 25 17 
Q 23 12 
", 
header=T) %>% data.table 

期望的結果是:

Out <- read.table(text= 
"d1.idA d2.idA d1.idB d2.idB d1.v1 d2.v2 
A A 10 10 500 11 # matched on idA and idB 
B B 1 1 111 12 # matched on idA and idB 
D D NA 15 400 12 # matched on idA. d2.idB had NAs 
E E 7 8 500 17 # matched on idA. idB had divergent values 
NA M 3 3 700 18 # matched on idB. d1.idA had NAs 
Z Z 5 25 543 13 # d1[7,] matched to d2[8,] on idA and d2[9,] on idB. Priority given to idA match. 
Q Q 9 23 657 17 # d2[9,] matched to d1[8,] on idA and d1[9,] on idB. Priority given to idA match. 
", 
header=T) %>% data.table 

#Non matched rows 
# d1[3,] 
# d2[3,] 

EDIT1:

  • 加入期望的結果
  • 保持data.table(函數read.table)由於容易 解析的讀者,實際數據來自fread(文件)

編輯2:從期望的結果中刪除不匹配的行

+1

@akrun,我不明白這是如何重複的。我在詢問如何通過兩個id變量進行連接,只需要其中一個匹配。 (該問題涉及同一個變量的內部,左邊,rigth連接) – LucasMation

+0

請在遊說之前重新打開您的示例並輸入所需的輸出。 「偏好應該是idA與idB匹配」並不是很清楚。另外,如果數據集很大,那麼您將需要使用'fread'而不是'data.table(read.table(。))'這是非常慢的 - 讀入速度較慢並且在進行不必要的複製時轉換爲DT。 – Frank

+0

添加了請求的功能。仍然原來的問題是完全無關的問題表明重複 – LucasMation

回答

1

我不知道一個優雅的方式來實現所需的結果(我也沒有意識到這種類型的操作在SQL中的技術術語)。

因此,我建議在四個步驟來實現:

  1. 內連接兩個data.tables上idAidB,確定每個data.tables的剩餘行。
  2. 內連接idA上的兩個data.tables的其餘行,再次確定剩餘的行。
  3. 內連接idB上的兩個data.tables的其餘行。
  4. 結合前面的步驟的結果。

代碼對所有4個步驟:

library(data.table) 

# create index column in both data.tables 
d1[, idx := .I] 
d2[, idx := .I] 

# inner join on idA and idB 
j1 <- d1[d2, .(idx, i.idx), on = c("idA", "idB"), nomatch = 0L] 
m1 <- unique(j1$idx) 
m2 <- unique(j1$i.idx) 

# inner join on idA 
j2 <- d1[!(idx %in% m1)][d2[!(idx %in% m2)], .(idx, i.idx), on = c("idA"), nomatch = 0L] 
m1 <- append(m1, unique(j2$idx)) 
m2 <- append(m2, unique(j2$i.idx)) 

# inner join on idB 
j3 <- d1[!(idx %in% m1)][d2[!(idx %in% m2)], .(idx, i.idx), on = c("idB"), nomatch = 0L] 
m1 <- append(m1, unique(j3$idx)) 
m2 <- append(m2, unique(j3$i.idx)) 

# combine results 
rbindlist(
    list(
    AB = cbind(
     d1[idx %in% j1[, idx]], 
     d2[idx %in% j1[, i.idx]]), 
    A. = cbind(
     d1[idx %in% j2[, idx]], 
     d2[idx %in% j2[, i.idx]]), 
    .B = cbind(
     d1[idx %in% j3[, idx]], 
     d2[idx %in% j3[, i.idx]])), 
    fill = TRUE, 
    idcol = "match_on") 

其產生

# match_on idA idB value1 idx idA idB value2 idx 
#1:  AB A 10 500 1 A 10  11 1 
#2:  AB B 1 111 2 B 1  12 2 
#3:  A. D NA 400 4 D 15  12 4 
#4:  A. E 7 500 5 E 8  17 5 
#5:  A. Z 5 543 7 Z 25  17 8 
#6:  A. Q 9 567 8 Q 23  12 9 
#7:  .B NA 3 700 6 M 3  18 6 

m1m2用於記住的行的行ID在d1d2,RESP,已經在之前的一個連接操作中使用過。

所以,最後在d1d2剩餘行還沒有找到一個匹配可以打印:

d1[!(idx %in% m1)] 
# idA idB value1 idx 
#1: C 4 234 3 
#2: U 23 723 9 
d2[!(idx %in% m2)] 
# idA idB value2 idx 
#1: L 21  15 3 
#2: N 5  13 7 

注意,在每個連接操作僅排索引被保留,而不是保持所有列。不同連接操作的結果在列的名稱和位置上有所不同。

在最後的組合步驟中,通過使用這些索引來選擇原始data.tables d1d2的行以產生統一的查找結果表。

+0

美麗,tks! – LucasMation

+0

這個問題解決了嗎?如果是這樣,請檢查刻度線以確認解決方案。 – Parfait

相關問題