EDC
EDC

Reputation: 633

Vectorizing nested-loop

For the last 3 hours I am trying to vectorize some piece of code. The idea is to loop over a matrix and compare all the values with the mean over the columns. If the values are larger, set them to 999.

comparevalues <- function(y){
  x <- apply(y,2, function(y) mean(y,na.rm=T))    
  for (j in 1:ncol(y)){
    for (i in 1:nrow(y)){
      if (!is.na(y[i,j]) & y[i,j] > x[j]) y[i,j] <- 999
    }
  }
  return(y)
}

Testing, e.g. with:

m1 <- matrix(c(1:3,NA,2.4,2.8,3.9,0,1,3,0,2,1.3,2,NA,7,3.9,2.4),6,3)
comparevalues(m1)

results in:

      [,1] [,2]  [,3]
[1,]    1  999   1.3
[2,]    2    0   2.0
[3,]  999    1    NA
[4,]   NA  999 999.0
[5,]  999    0 999.0
[6,]  999  999   2.4

My question is:

1) Can this kind of structure be vectorized, and if so, how can it be done?

2) I am trying to use apply and similar functions in this context. Likely there are different ways to solve this, but for learning purpose, I'd appreciate if someone could address apply as well. However if there are better ways I'd like to know them too.

Upvotes: 1

Views: 203

Answers (1)

akrun
akrun

Reputation: 887048

We use the colMeans to get the mean of the columns of 'm1', replicate it using col(m1), check whether the 'm1' is greater than those value to get a logical matrix, extract the elements of 'm1' using that and assign it to 999.

m1[m1 >colMeans(m1, na.rm=TRUE)[col(m1)]] <- 999
m1
#     [,1] [,2]  [,3]
#[1,]    1  999   1.3
#[2,]    2    0   2.0
#[3,]  999    1    NA
#[4,]   NA  999 999.0
#[5,]  999    0 999.0
#[6,]  999  999   2.4

Upvotes: 1

Related Questions