0

I have a n x 3 x m array, call it I. It contains 3 columns, n rows (say n=10), and m slices. I have a computation that must be done to replace the third column in each slice based on the other 2 columns in the slice.

I've written a function insertNewRows(I[,,simIndex]) that takes a given slice and replaces the third column. The following for-loop does what I want, but it's slow. Is there a way to speed this up by using one of the apply functions? I cannot figure out how to get them to work in the way I'd like.

for(simIndex in 1:m){
     I[,, simIndex] = insertNewRows(I[,,simIndex])
}

I can provide more details on insertNewRows if needed, but the short version is that it takes a probability based on the columns I[,1:2, simIndex] of a given slice of the array, and generates a binomial RV based on the probability.

It seems like one of the apply functions should work just by using I = apply(FUN = insertNewRows, MARGIN = c(1,2,3)) but that just produces gibberish..?

Thank you in advance! IK

  • 1
    It would be helpful if you could provide us with a reproducible [minimal working example](https://en.wikipedia.org/wiki/Minimal_working_example) that we can copy and paste to better understand the issue and test possible solutions. You can share datasets with `dput(YOUR_DATASET)` or smaller samples with `dput(head(YOUR_DATASET))`. (See [this answer](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example#5963610) for some great advice.) – ktiu Jun 17 '21 at 17:51

1 Answers1

0

The question has not defined the input nor the transformation nor the result so we can't really answer it but here is an example of adding a row of ones to to a[,,i] for each i so maybe that will suggest how you could solve the problem yourself.

This is how you could use sapply, apply, plyr::aaply, reshaping using matrix/aperm and abind::abind.

# input array and function
a <- array(1:24, 2:4)
f <- function(x) rbind(x, 1)  # append a row of 1's

aa <- array(sapply(1:dim(a)[3], function(i) f(a[,,i])), dim(a) + c(1,0,0))
aa2 <- array(apply(a, 3, f), dim(a) + c(1,0,0))
aa3 <- aperm(plyr::aaply(a, 3, f), c(2, 3, 1))
aa4 <- array(rbind(matrix(a, dim(a)[1]), 1), dim(a) + c(1,0,0))
aa5 <- abind::abind(a, array(1, dim(a)[2:3]), along = 1)

dimnames(aa3) <- dimnames(aa5) <- NULL 
sapply(list(aa2, aa3, aa4, aa5), identical, aa)
## [1] TRUE TRUE TRUE TRUE

aa[,,1]
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
## [3,]    1    1    1

aa[,,2]
##      [,1] [,2] [,3]
## [1,]    7    9   11
## [2,]    8   10   12
## [3,]    1    1    1

aa[,,3]
##      [,1] [,2] [,3]
## [1,]   13   15   17
## [2,]   14   16   18
## [3,]    1    1    1

aa[,,4]
##      [,1] [,2] [,3]
## [1,]   19   21   23
## [2,]   20   22   24
## [3,]    1    1    1
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • Thank you! I think this essentially does what I would like. Would you be able to tell me a little about what 1:4 and c(3,3,4) do inside the assignment for aa? It seems like 1:4 give the indices that are plugged in for i, right? Then c(3,3,4) gives the dimensions of the new array with the row of 1s appended? If so, this is almost exactly what I needed! – user16254869 Jun 17 '21 at 18:58
  • I have replaced the hard coded items to make it more understandable and added a 4th approach. – G. Grothendieck Jun 17 '21 at 19:02
  • Added another solution. – G. Grothendieck Jun 17 '21 at 22:26