2017-08-02 9 views
0

2つのデータテーブルに逆の順序で表示される2つの列の値に基づいて、結合/結合したい2つのデータテーブルがあります。ここ は、2つの例示的なデータテーブルである:2つの列を参照する条件でRの2つのデータテーブルを結合します。

library(data.table) 
# df1 
col1 <- c("aa", "bb", "cc", "dd") 
col2 <- c("bb", "zz", "dd", "ff") 
x <- c(130, 29, 122, 85) 
dt1 <- data.table(col1, col2, x) 

    col1 col2 x 
1: aa bb 130 
2: bb zz 29 
3: cc dd 122 
4: dd ff 85 

# df2 
col1 <- c("zz", "bb", "cc", "ff") 
col2 <- c("bb", "aa", "dd", "dd") 
y <- c(34, 567, 56, 101) 
dt2 <- data.table(col1, col2, y) 

    col1 col2 y 
1: zz bb 34 
2: bb aa 567 
3: cc dd 56 
4: ff dd 101 

だからCOL1の値とcol2が一緒になって、両方のデータテーブルについて同じであるが、分布が異なっています。例えば。 aaはdt1ではcol1に、dt2ではcol2にあります。 col1とcol2のペアに基づいてデータテーブルをマージ/結合したいが、他のデータテーブルでは逆の順序になる可能性があります。

これは、マージ/ジョインなどでは、dt1のペアaa + bbがdt2のbb + aaとして発生することを「認識」できなければならないことを意味します。 DT2の正しい値、所望の出力はどちらか、すなわち:

col1 col2 x y 
1: aa bb 130 567 
2: bb zz 29 34 
3: cc dd 122 56 
4: dd ff 85 101 

または本(すなわちDT1またはDT2の順序は保持されているかどうかは関係ありません):

col1 col2 x y 
1: zz bb 29 34 
2: bb aa 130 567 
3: cc dd 122 56 
4: ff dd 85 101 

私の元のデータテーブルを持っています約。 300万行(はい、それは巨大です)なので、手で何かをすることは問題になりません。 私はここを見回しましたが、私のケースに該当する解決策は見つかりませんでした。誰もこれを行う方法を知っていますか?

ご迷惑をおかけして申し訳ありません。

+0

dt2 [col1> col2、c( "col1"、 "col2"):=。(col2、col1)]; dt1 [dt2、on =。(col1、col2)] 'が働きます。あるいは、 ':='を使用して、提案されているように 'dt1'に列を追加することもできます。 – Frank

+1

@フランク、これは動作します!本当にありがとう!それを回答として投稿したいのですか? –

+0

Np、それはうれしいよ:)それでは、あなたの答えを自由に編集してください。 – Frank

答えて

1

役立つことを願って、私たちは仕事2つのソリューションを持っています!

バージョン1:

library(dplyr) 
final <- dt2[col1 > col2, c("col1", "col2") := .(col2, col1)] 
final <- dt1[dt2, on=.(col1, col2)] 
final <- select(final, col1, col2, x, y) # select relevant columns 
final 
    col1 col2 x y 
1: bb zz 29 34 
2: aa bb 130 567 
3: cc dd 122 56 
4: dd ff 85 101 

バージョン2:上記のフランクさんのコメントから適応 これは、いくつかのことを簡素化し、大規模なデータテーブルのこのソリューションは、より適用になりPritamJの答えのほんの微調整です。他の人にも役立つことを願っています!

library(dplyr) 
dt1$pairs <- paste(dt1$col1, dt1$col2) # creates new column with col1 and col2 
merged into one 
dt2$pairs <- paste(dt2$col1, dt2$col2) # same here 
dt2$revpairs <- paste(dt2$col2, dt2$col1) # creates new column with reverse pairs 

f1 <- merge(dt1, dt2, by="pairs") # merge by pairs as they are in dt1 
f1 <- select(f1, col1.x, col2.x, x, y) # select by name (easier for big dt) 

f2 <- merge(dt1, dt2, by.x = "pairs", by.y = "revpairs") # merge by pairs and reverse pairs 
colnames(f2)[ncol(f2)] <- "revpairs" # rename last column because it has the same name as the first, which can cause errors 
f2 <- select(f2, col1.x, col2.x, x, y) 


final <- bind_rows(f2, f1) # bind the two together 
colnames(final)[1:2] <- c("col1", "col2") # this is not necessary, just for clarity 
final 
    col1 col2 x y 
1: aa bb 130 567 
2: bb zz 29 34 
3: dd ff 85 101 
4: cc dd 122 56 
1

次の操作を行うことができます

dt1[dt2, on=.(col1, col2), y:= y] 

dt1[dt2, on=.(col1==col2, col2==col1), y:= i.y] 

> dt1 
# col1 col2 x y 
# 1: aa bb 130 567 
# 2: bb zz 29 34 
# 3: cc dd 122 56 
# 4: dd ff 85 101 
+0

これはdtの例でうまくいきますが、実際のデータテーブルで実行した場合、2行目を実行しようとするとこのエラーが発生します: 'vecseqのエラー(f__、len__、if(allow.cartesian || notjoin ||!anyDuplicated(f__、: 2^31行以上の結果を結合する(内部のvecseqが物理的な限界に達した)非常に誤って指定されている結合x内の同じグループに参加するiの重複するキー値を調べ、私はEACHIを試しましたが、yの値が間違っていました。どうすればこの問題を解決できますか? –

+0

私も試してみました。 –

+0

'=='は 'on ='の内部で動作するとは思っていませんでしたが、 '='を使わないのはなぜですか?また、 'iy'を使用しない理由がありますか?最初の行? – Frank

1

は、任意のストレートな答えを見つけることができなかったので、以下のコードを試してみました。 が、それはそう

require(stringi) 
require(data.table) 
require(dplyr) 
dt1$as <- paste(dt1$col1,dt1$col2) 
dt2$as <- paste(dt2$col1,dt2$col2) 
dt2$as1 <- stringi::stri_reverse(dt2$as) 

f1 <- merge(dt1,dt2,by="as") 
f1 <- subset(f1,select=c(2,3,4,7)) 
f1 <- setnames(f1,c("col1.x","col2.x"),c("Col1","Col2")) 
f2 <- merge(dt1,dt2,by.x = "as",by.y = "as1") 
f2 <- subset(f2,select=c(2,3,4,7)) 
f2 <- setnames(f2,c("col1.x","col2.x"),c("Col1","Col2")) 
final <- bind_rows(f2,f1) 

final 
    Col1 Col2 x y 
1: aa bb 130 567 
2: bb zz 29 34 
3: dd ff 85 101 
4: cc dd 122 56 
+0

ありがとうございました。おそらく最も簡潔な解決策ではないかもしれませんが、それはトリックを行います!修正版を回答として掲示します。 –

関連する問題