如何在R中找到2个数据帧的公共行(考虑反之亦然格式)

如何在R中找到2个数据帧的公共行(考虑反之亦然格式),r,dataframe,R,Dataframe,我想找到2个数据帧之间的公共行。要查找公共行,可以使用internal\u join()、semi\u join()和merge()。我已经通过了不同的职位,包括。但是,这些行动并没有达到我的目的。因为我的数据框中的数据有点不同 有时,数据帧中的数据可以是相反的。与数据帧1和数据帧2的第3行和第5行类似。数据帧1包含A3 A3 0.75,但数据帧2包含A3 A3 0.75。我想把这两行当作同一行 我的第一个数据帧看起来像 query target weight 1 A1 A2

我想找到2个数据帧之间的公共行。要查找公共行,可以使用
internal\u join()、semi\u join()
merge()
。我已经通过了不同的职位,包括。但是,这些行动并没有达到我的目的。因为我的数据框中的数据有点不同

有时,数据帧中的数据可以是相反的。与数据帧1和数据帧2的第3行和第5行类似。数据帧1包含
A3 A3 0.75
,但数据帧2包含
A3 A3 0.75
。我想把这两行当作同一行

我的第一个数据帧看起来像

  query target weight
1    A1     A2   0.60
2    A2     A5   0.50
3    A3     A1   0.75
4    A4     A5   0.88
5    A5     A3   0.99
6    (+)-1(10),4-Cadinadiene     Falcarinone-10     0.09
7    Leucodelphinidin-100    (+)-1(10),4-Cadinadiene     0.876
8    Lignin  (2E,7R,11R)-2-Phyten-1-ol   0.778
9    (2E,7R,11R)-2-Phyten-1-ol   Leucodelphinidin    0.55
10   Falcarinone     Lignin  1
11   A1  (+)-1(10),4-Cadinadiene     1
12   A2  Lignin-10  1
13   A3  (2E,7R,11R)-2-Phyten-1-ol   1
14   Falcarinone  A6    1
15   A4  Leucodelphinidin    1
16   A4  Leucodelphinidin    1
17   Falcarinone  A100    1
18   A4  Falcarinone     1
  query target
1    A1     A2   
2    A2     A5   
3    A1     A3  // Missing in the output
4    A4     A5   
5    A3     A5  // Missing in the output
6    A3  (2E,7R,11R)-2-Phyten-1-ol   
7    (+)-1(10),4-Cadinadiene     Falcarinone    
8    Leucodelphinidin    (+)-1(10),4-Cadinadiene-100    
9    Lignin-2  (2E,7R,11R)-2-Phyten-1-ol   
10   A11  (+)-1(10),4-Cadinadiene    
11   A2  Lignin  
12   A3  (2E,7R,11R)-2-Phyten-1-0l 
13   Falcarinone  A60    
14   A4  Leucodelphinidin  // Missing in the output
第二个数据帧看起来像

  query target weight
1    A1     A2   0.60
2    A2     A5   0.50
3    A3     A1   0.75
4    A4     A5   0.88
5    A5     A3   0.99
6    (+)-1(10),4-Cadinadiene     Falcarinone-10     0.09
7    Leucodelphinidin-100    (+)-1(10),4-Cadinadiene     0.876
8    Lignin  (2E,7R,11R)-2-Phyten-1-ol   0.778
9    (2E,7R,11R)-2-Phyten-1-ol   Leucodelphinidin    0.55
10   Falcarinone     Lignin  1
11   A1  (+)-1(10),4-Cadinadiene     1
12   A2  Lignin-10  1
13   A3  (2E,7R,11R)-2-Phyten-1-ol   1
14   Falcarinone  A6    1
15   A4  Leucodelphinidin    1
16   A4  Leucodelphinidin    1
17   Falcarinone  A100    1
18   A4  Falcarinone     1
  query target
1    A1     A2   
2    A2     A5   
3    A1     A3  // Missing in the output
4    A4     A5   
5    A3     A5  // Missing in the output
6    A3  (2E,7R,11R)-2-Phyten-1-ol   
7    (+)-1(10),4-Cadinadiene     Falcarinone    
8    Leucodelphinidin    (+)-1(10),4-Cadinadiene-100    
9    Lignin-2  (2E,7R,11R)-2-Phyten-1-ol   
10   A11  (+)-1(10),4-Cadinadiene    
11   A2  Lignin  
12   A3  (2E,7R,11R)-2-Phyten-1-0l 
13   Falcarinone  A60    
14   A4  Leucodelphinidin  // Missing in the output
我正在使用的代码
输出可能可以尝试:

output <- merge(df_1, df_2, all=T)
然后可以保留为FALSE的行

output[which(same.rows==F),]


query target weight
1    A1     A2   0.60
2    A1     A3   0.75
3    A2     A5   0.50
5    A3     A5   0.99
6    A4     A5   0.88

这有意义吗?

您可以编写一个小函数,对两个数据帧的前两列的行进行排序,然后合并它们

sc <- function(x, i) setNames(cbind(data.frame(t(apply(x[i], 1, sort))), x[-i]), names(x))

res <- merge(sc(df_1, 1:2), sc(df_2, 1:2))
res[!duplicated(res), ]  ## remove duplicates
#                      query           target weight
# 1  (+)-1(10),4-Cadinadiene      Falcarinone   0.09
# 2                       A1               A2   0.60
# 3                       A1               A3   0.75
# 4                       A2               A5   0.50
# 5                       A2           Lignin   1.00
# 6                       A3               A5   0.99
# 7                       A4               A5   0.88
# 8                       A4 Leucodelphinidin   1.00
# 10                      A6      Falcarinone   1.00

要返回
“data.frame”
s,只需执行例如
setDF(res)

您的预期输出是否与
df_1
相同?@MarBlo yes。谢谢你的评论。在使用了相同的数据帧之后,我似乎感到困惑。但是,现在我在数据帧中进行了更改。请现在看一下并给出你的建议。非常感谢。但是,你的代码对我不起作用。这其实是我的错。因为我的实际数据帧包含不同类型的数据,我在上一篇文章中给出了一小部分(更具体地说)类似类型的数据。但是,现在请看一下并给出您的建议。您好,代码示例似乎仍然不完整。我给出的解决方案仍然可以很好地工作,我得到了一组标志
FALSE-FALSE-FALSE
,也就是说,它标识了两个相似的行:(A1,A3,075)和(A3,A5,0.99)。可能提供更长的darta样品?请现在检查。我已经更新了数据帧并通知我。在问题中给出的数据帧中应用您的代码后,我只得到1个输出
(+)-1(10),4-Cadinadiene Falcarinone 0.09
,这是否意味着,df_1包含
3列
,df_2包含
2列
,这就是代码工作不完美的原因?非常感谢。您的代码对于文章中给出的演示数据非常有效。但当我将其用于实际数据时,它显示了
错误:无法分配大小为49.8GB的向量。但是,df_1的大小为
1272464字节、65893个对象和3个变量
,df_2的大小为
3507976字节、202732个对象和2个变量
。我不确定这两个小df是如何制作的
94.8GB
。你能给我一些建议吗?对象操作通常会复制对象,也就是说,在操作对象A时,比如说按行操作,首先会创建一个新的空对象B,然后逐行填充。因此,内存大小已经翻了一番。现在计算一下在函数
sc()
中进行的操作,您就知道发生了什么。您可以尝试首先在两个数据帧上使用
sc()
,从工作区中删除
dfu 1/2
,然后将它们放入
merge
。或者,您可以寻找一种不制作副本的解决方案。我尝试使用df_1和df_2的
sc()
函数。这个功能运行得很好。然后我从工作区中删除了所有
对象。最后,应用了
merge
函数,得到了相同的错误。倒霉@Akib62我提出了一个data.table解决方案,请参见编辑。我很好奇,它对你有用吗?
vecseq(f_uuuuuuuu,len_uuuuuu,if(allow.cartesian | | | | notjoin | | |!anyDuplicated(f_uuuuuuuu,:Join结果为2880332行;超过255736=nrow(x)+nrow(I).检查i中是否存在重复的键值,每个键值都会一次又一次地加入x中的同一个组。如果没有问题,请尝试by=.EACHI为每个组运行j以避免较大的分配。如果确实要继续,请使用allow.cartesian=TRUE重新运行。否则,请在常见问题解答、Wiki、堆栈溢出和data.table中搜索此错误消息问题追踪器以获取建议。
same.rows <- duplicated(t(apply(output, 1, sort)))
FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE
output[which(same.rows==F),]


query target weight
1    A1     A2   0.60
2    A1     A3   0.75
3    A2     A5   0.50
5    A3     A5   0.99
6    A4     A5   0.88
sc <- function(x, i) setNames(cbind(data.frame(t(apply(x[i], 1, sort))), x[-i]), names(x))

res <- merge(sc(df_1, 1:2), sc(df_2, 1:2))
res[!duplicated(res), ]  ## remove duplicates
#                      query           target weight
# 1  (+)-1(10),4-Cadinadiene      Falcarinone   0.09
# 2                       A1               A2   0.60
# 3                       A1               A3   0.75
# 4                       A2               A5   0.50
# 5                       A2           Lignin   1.00
# 6                       A3               A5   0.99
# 7                       A4               A5   0.88
# 8                       A4 Leucodelphinidin   1.00
# 10                      A6      Falcarinone   1.00
library(data.table)
setDT(df_1)[,c("query", "target") := list(pmin(query,target), pmax(query,target))]
setDT(df_2)[,c("query", "target") := list(pmin(query,target), pmax(query,target))]
res <- merge(df_1[!duplicated(df_1),], df_2, allow.cartesian=TRUE)
res
#                      query           target weight
# 1: (+)-1(10),4-Cadinadiene      Falcarinone   0.09
# 2:                      A1               A2   0.60
# 3:                      A1               A3   0.75
# 4:                      A2               A5   0.50
# 5:                      A2           Lignin   1.00
# 6:                      A3               A5   0.99
# 7:                      A4               A5   0.88
# 8:                      A4 Leucodelphinidin   1.00
# 9:                      A6      Falcarinone   1.00