I have an array of strings which are actually names of datasets. I perform several measures on each dataset and get result of each measure in a matrix.
I want to save the results of one dataset in some data structure.
So, for example:
We have a string "glass".
From measurements on dataset "glass" I get 3 matrices a,b,c.
How could I save a,b,c in one structure?
Thanks.
Use a list.
> mydata <- list()
> mydata[[1]] <- matrix(1:4, 2, 2)
> mydata[[2]] <- matrix(1:10, 5, 2)
> mydata[[3]] <- matrix(1:16, 4, 4)
> mydata
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
[[3]]
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
>
> # To access the first matrix in the list...
> mydata[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
See ?list for more information.
Since they are the same size you can choose either list or a array. Dason showed the list option.
a=matrix(rnorm(16),nrow=4)
b=matrix(rnorm(16),nrow=4)
d=matrix(rnorm(16),nrow=4)
glass=array(c(a,b,d),dim=c(4,4,3))
Related
I would like to row-bind specific rows that are rows in matrices in a list. For instance, I might have a list that has three matrices in them like:
> t
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 5 7
[2,] 6 8
[[3]]
[,1] [,2]
[1,] 9 11
[2,] 10 12
Then what I'd like to do is calculate the distances between the rows of these matrices, so if I could just write out
dist(rbind(t[[1]][1,], t[[2]][1,], t[[3]][1,]))
dist(rbind(t[[1]][2,], t[[2]][2,], t[[3]][2,]))
But in my case I could have much larger matrices and larger lists, so I was wondering if there is a way to row bind the corresponding rows of the matrices in the list in a quicker way?
Many thanks for any help!
Sure, if l is your list, we may use, e.g., sapply in the following way:
t(sapply(l, `[`, 1,))
# [,1] [,2]
# [1,] 1 3
# [2,] 5 7
# [3,] 9 11
which is short for
t(sapply(l, `[`, i = 1, j =))
or
t(sapply(l, function(ll) ll[1, ]))
I'm trying to understand more about matrices in R and I stumbled upon this query. Could someone explain to me why x[2:3, 2:2] returns 5 and 6?
Am I right to say that, 2:3, 2:2, simply refers to row 2, column 2 and row 3 column 2?
> x <- matrix(c(1:6), ncol = 2)
> x
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
>
>
> x[2:3, 2:2]
[1] 5 6
If that's the case, why is it that having a 3x3 matrix returns such a strange value?
> x <- matrix(c(1:9), ncol = 3)
> x
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> x[1:2, 3:2, drop = F]
[,1] [,2]
[1,] 7 4
[2,] 8 5
Consider the following 3-dimensional array:
set.seed(123)
arr = array(sample(c(1:10)), dim=c(3,4,2))
which yields
> arr
, , 1
[,1] [,2] [,3] [,4]
[1,] 10 9 8 2
[2,] 5 1 4 10
[3,] 6 7 3 5
, , 2
[,1] [,2] [,3] [,4]
[1,] 6 7 3 5
[2,] 9 8 2 6
[3,] 1 4 10 9
I'd like to subset it like
arr[c(1,2), c(2,4), c(1)]
but the catch is that I don't know (a) which indices or (b) which dimension the indices are.
What is the best way to access an N-dimensional array with index variables?
ll = list(c(1,2), c(2,4), c(1))
arr[ll] # doesn't work
arr[grid.expand(ll)] # doesn't work
# ..what else?
use do.call, such as:
do.call(`[`, c(list(arr), ll))
or more cleanly, using a wrapper function:
getArr <- function(...)
`[`(arr, ...)
do.call(getArr, ll)
[,1] [,2]
[1,] 10 5
[2,] 7 3
There is the asub function from the abind package:
library(abind)
asub(arr, ll)
which can also do a lot more, in particular extract along a subset of the dimensions (https://stackoverflow.com/a/17752012/1201032). Worth having in your toolbox.
After a clever lapply, I'm left with a list of 2-dimensional matrices.
For example:
set.seed(1)
test <- replicate( 5, matrix(runif(25),ncol=5), simplify=FALSE )
> test
[[1]]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.8357088 0.29589546 0.9994045 0.2862853 0.6973738
[2,] 0.2377494 0.14704832 0.0348748 0.7377974 0.6414624
[3,] 0.3539861 0.70399206 0.3383913 0.8340543 0.6439229
[4,] 0.8568854 0.10380669 0.9150638 0.3142708 0.9778534
[5,] 0.8537634 0.03372777 0.6172353 0.4925665 0.4147353
[[2]]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.1194048 0.9833502 0.9674695 0.6687715 0.1928159
[2,] 0.5260297 0.3883191 0.5150718 0.4189159 0.8967387
[3,] 0.2250734 0.2292448 0.1630703 0.3233450 0.3081196
[4,] 0.4864118 0.6232975 0.6219023 0.8352553 0.3633005
[5,] 0.3702148 0.1365402 0.9859542 0.1438170 0.7839465
[[3]]
...
I'd like to turn that into a 3-dimensional array:
set.seed(1)
replicate( 5, matrix(runif(25),ncol=5) )
Obviously, if I'm using replicate I can just turn on simplify, but sapply does not simplify the result properly, and stack fails utterly. do.call(rbind,mylist) turns it into a 2d matrix rather than 3d array.
I can do this with a loop, but I'm looking for a neat and functional way to handle it.
The closest way I've come up with is:
array( do.call( c, test ), dim=c(dim(test[[1]]),length(test)) )
But I feel like that's inelegant (because it disassembles and then reassembles the array attributes of the vectors, and needs a lot of testing to make safe (e.g. that the dimensions of each element are the same).
Try this:
simplify2array(test)
You can use the abind package and then use abind(test, along = 3)
library(abind)
testArray <- abind(test, along = 3)
Or you could use simplify = 'array' in a call to sapply, (instead of lapply). simplify = 'array' is not the same as simplify = TRUE, as it will change the argument higher in simplify2array
eg
foo <- function(x) matrix(1:10, ncol = 5)
# the default is simplify = TRUE
sapply(1:5, foo)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 2 2 2 2
[3,] 3 3 3 3 3
[4,] 4 4 4 4 4
[5,] 5 5 5 5 5
[6,] 6 6 6 6 6
[7,] 7 7 7 7 7
[8,] 8 8 8 8 8
[9,] 9 9 9 9 9
[10,] 10 10 10 10 10
# which is *not* what you want
# so set `simplify = 'array'
sapply(1:5, foo, simplify = 'array')
, , 1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 2
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 3
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 4
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 5
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
An array is simply an atomic vector with dimensions. Each of the matrix components of test is really just a vector with dimensions too. Hence the simplest solution I can think of is to unroll the list test into a vector and convert that to an array using array and suitably supplied dimensions.
set.seed(1)
foo <- replicate( 5, matrix(runif(25),ncol=5) )
tmp <- array(unlist(test), dim = c(5,5,5))
> all.equal(foo, tmp)
[1] TRUE
> is.array(tmp)
[1] TRUE
> dim(tmp)
[1] 5 5 5
If you don't want to hardcode the dimensions, we have to make some assumptions but can easily fill in the dimension from test, e.g.
tmp2 <- array(unlist(test), dim = c(dim(test[[1]]), length(test)))
> all.equal(foo, tmp2)
[1] TRUE
This assumes that the dimensions of each component are all the same, but then I don't see how you could put sub-matrices into a 3-d array if that condition doesn't hold.
This may seem hacky, to unroll the list, but this is simply exploiting how R handles matrices and arrays as vectors with dimensions.
test2 <- unlist(test)
dim(test2) <- c(dim(test[[1]]),5)
or if you do not know the expected size ahead of time:
dim3 <- c(dim(test[[1]]), length(test2)/prod(dim(test[[1]])))
dim(test2) <- dim3
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