R: Efficiently remove singleton dimensions from array - arrays

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

Related

Indexing a matrix by column/row when it might become length 1 [duplicate]

> a<-matrix(c(1:9),3,3)
> a
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> a[3,]*a[,3] # I expect 1x1 matrix as result of this.
[1] 21 48 81
> class(a)
[1] "matrix"
> class(a[3,])
[1] "integer"
In R, 1-dimensional matrix is changed to a vector. Can I avoid this?
I would like to keep 1-D matrix as a matrix. Actually, I need to throw many kind of matrix to RcppArmadillo, even zero-D matrix. Changing matrix to vector by itself is my problem.
This is an R FAQ. You need to do a[3,,drop = FALSE].
You're confusing element-by-element multiplication and matrix multiplication (see ?"*"). You want %*%:
> a[3,]%*%a[,3]
[,1]
[1,] 150

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.

Select each nth matrix from each array in a list of arrays

I have problems with selecting specific matrices in a list of arrays:
My dataset is a list. Each element of the list is an array, and each element of each array is naturally a matrix. Now what I want is to extract each nth (e.g. second) complete matrix from each element of the list, and combine them together into a new array. I have found several solutions with sapply and lapply, that work great when the elements of the list are vectors, but having arrays as list elements from which whole matrices should be extracted adds an additional level of complexity for which I cannot figure out a solution.
Here is an example:
#Create dataset
set.seed(1000)
D1<-array(runif(16), dim=c(4, 2, 2))
D2<-array(runif(16), dim=c(4, 2, 2))
D3<-array(runif(16), dim=c(4, 2, 2))
Dat<-list(D1, D2, D3)#This is how my data look like
#This works and produces exactly what I want
array(c(Dat[[1]][,,2], Dat[[2]][,,2], Dat[[3]][,,2]), dim=c(4, 2, 3))
The last line of code manually produces exactly what I want. However, in the end the lists will of variable length and the arrays will have different lengths as well (although not the arrays contained in the same list, those will always be of equal length). Therefore I will need a way to pick each nth matrix per array for all arrays in the list automatically. I tried some things, but they all did not work:
#This does not work at all
array(Dat[[]][,,2], dim=c(4, 2, 3))
array(Dat[[1:3]][,,2], dim=c(4, 2, 3))
array(Dat[[c(1, 2, 3)]][,,2], dim=c(4, 2, 3))
#This gives the the second row, first column of each matrix in the first array (i.e. first list element) only---absolutely not what I want
sapply(Dat, "[[", 2)
#Result
[1] 0.7588465 0.6351620 0.9661789
Thanks in advance if anyone could help me out with that matter.
lapply( Dat , "[" , , , 2 )
#[[1]]
# [,1] [,2]
#[1,] 0.2157714 0.31708425
#[2,] 0.2561224 0.86581282
#[3,] 0.3499375 0.76416075
#[4,] 0.7554616 0.07288487
#
#...snip...
The above gives you a list of matrices.
To get the array, as suggested by #GavinSimpson, instead do:
simplify2array(lapply( Dat , "[" , , , 2 ))
(see edits for my earlier, less elegant suggestion for this)
Another way is to redimension the returned value from an sapply call:
temp <- sapply(Dat, "[", TRUE, TRUE, 2)
dim(temp) <- c(4,2,3)
temp
#-----------
, , 1
[,1] [,2]
[1,] 0.2157714 0.31708425
[2,] 0.2561224 0.86581282
[3,] 0.3499375 0.76416075
[4,] 0.7554616 0.07288487
, , 2
[,1] [,2]
[1,] 0.5483054 0.09076793
[2,] 0.6765533 0.12221227
[3,] 0.4518961 0.56751754
[4,] 0.8241250 0.04970992
, , 3
[,1] [,2]
[1,] 0.9962082 0.7979292
[2,] 0.5310467 0.7129898
[3,] 0.1099083 0.7028350
[4,] 0.6332116 0.5628327
You may try
library(abind)
ar1 <- abind(Dat, along=3)
ar1[,,seq(2,dim(ar1)[3], by=2)]

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.

Return a n-by-1 matrix from a multi-dimensional array

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>

Resources