【问题标题】:R - get the column index of a matrix based on a function for each rowR - 根据每行的函数获取矩阵的列索引
【发布时间】:2014-07-28 01:59:48
【问题描述】:
> set.seed(2014)
> m<-matrix(sample(10,16,replace=TRUE),nrow=4)
> m
     [,1] [,2] [,3] [,4]
[1,]    3    6    1    7
[2,]    2    1    2    6
[3,]    7   10    7    7
[4,]    4    7    1    5

对于每一行,我想检索该行中大于或等于最后一个元素的第一个元素的索引,否则为 NA。因此,对于第 1 行,前三列中没有元素>=7,因此应返回 NA。对于第 3 行,第一个元素 >=7,因此应返回 1。

结果应该是长度为 4 的向量,等于 (NA, NA, 1, 2)

我认为解决方案可能涉及应用,但我不知道如何正确解决。另外,请记住效率,因为我的真实矩阵可能有数百万行。

谢谢

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    这是一种可能性——不过,它可能会为中期结果占用大量空间。

    set.seed(2014)
    m <- matrix(sample(10,16,replace=TRUE),nrow=4)
    m2 <- sweep(m,1,m[,ncol(m)],">=")
    v <- apply(m2,1,function(x) which(x)[1])
    ifelse(v==ncol(m),NA,v)
    

    基于 Rcpp 的解决方案仅在需要时迭代每一行会更快(如果有人编写了一个通用、快速的 which.first() 函数,那就太好了...

    【讨论】:

    • 我支持which.first的需要——写起来应该不难吧? (说我没有 C 编程经验)。
    【解决方案2】:

    另一个尝试:

    apply(m[,-ncol(m)] >= m[,ncol(m)], 1, match, x=TRUE)
    #[1] NA NA  1  2
    

    或者删除apply

    chk <- m[,-ncol(m)] >= m[,ncol(m)]
    replace(max.col(chk,"first"), rowSums(chk)==0, NA)
    #[1] NA NA  1  2
    

    它实质上创建了除最后一列之外的所有m 列的逻辑矩阵,测试值是否为&gt;= 到最后一列的值。然后使用match提取每行第一个TRUE的位置。

    针对 Ben 的解决方案使用更大的矩阵测试速度:

    m<-matrix(sample(10,1.6e6,replace=TRUE),nrow=4e5)
    
    replicate(5,
    system.time(
     apply(m[,-ncol(m)] >= m[,ncol(m)], 1, match, x=TRUE)
    ))
    #elapsed     0.7 0.77 0.77 0.76 0.93
    
    replicate(5,
    system.time({
     m2 <- sweep(m,1,m[,ncol(m)],">=")
     v <- apply(m2,1,function(x) which(x)[1])
     ifelse(v==ncol(m),NA,v)
    }))
    #elapsed    1.11 1.04 1.10 1.06 1.06
    

    【讨论】:

      【解决方案3】:

      这是一个简单的实现:

      getFirst <- function(vec) {
        temp = which(vec[1:(length(vec)-1)] >= vec[length(vec)])  
        if(length(temp) == 0) NA else temp[1]
      }
      
      index <- NULL
      for(i in 1:nrow(m)){
        index[i] <- getFirst(m[i,])
      }
      index
      

      您也可以一步完成:

      apply(m,1,function(vec) {
        temp = which(vec[1:(length(vec)-1)] >= vec[length(vec)])  
        if(length(temp) == 0) NA else temp[1]
      })
      

      【讨论】:

        猜你喜欢
        • 2016-07-09
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-01
        • 1970-01-01
        相关资源
        最近更新 更多