2

I have an array with 3 dimensions. I would like to apply a function to the 3rd dimension and return an array. I was very pleased that the plyr::aaply does nearly what I want. However it swaps around the dimensions of my array. The documentation told me that it is idempotent, which (after I'd looked it up) makes me think the structure should remain the same. Here's a reproducible example with the identity function. Can I modify this to retain the order of the array dimensions ?

nRow <- 10
nCol <- 10
nAge <- 7

#creating the array
dimnames <- list(NULL,NULL,NULL)
names(dimnames) <- c("x","y","age")
aF <- array(0, dim=c(nCol,nRow,nAge), dimnames=dimnames)

#aaply the identity function to the 3rd dimension
aTst <- aaply(aF, .margins=3, identity )

dim(aF)
#[1] 10 10  7
dim(aTst)
#[1]  7 10 10

See the dimensions have been changed from 10,10,7 to 7,10,10. I'm aware it can be changed back using aperm but if I can avoid that it would be good.

aTst2 <- aperm(aTst, c(2, 3, 1))

Here's some more detail about what I'm actually trying to do with this (Thanks @Simon O'Hanlon). x & y represent 2D space and I have a vector of ages at each cell on the grid. I want to move each age group, using this function :

rtMove1 <- function(m, pMove=0.4) {

  #create matrices of the 4 neighbour cells to each cell
  mW = cbind( rep(0,nrow(m)), m[,-nrow(m)] )
  mN = rbind( rep(0,ncol(m)), m[-ncol(m),] )
  mE = cbind( m[,-1], rep(0,nrow(m)) )
  mS = rbind( m[-1,], rep(0,ncol(m)) )

  mArrivers <- pMove*(mN + mE + mS + mW)/4
  mStayers <- (1-pMove)*m

  mNew <- mArrivers + mStayers
  return( mNew )
}

To initiate a popn, move all ages in all cells I can do this.

#initiate 100 individuals of age 3 at 5,5
aF[5,5,3] <- 100

aTst <- aaply(aF, .margins=3, rtMove1 )

aTst[3,,]

This works in redistributing the popn :

     1 2 3  4  5  6 7 8 9 10
  1  0 0 0  0  0  0 0 0 0  0
  2  0 0 0  0  0  0 0 0 0  0
  3  0 0 0  0  0  0 0 0 0  0
  4  0 0 0  0 10  0 0 0 0  0
  5  0 0 0 10 60 10 0 0 0  0
  6  0 0 0  0 10  0 0 0 0  0
  7  0 0 0  0  0  0 0 0 0  0
  8  0 0 0  0  0  0 0 0 0  0
  9  0 0 0  0  0  0 0 0 0  0
  10 0 0 0  0  0  0 0 0 0  0

But I need to use aperm to rearrange the dimensions if I want to repeat.

Thanks, Andy

Andy
  • 1,821
  • 13
  • 23
  • Idempotent means that it remains the same with subseqent invocations: ie f^n(x) = f(x). – James Jun 05 '14 at 10:34
  • What function do you actually want to apply? Did you know that the `base::apply` function can operate over as many dimensions of an array as you like? `apply( aF , 1:3 , identity )` or e.g. `apply( aF , 3 , sum )` gives you the sum of each of the 2D matrices across the 3rd dimension (so a vector of 7 `0`s in this case). – Simon O'Hanlon Jun 05 '14 at 10:34

1 Answers1

-1

You could try

aTst <- aaply(aF, c(1,2,3), identity)

That should do the trick

arvind
  • 96
  • 1
  • 6