我有两个数据表,我想根据两列中的值合并/连接,这两列可以在两个数据表中以相反的顺序出现。 以下是两个示例数据表:
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对合并/连接数据表,但它们可能在另一个数据表中的顺序相反。 (请注意,简单地对它们进行排序并不起作用。)
这意味着合并/加入等必须能够看到&#39; 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 :(得分:2)
您可以执行以下操作:
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
答案 1 :(得分: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
答案 2 :(得分:1)
所以,我们有两个有效的解决方案!
版本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