R - 根据每行的函数获取矩阵的列索引

时间:2014-07-28 01:59:49

标签: r matrix

> 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行,前三列中没有元素&gt; = 7,因此应返回NA。对于第3行,第一个元素是> = 7,因此应该返回1。

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

我认为解决方案可能涉及申请,但我无法弄清楚如何做到正确。另外,请记住效率,因为我的真实矩阵可能有数百万行。

由于

3 个答案:

答案 0 :(得分:3)

这是一种可能性 - 虽然它可能会占用大量空间用于中期结果。

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()函数会很好......

答案 1 :(得分: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列的逻辑矩阵,测试值是否为>=到最后一列值。然后使用TRUE提取每行中第一个match的位置。

使用比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

答案 2 :(得分:1)

这是一个简单的实现:

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]
})