将两列与另外两列匹配

Posted

技术标签:

【中文标题】将两列与另外两列匹配【英文标题】:match two columns with two other columns 【发布时间】:2011-10-16 08:45:03 【问题描述】:

我有几行数据(制表符分隔)。我想找到与每行中两列 (3rd & 4th) 中的元素与另外两列 (10th & 11th) 匹配的行。例如,在第 1 行第 3 和 4 列 中的 95428891 和 95443771 匹配 第 19 行中的第 10 和 11 列 中的元素/强>。同样,倒数也成立。 第 19 行第 3 列和第 4 列中的元素也匹配 第 1 行中的第 10 列和第 11 列中的元素。我需要能够遍历每一行并输出相应匹配的行索引。有时可能只有一列匹配而不是两者匹配(因为有时有重复的数字),但我只需要选择两列都匹配以及相互匹配的行。因此,最好在存在相互匹配的情况下输出行索引,例如,1 & 19 作为制表符分隔值(可能在不同的 data.frame 对象中)。并且没有相互匹配的行可以单独输出。我正在尝试在 R 中实现这一点以遍历多行数据。

1313    chr2    95428891    95443771    14880   chr2:96036782   205673  +   chr2    96036782    96052481
1313    chr2    95428896    95443771    14875   chr2:97111880   205214  -   chr2    97111880    97127588
1313    chr2    95443771    95526464    82693   chr2:95609272   1748861 -   chr2    95609272    95691902
1313    chr2    95477143    95486318    9175    chr2:97616847   177391  +   chr2    97616847    97626039
1313    chr2    95486323    95521267    34944   chr2:97035158   268351  +   chr2    97035158    97070183
1313    chr2    95515418    95525958    10540   chr2:95563236   132439  +   chr2    95563236    95572666
1314    chr2    95563236    95572666    9430    chr2:95515418   132439  +   chr2    95515418    95525958
1314    chr2    95563236    95572666    9430    chr2:95609778   126017  -   chr2    95609778    95620287
1314    chr2    95563236    95569115    5879    chr2:97064308   89848   +   chr2    97064308    97070183
164     chr2    95609272    95691902    82630   chr2:95443771   1748861 -   chr2    95443771    95526464
1314    chr2    95609778    95620287    10509   chr2:95563236   126017  -   chr2    95563236    95572666
1314    chr2    95614473    95649363    34890   chr2:97035158   394821  -   chr2    97035158    97070173
1314    chr2    95649368    95658543    9175    chr2:97616847   177822  -   chr2    97616847    97626039
164     chr2    95775062    95814080    39018   chr2:97578938   0       -   chr2    97578938    97616780
1315    chr2    95778788    95781856    3068    chr2:97609982   31302   -   chr2    97609982    97616788
164     chr2    95780657    95829665    49008   chr2:96053880   882178  -   chr2    96053880    96102738
1316    chr2    95829982    95865446    35464   chr2:97296848   242680  -   chr2    97296848    97333087
1316    chr2    95829982    95935104    105122  chr2:97438085   1169669 +   chr2    97438085    97544431
1317    chr2    96036782    96052481    15699   chr2:95428891   205673  +   chr2    95428891    95443771

【问题讨论】:

【参考方案1】:

接受的答案有效,但是对于大型数组,通常超过 50k 左右,您会遇到内存问题,因为您正在创建的矩阵很大。

我会这样做:

match(
  interaction( indat$V3, indat$V10),
  interaction( indat$V4, indat$V11)
);

它将所有感兴趣的值连接成因子并进行匹配。

不确定这是否更快,但内存效率更高。

【讨论】:

【参考方案2】:

您没有表明您认为正确答案是什么,并且当您谈论“存在互惠匹配”时,您的术语似乎有点含糊,但如果我正确理解该任务,即找到 col.3 = 的所有行= col.10 & col.4 == col.11,那么这应该完成任务:

which( outer(indat$V4, indat$V11, "==") & 
       outer(indat$V3, indat$V10, "=="), 
       arr.ind=TRUE)
# result
      row col
 [1,]  19   1
 [2,]  10   3
 [3,]   7   6
 [4,]   8   6
 [5,]   6   7
 [6,]  11   8
 [7,]   3  10
 [8,]   7  11
 [9,]   8  11
[10,]   1  19

外部函数将函数'FUN',在这种情况下为“==”,应用于x和y的所有双向组合,它的第一个和第二个参数,所以这里我们得到一个带有逻辑条目的nxn矩阵和I我正在采用两个这样的矩阵的逻辑“和”。所以与其他行匹配的行是:

unique( c(which( outer(indat$V4, indat$V11, "==") & 
outer(indat$V3, indat$V10, "=="), 
arr.ind=TRUE) ))

#[1] 19 10  7  8  6 11  3  1

所以与 no 匹配的集合,假设一个名为 indat 的 data.frame 是:

matches <- unique( c(which( outer(indat$V4, indat$V11, "==") & 
                      outer(indat$V3, indat$V10, "=="), arr.ind=TRUE) ))
indat[ ! 1:NROW(indat) %in% matches, ]

匹配的有:

indat[ 1:NROW(indat) %in% matches, ]

【讨论】:

感谢您的回答。我所说的互惠匹配是什么意思,...查看第 1 行和第 19 行。第 1 行中第 3,4 列中的值与第 19 行中第 10,11 列中的值相同。同样,第 19 行中第 3,4 列中的值与第 1 行中的第 10,11 列相同。因此输出第 1 行和第 19 行。类似地,第 6 行和第 7 行在第 3,4 列和第 10,11 列中具有相互匹配。 @user645600 我的解决方案肯定已经确定了这些情况。我的复选标记在哪里? @什么是复选标记?我很少使用这个论坛并且不确定协议。 能不能也给arr.ind=TRUE加个解释,它是干什么用的?谢谢。【参考方案3】:

下面的函数compare利用了R的快速排序能力。函数参数ab 是矩阵; a 中的行被筛选以匹配b 中任意数量的列的行。如果列顺序无关紧要,请设置row_order=TRUE 以使行条目按升序排序。猜猜这个函数应该也适用于数据框和字符/因子列,以及a 和/或b 中的重复条目。尽管使用了forwhile,但对于a 的每一行(或0,如果未找到匹配项)返回b 中的第一行匹配相对较快。

compare<-function(a,b,row_order=TRUE)

    len1<-dim(a)[1]
    len2<-dim(b)[1]
    if(row_order)
        a<-t(apply(t(a), 2, sort))
        b<-t(apply(t(b), 2, sort))
    
    ord1<-do.call(order, as.data.frame(a))
    ord2<-do.call(order, as.data.frame(b))
    a<-a[ord1,]
    b<-b[ord2,] 
    found<-rep(0,len1)  
    dims<-dim(a)[2]
    do_dims<-c(1:dim(a)[2])
    at<-1
    for(i in 1:len1)
        for(m in do_dims)
            while(b[at,m]<a[i,m])
                at<-(at+1)      
                if(at>len2)break              
            
            if(at>len2)break
            if(b[at,m]>a[i,m])break
            if(m==dims)found[i]<-at
        
        if(at>len2)break
    
    return(found[order(ord1)]) # indicates the first match of a found in b and zero otherwise




# example data sets:
a <- matrix(sample.int(1E4,size = 1E4, replace = T), ncol = 4)
b <- matrix(sample.int(1E4,size = 1E4, replace = T), ncol = 4)
b <- rbind(a,b) # example of b containing a


# run the function
found<-compare(a,b,row_order=TRUE)
# check
all(found>0) 
# rows in a not contained in b (none in this example):
a[found==0,]

【讨论】:

以上是关于将两列与另外两列匹配的主要内容,如果未能解决你的问题,请参考以下文章

根据条件将两列与 nan 连接(python)

如何将 R 中的两列与特定符号合并?

如何将两列与数据合并,如果一列的单元格为空,则相邻的单元格已满?

如何将 DataFrame(包括数组)中的两列与 CSV(Dataframe/Dictionary)中的两列匹配

在 Pandas 中将两列与 NaN 进行比较并获得差异

怎么将两列数据合并