【问题标题】:matrix index subsetting with another matrix矩阵索引子集与另一个矩阵
【发布时间】:2017-06-02 01:44:41
【问题描述】:

将两个矩阵(一和二)匹配在一起并提取矩阵二的索引以进行匹配的快速方法是什么?矩阵二很大(数百到数千行)。

one
[,1] [,2]
   9   11
  13    2


head(two)
   [,1][,2]
[1,] 9 11
[2,] 11 9
[3,]  2 3
[4,] 13 2
[5,]  2 4
[6,]  3 3

输出应该是(注意索引 2 不是输出值)

1 4  

【问题讨论】:

标签: r matrix subset


【解决方案1】:

一种方法:

a = apply(one, 1, paste0, collapse = "-")
b = apply(two, 1, paste0, collapse = "-")
match(a, b)

#[1] 1 4

我们将两个矩阵的所有列按行粘贴在一起,然后匹配它们以获得相同的行。

仅供参考,

a
#[1] "9-11" "13-2"
b
#[1] "9-11" "11-9" "2-3"  "13-2" "2-4"  "3-3" 

【讨论】:

    【解决方案2】:

    您可以编写一个 C++ 循环来相当快地完成它

    library(Rcpp)
    
    cppFunction('NumericVector matrixIndex(NumericMatrix m1, NumericMatrix m2){
    
    int m1Rows = m1.nrow();
    int m2Rows = m2.nrow();
    NumericVector out;  
    
    for (int i = 0; i < m1Rows; i++){
      for (int j = 0; j < m2Rows; j++){
    
        if(m1(i, 0) == m2(j, 0) && m1(i, 1) == m2(j, 1)){
            //out[j] = (j+1);
            out.push_back(j + 1);
        }
      }
    }
    
    return out;
    
    }')
    
    matrixIndex(m1, m2)
    [1] 1 4
    

    虽然我怀疑先预分配结果向量会更快,比如

    cppFunction('NumericVector matrixIndex(NumericMatrix m1, NumericMatrix m2){
    
    int m1Rows = m1.nrow();
    int m2Rows = m2.nrow();
    NumericVector out(m2Rows);  
    
    for (int i = 0; i < m1Rows; i++){
      for (int j = 0; j < m2Rows; j++){
    
        if(m1(i, 0) == m2(j, 0) && m1(i, 1) == m2(j, 1)){
            out[j] = (j+1);
            //out.push_back(j + 1);
        }
      }
    }
    
    return out;
    
    }')
    
    matrixIndex(m1, m2)
    [1] 1 0 0 4 0 0
    ## 0 == nomatch. 
    

    【讨论】:

      【解决方案3】:

      您不会说“快速”是指计算时间还是人员时间。如果只需要做一次,如果优化人员时间,整体时间可能是最短的,而且 Ronak 的答案将难以被击败,它清晰而稳健。

      如果所有数字都小于某个数字(例如,100,如您的示例数据),您可以做类似的事情,但使用算术将两列组合在一起然后匹配。我怀疑(但尚未测试)这会比转换为字符向量更快。当然,根据您的情况,还有其他算术选项。

      a <- one[,1]*100 + one[,2]
      b <- two[,1]*100 + two[,2]
      match(a, b)
      

      【讨论】:

        【解决方案4】:

        我们可以使用%in%

        which(do.call(paste, as.data.frame(two)) %in% do.call(paste, as.data.frame(one)))
        #[1] 1 4
        

        【讨论】:

          猜你喜欢
          • 2012-12-29
          • 2016-11-17
          • 2015-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-06
          • 2017-02-10
          相关资源
          最近更新 更多