How do I understand this index matrix in R - r

Here I have a
x <- array(1:20, dim=c(4,5))
x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
I also have a index array
i <- array(c(1:3,3:1), dim=c(3,2))
[,1] [,2]
[1,] 1 3
[2,] 2 2
[3,] 3 1
Then
x[i]
will extract X[1,3], X[2,2] and X[3,1]
However, what if I have
i <- array(c(1:3,3:1), dim=c(2,3))
The output is
x[i]
[1] 1 2 3 3 2 1
How can I understand this result?

Related

Sum of a list of matrices in R

I am trying to put a list of matrices together in a list and then do summation inside of each list. Below are the simple example of the codes:
Let's say if I have 4 matrices:
x1 <- matrix(1:9, nrow = 3)
x2 <- matrix(2:10, nrow = 3)
x3 <- matrix(3:11, nrow = 3)
x4 <- matrix(4:12, nrow = 3)
And I want to put them into a list() in a way like this:
[[1]]
[[1]][[1]]
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
[[1]][[2]]
[,1] [,2] [,3]
[1,] 2 5 8
[2,] 3 6 9
[3,] 4 7 10
[[2]]
[,1] [,2] [,3]
[1,] 3 6 9
[2,] 4 7 10
[3,] 5 8 11
[[3]]
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 5 8 11
[3,] 6 9 12
And how do I perform summation of each element inside the list()?
For example, my desired output is as below:
[[1]]
[,1] [,2] [,3]
[1,] 3 9 15
[2,] 5 11 17
[3,] 7 13 19
[[2]]
[,1] [,2] [,3]
[1,] 3 6 9
[2,] 4 7 10
[3,] 5 8 11
[[3]]
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 5 8 11
[3,] 6 9 12
I have tried using list(Reduce(`+`, x)) however it does not work.
Since you want to keep top-level list use lapply :
lapply(x, function(l) if(is.list(l)) Reduce(`+`, l) else l)
#[[1]]
# [,1] [,2] [,3]
#[1,] 3 9 15
#[2,] 5 11 17
#[3,] 7 13 19
#[[2]]
# [,1] [,2] [,3]
#[1,] 3 6 9
#[2,] 4 7 10
#[3,] 5 8 11
#[[3]]
# [,1] [,2] [,3]
#[1,] 4 7 10
#[2,] 5 8 11
#[3,] 6 9 12
A corresponding purrr version of #RonakShah's answer with map_if():
library(purrr)
map_if(x, is.list, reduce, `+`)
# [[1]]
# [,1] [,2] [,3]
# [1,] 3 9 15
# [2,] 5 11 17
# [3,] 7 13 19
#
# [[2]]
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 4 7 10
# [3,] 5 8 11
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 4 7 10
# [2,] 5 8 11
# [3,] 6 9 12

R accessing a matrix to an array 3d

I would like to access an array 3d with a matrix. Here an example of the desired output:
a <- array(1:18, dim=c(3,3,2))
a
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
b <- array(1:2, dim=c(3,3))
b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
a[b]
[,1] [,2] [,3]
[1,] 1 13 7
[2,] 11 5 17
[3,] 3 15 9
(Should i pass a data frame with 3 columns (indexs + values) instead of a matrix?)
if i do a[b], this is the result:
a[b]
4 11 4
and why?
c <- array(1:2, dim=c(2,2))
a[c]
[1] 1 2 1 2
for b <- array(1:2, dim=c(3,3))
> b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
the indices are read by rows. Thus, as #jogo mentioned, a[b] is actually c(a[1, 2, 1], a[2, 1, 2], a[1, 2, 1])
for C <- array(1:2, dim=c(2,2))
> C
[,1] [,2]
[1,] 1 1
[2,] 2 2
since the dimension of C does not match a (only two out of three fit), in this case a[C] is interpreted as a[c(C)] (thanks to comments from #jogo).

How to replace even or odd colums in a matrix?

For, example I if a had matrix like this:
realmatrix=matrix(1:16,ncol=4,nrow=4)
Which would give this:
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
And I would like to make a function that would replace the two columns with a certain value ( for example 1:4) if it has a even number of colums, then the result should be something like this:
[,1] [,2] [,3] [,4]
[1,] 1 1 1 13
[2,] 2 2 2 14
[3,] 3 3 3 15
[4,] 4 4 4 16
And if the matrix has odd numbers of colums, the function should replace only the odd column, that is to say the central one:
This is the matrix with odd numbers of columns:
realmatrix2=matrix(1:12,ncol=3,nrow=4)
The final result:
[,1] [,2] [,3]
[1,] 1 1 9
[2,] 2 2 10
[3,] 3 3 11
[4,] 4 4 12
Thanks a lot!
Try:
fun2 <- function(mat, val){
stopifnot(length(val)==nrow(mat))
n <- ncol(mat)
if( (n/2) %%2 ==0){
mat[, c(n/2, n/2+1)] <- val
}
else {
mat[, ceiling(n/2)] <- val
}
mat
}
fun2(realmatrix, 1:4)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 13
#[2,] 2 2 2 14
#[3,] 3 3 3 15
#[4,] 4 4 4 16
fun2(realmatrix2,1:4)
# [,1] [,2] [,3]
#[1,] 1 1 9
#[2,] 2 2 10
#[3,] 3 3 11
#[4,] 4 4 12
realmatrix5=matrix(1:32, ncol=8,nrow=4)
fun2(realmatrix5, 1:4)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 5 9 1 1 21 25 29
#[2,] 2 6 10 2 2 22 26 30
#[3,] 3 7 11 3 3 23 27 31
#[4,] 4 8 12 4 4 24 28 32
Update
If you want to change the rows:
funR <- function(mat, val){
stopifnot(length(val)==ncol(mat))
n <- nrow(mat)
if((n/2) %%2==0){
mat[c(n/2, n/2+1),] <- rep(val, each=2)
}
else {
mat[ceiling(n/2),] <- val
}
mat
}
funR(realmatrix, 1:4)
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 1 2 3 4
#[3,] 1 2 3 4
#[4,] 4 8 12 16
realmatrix3 <- matrix(1:15, ncol=5)
funR(realmatrix3, 1:5)
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 4 7 10 13
#[2,] 1 2 3 4 5
#[3,] 3 6 9 12 15

Duplicate matrix columns and put next to original in R

If I have a matrix say:
> mat1=matrix(1:12, ncol=3)
> mat1
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
What do I do to replicate each column and put it next to the original so it looks like this:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 5 5 9 9
[2,] 2 2 6 6 10 10
[3,] 3 3 7 7 11 11
[4,] 4 4 8 8 12 12
I'm sure this is really simple but can't see it! Many thanks.
Try this:
mat1=matrix(1:12, ncol=3)
mat1[,rep(1:ncol(mat1),each=2)]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 1 5 5 9 9
## [2,] 2 2 6 6 10 10
## [3,] 3 3 7 7 11 11
## [4,] 4 4 8 8 12 12
Probably easiest to re-order a simple cbind:
cbind(mat, mat)[,order(rep(1:ncol(mat), times=2))]
or
mat[,rep(1:ncol(mat), each=2)]

Transforming a table in a 3D array in R

I have a matrix:
R> pippo.m
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[5,] 17 18 19 20
[6,] 21 22 23 24
and I would like to transform this matrix in a 3D array with dim=(2,4,3). Passing through the transponse of pippo.m I am able to obtain a similar result but with columns and rows rotated.
> pippo.t <- t(pippo.m)
> pippo.vec <- as.vector(pippo.t)
> pippo.arr <- array(pippo.vec,dim=c(4,2,3),dimnames=NULL)
> pippo.arr
, , 1
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
, , 2
[,1] [,2]
[1,] 9 13
[2,] 10 14
[3,] 11 15
[4,] 12 16
, , 3
[,1] [,2]
[1,] 17 21
[2,] 18 22
[3,] 19 23
[4,] 20 24
Actually, I would prefer to mantain the same distribution of the original data, as rows and colums represent longitude and latitude and the third dimension is time. So I would like to obtain something like this:
pippo.a
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
, , 2
[,1] [,2] [,3] [,4]
[1,] 9 10 11 12
[2,] 13 14 15 16
, , 3
[,1] [,2] [,3] [,4]
[1,] 17 18 19 20
[2,] 21 22 23 24
How can I do?
Behold the magic of aperm!
m <- matrix(1:24,6,4,byrow = TRUE)
> aperm(array(t(m),c(4,2,3)),c(2,1,3))
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
, , 2
[,1] [,2] [,3] [,4]
[1,] 9 10 11 12
[2,] 13 14 15 16
, , 3
[,1] [,2] [,3] [,4]
[1,] 17 18 19 20
[2,] 21 22 23 24

Resources