thiagoveloso
thiagoveloso

Reputation: 2763

R - change matrix values based on another matrix indices

I have two matrices:

m1 <- matrix(runif(750), nrow = 50, byrow=T)
m2 <- matrix(rep(TRUE,750), nrow = 50, byrow=T)

For each m1 row, I need to find the indices of the two lowest values. Then, I need to use the remaining indices (i.e. not the two lowest values) to assign FALSE in m2.

It is fairly easy to do for one row:

ind <- order(m1[1,], decreasing=FALSE)[1:2]
m2[1,][-ind] <- FALSE

Therefore, I can use a loop to do the same for all rows:

for (i in 1:dim(m1)[1]){
  
  ind <- order(m1[i,], decreasing=FALSE)[1:2]
  m2[i,][-ind] <- FALSE
  
}

However, in my data set this loop runs slower than I would like (since my matrices are quite large - 500000x150000).

Is there any faster, R way to achieve the same result without the use of loops?

Upvotes: 2

Views: 91

Answers (4)

akrun
akrun

Reputation: 887048

Using pmap

library(purrr)
pmap_dfr(as.data.frame(m1), ~ min_rank(c(...)) < 3)

Upvotes: 1

jogo
jogo

Reputation: 12559

You can do:

m2 <- t(apply(m1, 1, function(x) rank(x)<3))

Upvotes: 2

ThomasIsCoding
ThomasIsCoding

Reputation: 101247

You can try the code below

m2 <- t(apply(m1,1,function(x) x %in% head(sort(x),2)))

Upvotes: 3

Ronak Shah
Ronak Shah

Reputation: 388907

You can try apply since you have matrix :

val <- rep(TRUE, ncol(m1))
m3 <- t(apply(m1, 1, function(x) {val[-order(x)[1:2]] <- FALSE;val}))

Upvotes: 3

Related Questions