Element-wise multiplication between array and matrix - arrays

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].

Related

Is there a dimension function that works for vectors, matrices and arrays in R

As we all know the function dim calculates the dimension of a multidemnsional array or matrix.
n = 2
A = matrix(rnorm(n^2),n,n)
dim(A)
Which yields the answer 2,2 as expected. Now the issue is often you don't know if an object will be a vector or a matrix or an array. dim only works on the latter two types. Of course one could write a function as follows
dimVorM = function(x) ifelse( is.vector(x), return(c(1,length(x))), dim(x) )
But is there a better way?
You could write something like this, which would be analogous to NROW and NCOL.
DIM <- function(x) if(is.null(dim(x))) length(x) else dim(x)
I wouldn't return a length-2 vector if something only has one dimension. And don't use ifelse for control flow.
Technically, dim() works for vectors. The function dim() extracts a "dim" attribute and returns its values. A vector doesn't have that attribute dim, so the function dim() rightfully returns NULL.
> x <- 1:10
> attr(x, "dim") <- c(2,5)
> x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
> dim(x)
[1] 2 5
> attributes(x)
$dim
[1] 2 5
> dim(x) <- NULL
> x
[1] 1 2 3 4 5 6 7 8 9 10
> dim(x)
NULL
The dim attribute is a vector with one value for each dimension, indicating the number of elements in that dimension. Both NROW and NCOL are constructed in such a way that they consider a vector to be a column vector with 1 column and n rows, and the solution of Hong Ooi is consistent with this.
Also keep in mind that a table is something entirely different. That is not a vector but a one-dimensional array :
> y <- table(iris$Species)
> y
setosa versicolor virginica
50 50 50
> dim(y)
[1] 3
> class(y)
[1] "table"

Subsetting multi-dim. array with matrices

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.

matrix addition from an array r

I have an array with 272 matrices, each one is 2 by 2. I now want to sum these matrices up using matrix addition. So I want the return to be a single 2 by 2 matrix. Here are some code I have used.
y <- as.matrix(faithful)
B <- matrix(c(0,0,0,0),nrow = 2)
sigma <- function(n = 272,u_new) {
vec = replicate(272,B)
for (i in 1:n) {
w <- (y-u_new)[i,]
x <- ptilde1[i]*(w%*%t(w))
vec[,,i][1,1] <- x[1,1]
vec[,,i][1,2] <- x[1,2]
vec[,,i][2,1] <- x[2,1]
vec[,,i][2,2] <- x[2,2]}
vec
}
Here vec is the array with 272 matrices. Thank you in advance.
Here is code which loops a number of times (272) and adds a matrix to the same list.
B <- matrix(c(0,0,0,0),nrow = 2)
list <- list(B)
for (i in 2:272) {
list[[i]] <- B
}
To add them all together, you can use the Reduce() function:
sum <- Reduce('+', list)
> sum
[,1] [,2]
[1,] 0 0
[2,] 0 0
This is a contrived example because all the matrices are the zero matrix. I will leave it to you as a homework assignment to use the matrices you actually want to sum together.

Matrix of vectors in R

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.

R: Fill a matrix with a covariance function

I'm experimenting with spectral simulation for generating unconditional Gaussian realizations of a spatial variable. The variable has a covariance function c(h) = exp(-h/a), where a is the range of the covariance function and h is distance. In the first step, I need to discretize the covariance function into an array/matrix. The entries in the matrix correspond to physical locations in space (i.e. the matrix indices correspond to x and y coordinates):
cov(i,j) = exp(-sqrt((i-64)^2 + (j-64)^2) / 20) for i,j = 1 to 128
I am looking to generate a matrix in R and fill it with the covariance function related to the indices of the array. As a total beginner with R, I'm a bit lost.
stuff that expression into a function:
myfun <- function(i, j) {
exp(-sqrt((i-64)^2 + (j-64)^2) / 20)
}
Then make your "matrix" of possible i, j combinations:
n <- 128
combos <- expand.grid(i=1:n, j=1:n)
Then call your function with those two vectors:
matrix(myfun(combos$i, combos$j), nrow=n)
Using a smaller number:
> n <- 5
> combos <- expand.grid(i=1:n, j=1:n)
> matrix(myfun(combos$i, combos$j), nrow=n)
[,1] [,2] [,3] [,4] [,5]
[1,] 0.01162296 0.01203954 0.01246747 0.01290681 0.01335761
[2,] 0.01203954 0.01247458 0.01292166 0.01338085 0.01385221
[3,] 0.01246747 0.01292166 0.01338860 0.01386840 0.01436113
[4,] 0.01290681 0.01338085 0.01386840 0.01436960 0.01488451
[5,] 0.01335761 0.01385221 0.01436113 0.01488451 0.01542247
>
You could also use outer:
f <- function(i, j) {
exp(-sqrt((i-64)^2 + (j-64)^2) / 20)
}
n <- 5
outer(1:n, 1:n, f)

Resources