Is there any quick way or build-in function in R to calculation the mean values based on the third dimension?
For example my array is:
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 11 13
[2,] 12 14
, , 3
[,1] [,2]
[1,] 21 23
[2,] 22 24
My output would be:
[,1] [,2]
[1,] mean(1,11,21) mean(3,13,23)
[2,] mean(2,12,22) mean(4,14,24)
Thanks!
?apply is your friend for these types of tasks.
# Make the sample data
j <- array(c(1:4, 11:14, 21:24), c(2,2,3))
# For each combination in the 1st and 2nd dimension
# average over the values in the 3rd.
apply(j, c(1,2), mean)
Related
I want to run mantelhaen.test in R which requires 2x2 contingency tables in 3D array form. These tables can be constructed by looping over each row of the dataframe, but I am trying to figure out if there is a vectorised way to do it - ie using apply(df[,c("col1","col2",etc), margin=1, array(x, c(2,2,11))) to make a 3D array for each row of the table (which would then be wrapped in mantelhaen.test).
I have previously got this to work using matrix() for fisher.test in R and Pandas, but in this case I am running into an issue where array() doesn't seem to have any effect on the data. Here is a reproducible example:
df = data.frame(group1_variant_cases = c(2,1,3,0,0,2), group1_nonvariant_cases = c(100,92,33,40,21,87),
group1_variant_controls = c(1,2,1,0,2,1), group1_nonvariant_controls = c(45,61,70,71,31,55),
group2_variant_cases = c(0,2,1,0,1,0), group2_nonvariant_cases = c(201,99,213,52,178,98),
group2_variant_controls = c(1,0,0,0,1,2), group2_nonvariant_controls = c(67,43,12,88,91,73))
apply(head(df,1), 1, function(x) array(x, c(2,2,2)))
Output:
1
[1,] 2
[2,] 100
[3,] 1
[4,] 45
[5,] 0
[6,] 201
[7,] 1
[8,] 67
Any help appreciated!
With apply, there is simplify argument which is by default TRUE. Change it to FALSE and it works i.e. according to ?apply
If each call to FUN returns a vector of length n, and simplify is TRUE, then apply returns an array of dimension c(n, dim(X)[MARGIN]) if n > 1. If n equals 1, apply returns a vector if MARGIN has length 1 and an array of dimension dim(X)[MARGIN] otherwise.
apply(head(df,3), 1, function(x) array(x, c(2,2,2)), simplify = FALSE)
-output
$`1`
, , 1
[,1] [,2]
[1,] 2 1
[2,] 100 45
, , 2
[,1] [,2]
[1,] 0 1
[2,] 201 67
$`2`
, , 1
[,1] [,2]
[1,] 1 2
[2,] 92 61
, , 2
[,1] [,2]
[1,] 2 0
[2,] 99 43
$`3`
, , 1
[,1] [,2]
[1,] 3 1
[2,] 33 70
, , 2
[,1] [,2]
[1,] 1 0
[2,] 213 12
I have a simple question that I seem to not be able to wrap my head around. I have a 3D array (an image stack) and I am trying to do a projection onto 2D array (e.g. a maximum intensity projection for an image stack). To do this, I have a matrix of indices which indicate the z-stack to use for each pixel.
For example, I have a 3D array which looks like this:
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
And a "selection matrix" which looks like this:
[,1] [,2]
[1,] 1 1
[2,] 2 2
The result of this selection should then be
[,1] [,2]
[1,] 1 3
[2,] 6 8
i.e. the matrix indicates from which "z-columns" of the array to extract the values.
I know this should be a stupid simple thing but I'm drawing a blank on how to do this. Thank you in advance!
One way to do this is to use multi-dimensional array indexing via cbind:
Here is your data and selection matrix:
d <- array(1:8,c(2,2,2))
selec <- matrix(c(1,2,1,2),2,2)
First construct a grid of your selection matrix indices:
selec.ind <- expand.grid(1:nrow(selec),1:ncol(selec))
Then use this with the selection matrix values to access d:
out <- matrix(d[cbind(selec.ind$Var1,selec.ind$Var2,as.vector(selec))], nrow(selec), ncol(selec))
## [,1] [,2]
##[1,] 1 3
##[2,] 6 8
Finally, reshape the result back to the size of the selection matrix.
This will work with any size selection matrix and any number of layers in z.
This only works for array with 2 third dimensions (dim=c(...,...,2))
The data:
ar=array(data=c(1,2,3,4,5,6,7,8),dim = c(2,2,2))
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
selec=matrix(c(1,2,1,2),nrow = 2,ncol = 2)
[,1] [,2]
[1,] 1 1
[2,] 2 2
We use ifelse
ifelse(selec==1,ar[,,1],ar[,,2])
[,1] [,2]
[1,] 1 3
[2,] 6 8
I'm trying to write for each cell entry in a matrix what value is smallest, either its rowsum value or colsum value in a new matrix of the same dimension.
For example:
say I have matrix c which looks like this:
x <- matrix(seq(1:6),2)
x
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Its rowsum and colsum are:
rowSums(x)
[1] 9 12
colSums(x)
[1] 3 7 11
so based on that info, the new matrix should look like this:
[,1] [,2] [,3]
[1,] 3 7 9
[2,] 3 7 11
I've been thinking about using apply but I do not know how I can write an if statement to write the smallest value from either rowsum or colsum for each cell entry. Any ideas?
This can be thought of as an outer product of the row and column sums, where the function takes the minimum value:
outer(rowSums(x), colSums(x), FUN=pmin)
## [,1] [,2] [,3]
## [1,] 3 7 9
## [2,] 3 7 11
x[] <- pmin(rep(colSums(x), each = nrow(x)), rep(rowSums(x), times = ncol(x)))
x
# [,1] [,2] [,3]
# [1,] 3 7 9
# [2,] 3 7 11
If I have a matrix mat1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
it is possible via a very simple command to square all individual values by
mat1 * mat1
[,1] [,2] [,3]
[1,] 1 9 25
[2,] 4 16 36
Now, what I want to do is to create a new matrix where all values are computed by e^(old_value), e.g., e^1, e^2, e^3 and so forth. How can I do this?
exp computes the exponential function
> mat1 <- matrix(1:6, nrow=2)
> exp(mat1)
[,1] [,2] [,3]
[1,] 2.718282 20.08554 148.4132
[2,] 7.389056 54.59815 403.4288
I have X, a three-dimensional array in R. I want to take a vector of indices indx (length equal to dim(X)[1]) and form a matrix where the first row is the first row of X[ , , indx[1]], the second row is the second row of X[ , , indx[2]], and so on.
For example, I have:
R> X <- array(1:18, dim = c(3, 2, 3))
R> X
, , 1
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
, , 2
[,1] [,2]
[1,] 7 10
[2,] 8 11
[3,] 9 12
, , 3
[,1] [,2]
[1,] 13 16
[2,] 14 17
[3,] 15 18
R> indx <- c(2, 3, 1)
My desired output is
R> rbind(X[1, , 2], X[2, , 3], X[3, , 1])
[,1] [,2]
[1,] 7 10
[2,] 14 17
[3,] 3 6
As of now I'm using the inelegant (and slow) sapply(1:dim(X)[2], function(x) X[cbind(1:3, x, indx)]). Is there any way to do this using the built-in indexing functions? I had no luck experimenting with the matrix indexing methods described in ?Extract, but I may just be doing it wrong.
Maybe like this:
t(sapply(1:3,function(x) X[,,idx][x,,x]))
I may be answering the wrong question (I can't reconcile your first description and your sample output)... This produces your sample output, but I can't say that it's much faster without running it on your data.
do.call(rbind, lapply(1:dim(X)[1], function(i) X[i, , indx[i]]))
Matrix indexing to the rescue! No applys needed.
Figure out which indices you want:
n <- dim(X)[2]
foo <- cbind(rep(seq_along(indx),n),
rep(seq.int(n), each=length(indx)),
rep(indx,n))
(the result is this)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 1 3
[3,] 3 1 1
[4,] 1 2 2
[5,] 2 2 3
[6,] 3 2 1
and use it as index, converting back to a matrix to make it look like your output.
> matrix(X[foo],ncol=n)
[,1] [,2]
[1,] 7 10
[2,] 14 17
[3,] 3 6