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)