【问题标题】: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

【问题讨论】:

    标签: r


    【解决方案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,]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        相关资源
        最近更新 更多