Home > database >  Add matrix to all slices in an array
Add matrix to all slices in an array

Time:12-06

This seems like a very basic R question, but had some difficulty adding a matrix to all slices in an array (actually an image stack, and before anyone asks, there is a reason I want to do this in R). As an example I want to add the matrix sampleMean to all the slices in the third dimension of combinedAtten:

combinedAtten <- array(rexp(300), dim = c(10, 10, 3))
sampleMean <- matrix(rep(1:2, 50), ncol = 10)
distortedMask <- apply(combinedAtten, 3, function(x)x   sampleMean)
dim(distortedMask)

Unexpectedly, the output is a matrix with dims [100, 3], not an array with dims [10, 10, 3]. I have a clumsy solution of using simplify = F, then combining the list back into an array, as follows:

distortedMask <- apply(combinedAtten, 3, function(x)x   sampleMean, simplify = F)
distortedMask <- array(unlist(distortedMask), dim = dim(combinedAtten))
dim(distortedMask)

Just as a learning exercise, I am curious as to why apply reshapes the array in the first place, and whether there is slightly less clumsy solution than using apply to create a list, unlisting it, then recreating the array from the resulting vector.

CodePudding user response:

An option is to replicate the 'sampleMean' to make the dimensions same and add ( )

distoredMask <- combinedAtten   replicate(dim(combinedAtten)[3], sampleMean)

NOTE: By default replicate uses simplify = "array"

-check the dim

> all.equal(dim(combinedAtten), dim(distoredMask))
[1] TRUE

Or if we want to use the OP's method, then another option is wrap with simplify2array on the list output

distoredMask2 <- simplify2array(apply(combinedAtten, 3,
     function(x)x   sampleMean, simplify = FALSE))

-checking

> dim(distoredMask2)
[1] 10 10  3
> identical(distoredMask, distoredMask2)
[1] TRUE

CodePudding user response:

Edit: Now that I understand what the goal was, I can suggest that all you needed to do was alter the dimension of the result you had constructed that was 100 x 3

dim(distortedMask) <- c(10,10,3)
dim(distortedMask)
#[1] 10 10  3

You could have added just 3 copies to the original matrix as well


Prior off target suggestion:

identical(distortedMask, combinedAtten   c(sampleMean,sampleMean,sampleMean) )
[1] TRUE

' See if abind in the abind package is what you want:

> library(abind)
> str(abind(combinedAtten,sampleMean))
 num [1:10, 1:10, 1:4] 0.862 0.639 0.3 0.193 0.259 ...
 - attr(*, "dimnames")=List of 3
  ..$ : NULL
  ..$ : NULL
  ..$ : NULL

That looks like what I think you wanted, so try:

 distortedMask <- abind(combinedAtten,sampleMean) # after library(abind)
  •  Tags:  
  • r
  • Related