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
Related
I have a list of matrices where most of the matrices are column matrices but some of them are row matrices. How to convert only those row matrices to column matrices? I would like to achieve this using base R.
Here is the list of matrices where the third one is a row matrix
x <- list(`1` = matrix(1:20, nrow=5), `2` = matrix(1:20, nrow=10), `3` = matrix(1:5, nrow=1))
How to convert the list to one like this:
$`1`
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
$`2`
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
$`3`
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
I have a much larger dataset and so efficient code is preferred!
Check the dimensions of the matrix and transpose it if the row dimension is 1:
(y <- lapply(x, function(x) if(dim(x)[1] == 1) { t(x)} else x))
# $`1`
# [,1] [,2] [,3] [,4]
# [1,] 1 6 11 16
# [2,] 2 7 12 17
# [3,] 3 8 13 18
# [4,] 4 9 14 19
# [5,] 5 10 15 20
#
# $`2`
# [,1] [,2]
# [1,] 1 11
# [2,] 2 12
# [3,] 3 13
# [4,] 4 14
# [5,] 5 15
# [6,] 6 16
# [7,] 7 17
# [8,] 8 18
# [9,] 9 19
# [10,] 10 20
#
# $`3`
# [,1]
# [1,] 1
# [2,] 2
# [3,] 3
# [4,] 4
# [5,] 5
Good afternoon!
Assume we have a vector and a matrix :
v = c(2,3,4)
[1] 2 3 4
m=matrix(1:9,ncol=3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
I'm searching an efficient way ( or built-in function ) to get three matrices m1 , m2 , m3 such that :
m1=v[1]*m
m2=v[2]*m
m3=v[3]*m
We could obtain this using a 3d-array :
my_fct<-function(m,v){
f=array(data=rep(NA,nrow(m)*ncol(m)*length(v)),dim = c(nrow(m),ncol(m),length(v)))
for (j in c(1:length(v))){
f[,,j]=v[j]*m
}
return(f)
}
my_fct(m,v)
, , 1
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
, , 2
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
, , 3
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36
I hope my request is clear!
Thank you a lot for help !
As 'v' is a vector and we want each element to be multiplied by the same matrix 'm', an option is to loop over the element of 'v' and do the multiplication
lapply(v, `*`, m)
-output
[[1]]
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
[[2]]
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
[[3]]
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36
Another base R option
> Map(`*`, list(m), v)
[[1]]
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
[[2]]
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
[[3]]
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36
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?
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
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)]