i want to subset a 3-dimensional array with three matrices where each matrix represents one dimension.
An example:
set.seed(1)
A = array(sample(1:10,24, replace=TRUE), dim=c(3,4,2))
ind_dimension1 = matrix(c(1,3,2,1), nrow=2)
ind_dimension2 = matrix(c(4,3,2,1), nrow=2)
ind_dimension3 = matrix(c(1,2,2,1), nrow=2)
As result i want a matrix with the same dimension as the subsetting matrices, i.e. 2x2:
# A[1,4,1](=1) A[2,2,2](=8)
# A[3,3,2](=10) A[1,1,1](=3)
In Matlab this can be done by:
A(sub2ind(size(A), ind_dimension1, ind_dimension2, ind_dimension3))
With two dimensions, i.e. A2=A[,,1], the Matlab command sub2ind(size(A2), ind_dimension1, ind_dimension2) can be replicated in R with (ind_dimension2-1)*dim(A2)[2]+ind_dimension1 as mentioned by Hiebeler (2010) https://cran.r-project.org/doc/contrib/Hiebeler-matlabR.pdf (Page 5). This is not possible in higher dimensions.
Thanks in advance.
How about this?
myMat <- matrix(A[cbind(c(ind_dimension1),
c(ind_dimension2),
c(ind_dimension3))],
dim(ind_dimension1))
myMat
[,1] [,2]
[1,] 1 8
[2,] 10 3
This uses matrix subsetting (see help("[")) to extract the desired elements. The dimension matrices are turned into vectors with c, and then recombined into a matrix with cbind that is used to extract from the array. The resulting vector is fed to matrix and the desired dimensions are produces with dim.
Related
In R, I can have piece-wise multiplication between a matrix and a (conformal) vector, for example:
X <- matrix(c(1, 2, 3, 4), nrow = 2)
a <- c(0, 1)
X * a
Each row of the matrix is then multiplied with the corresponding vector element. I can also do the same for arrays of dimension bigger than 2:
XX <- array(X, dim = c(2, 2, 2))
a <- c(0, 1)
XX * a
Again each row is multiplied with the corresponding vector element. Can I do something similar for an 3d array and a 2d matrix? I just want every submatrix of the array to be element-wise multiplied with a matrix.
you cannot multiply it with 2d matrix, but you could try this
XX*c(1,2,3,4)
It is possible to achieve 'piece'-wise multiplication (or any arithmetic operation, really) by first constructing an appropriate array from the lesser-dimensional matrix and then performing the element-wise operation. In your example:
X <- 1:8
XX <- array(X, dim = c(2, 2, 2))
a <- c(0, 1)
# construct array for point-wise operation
expandeda <- array(a, dim=dim(XX))
XX * expandeda
The result of this shows that, as you said, the individual elements of a are applied row-wise (i.e. to the first dimension of the array):
, , 1
[,1] [,2]
[1,] 0 0
[2,] 2 4
, , 2
[,1] [,2]
[1,] 0 0
[2,] 6 8
Constructing an appropriate array using array(a, dim=dim(XX)) doesn't just work for 3d and 2d matrices but for any dimensionality of arrays, as long as length(a) == dim(XX)[1].
R comes with three types to store lists of homogenous objects: vector, matrix and array.
As far as I can tell:
vector is special cases for 1 dimension arrays
matrix is a special case for 2 dimensions arrays
array can also have any dimension level (including 1 and 2).
What is the difference between using 1D arrays over vectors and 2D arrays over matrices? Do we need to cast between those, or will it happen automagically?
There is no difference between a matrix and a 2D array:
> x <- matrix(1:10, 2)
> y <- array(1:10, c(2, 5))
> identical(x, y)
[1] TRUE
...
matrix is just a more convenient constructor, and there are many functions and methods that only accept 2D arrays (a.k.a. matrices).
Internally, arrays are just vectors with a dimension attribute:
...
> attributes(x)
$dim
[1] 2 5
> dim(x) <- NULL
> x
[1] 1 2 3 4 5 6 7 8 9 10
> z <- 1:10
> dim(z) <- c(2, 5)
> is.matrix(z)
[1] TRUE
To cite the language definition:
Matrices and arrays are simply vectors with the attribute dim and
optionally dimnames attached to the vector.
[...]
The dim attribute is used to implement arrays. The content of the
array is stored in a vector in column-major order and the dim
attribute is a vector of integers specifying the respective extents of
the array. R ensures that the length of the vector is the product of
the lengths of the dimensions. The length of one or more dimensions
may be zero.
A vector is not the same as a one-dimensional array since the latter
has a dim attribute of length one, whereas the former has no dim
attribute.
I am looking for a fast way to remove redundant dimensions from an array in R, similar to the squeeze() command in MATLAB.
Right now I combine the melt() and the cast() commands from the reshape2 package, but there should be a less intricate way of doing the same.
This is how I do it so far:
require(reshape2)
array3d <- array(rep(0,4),dim=c(1,2,2)) # create a 2*2 matrix within a 3-d array
acast(melt(array3d),Var2~Var3) # recover the matrix
It sounds like you're looking for drop(), which "delete[s] the dimensions of an array which have only one level".
drop(array3d)
# [,1] [,2]
# [1,] 0 0
# [2,] 0 0
Is it possible to create matrix of vectors in R? I mean the elements of this matrix must be vectors. For example mat[1,3] == c(6,8,9)
i must create 40x40 matrix and i need to fill it manually.
This is not a matrix but an array:
myarray <- array(1:24, c(2,4,3))
myarray[1,3,]
#[1] 5 13 21
Well, you can add dimensions to a list, so that it resembles a matrix where the elements can be anything you want, including vectors of different length. For example:
foo <- as.list(numeric(2^2))
dim(foo) <- c(2,2)
# Assignment per element:
foo[[1,1]] <- 1:4
foo[[1,2]] <- 1:10
foo[[2,1]] <- "foo"
foo[[2,2]] <- list(foo)
Gives you a weird looking object:
> foo
[,1] [,2]
[1,] Integer,4 Integer,10
[2,] "foo" List,1
Where each element basically is a vector. Still, this is hardly ever the best way of doing this. If the vectors are the same length an array as described by Roland is much more appropriate.
I was quite surprised when I found out that for x <- array(0, c(5,3,1)), e.g. x[2,,] returns a vector instead of a two-dimensional array (or matrix).
Why is it that this array is obviously interpreted as 5 vectors of length 3 instead of 5 3-by-1 arrays? attr(array(0, c(5,3,1)), "dim") yields [1] 5 3 1 as expected, so it seems that the last dimension didn't get lost.
How can I make sure that I get a two-dimensional array? I understand that arrays are nothing but vectors with additional attributes, but I don't understand this apparent "inconsistent" behaviour.
Please enlighten me :) I'm using a three-dimensional array in the context of another function in order to store several matrices. In general, these matrices have n-by-m shape where, in particular, m can be 1 (although it is usually higher).
It's a classic, and has been in the R FAQ for over a decade too: use drop=FALSE to prevent the collapsing of a 1-row / col matrix to a vector.
R> M <- matrix(1:4,2,2)
R> M
[,1] [,2]
[1,] 1 3
[2,] 2 4
R> M[,1]
[1] 1 2
R> M[,1,drop=FALSE]
[,1]
[1,] 1
[2,] 2
R>