0

I have a function f(x, y) that returns a list of 8 logical vectors, where x and y are integers. I want to populate a three-dimensional array M so that M[x, y, z] is the number of TRUEs in the zth element of f(x, y). I can do this with nested for loops, but I know those are frowned upon in R. I think there's a more elegant way, using either outer or rbind and sapply but I can't figure it out. Here's my code with the nested for loops:

M <- array(dim=c(150, 200, 8))
for(j in 1:150) {
  for(k in 1:200) {
    rsu <- f(j, k)
    for(z in 1:8) {
      M[j, k, z] <- sum(rsu[[z]])
}}}

What is a more efficient/elegant way of populating this array that gives the same result?

Edited to add: For purposes of this question, treat f as a black box. In reality it involves various calculations and lookups about eight different satellites, but here's a dummy function that will generate some data for this example:

is.prime <- function(n) n == 2L || all(n %% 2L:ceiling(sqrt(n)) != 0)
#source for is.prime function:
# https://stackoverflow.com/questions/19767408/prime-number-function-in-r

f <- function(x,y) {
retlist <- list()
retlist[[1]] <- c(FALSE, FALSE, rep(TRUE, x))
retlist[[2]] <- c(TRUE, TRUE, rep(FALSE, y), rep(TRUE, y))
retlist[[3]] <- c(is.prime(x), is.prime(y), is.prime(x+y), is.prime(x+y+3),  sapply(x:(2*(x+y)), is.prime))
retlist[[4]] <- c(x+y %% 5 == 0, x*y %% 6 ==0)
retlist[[5]] <- retlist[[(x+y) %% 4 + 1]]
retlist[[6]] <- retlist[[y %% 4 + 1]]
retlist[[7]] <- retlist[[x %% 6 + 1]]
retlist[[8]] <- sapply(abs(x-y):(7L*x+y+1), is.prime)
return(retlist)
}
Montgomery Clift
  • 445
  • 3
  • 13
  • 1
    What is `f(j, k)` The code is giving error `Error in f(j, k) : could not find function "f"` – akrun Sep 22 '17 at 07:37
  • @akrun I'm not at liberty to post the actual function f, but I've edited the example to provide a dummy function that will give some data. – Montgomery Clift Sep 22 '17 at 14:12

2 Answers2

0

Here's how to the populate the array, giving the same results, using nested functions and sapply instead of for:

f2 <- function(x,y) {
  rsu <- f(x,y)
  values <- vapply(1:8, FUN=function(z) sum(rsu[[z]]), FUN.VALUE=1L)
  }
f3 <- function(x) array(data=t(sapply(1:200, FUN=function(w) f2(x,w))), dim=c(1,200,8))
M2 <- array(data=t(sapply(1:150, FUN=f3)), dim=c(150,200,8))
Montgomery Clift
  • 445
  • 3
  • 13
0

Here's how to do it with outer. But it's unintuitive; the matrix data are assigned within the function. I don't understand why I need to invoke Vectorize(f2) here instead of simply f2.

M2 <- array(dim=c(150, 200, 8))
f2 <- function(x, y) {
   rsu <- f(x, y)
   M2[x, y, ] <<- vapply(1:8, FUN=function(z) sum(rsu[[z]]), FUN.VALUE=1L)
   return(0L)
   }
ABC <- outer(1:150, 1:200, Vectorize(f2))
Montgomery Clift
  • 445
  • 3
  • 13