jamesguy0121
jamesguy0121

Reputation: 1254

Use apply functions to iteratively update the same object (for loop to apply function)

I have a matrix which I want to put into an apply function and use the location and value of each object in the matrix to select and update positions in a 3 dimensional array. I can do this very easily in a for loop, but I am curious if it is possible to do it in an apply function. I seem to be having trouble wrapping my head around that. I have some things that work, but not ideally.

foo <- matrix(c(3, NA, NA, 1, NA, 3, NA, 2, NA),  
       3, 3, byrow = TRUE)
bar <- array(NA, c(3, 3, 3))

This is the for loop that does exactly what I am looking for

for (i in 1:3){
  for (j in 1:3){
    if (!is.na(foo[i, j])){
      bar[i, j, foo[i, j]] <- TRUE
    }
  }
}

This is the best that I have gotten so far. It does update the array, but it prints out a list of the assignments made at each iteration. Also if it is possible to do this without the <<- operator, that would be ideal.

fillArray <- function(x) {
  if (!is.na(foo[x[1], x[2]])) {
    bar[x[1], x[2], foo[x[1], x[2]]] <<- TRUE
  }
}

apply(expand.grid(1:3, 1:3), 1, fillArray)

I would like to get the same result as the for loop does.

Upvotes: 0

Views: 175

Answers (1)

akrun
akrun

Reputation: 887951

It is easier to construct a three column i, j, k matrix index and then do the assignment

# index matrix
m1 <- cbind(as.matrix(expand.grid(1:3, 1:3)), c(foo))
bar1 <- bar # initial data
# remove the NA rows of the third column of index
bar1[m1[!is.na(m1[,3]),, drop  = FALSE]] <- TRUE

-checking with the output from OP

identical(bar, bar1)
#[1] TRUE

Upvotes: 1

Related Questions