I want you to help me about R code.
I have an object, M(list & array). Like this.
object1 <- array(0, c(2,2,2))
M <- list(object1, object1)
Then, I want to reshape m(vector) into M structure.
m <- c(1:16)
When M is list & matrix object, I can use 'relist' function. However, I can't use it to array object. How can I reshape m into M structure??
We can specify the dims in array and use relist
lapply(relist(m, skeleton = M), array, dim(object1))
#[[1]]
#, , 1
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#, , 2
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8
#[[2]]
#, , 1
# [,1] [,2]
#[1,] 9 11
#[2,] 10 12
#, , 2
# [,1] [,2]
#[1,] 13 15
#[2,] 14 16
Or another option is
lapply(setNames(split(m, (seq_along(m)-1) %/% lengths(M)[1]), NULL), array, dim(object1))
#[[1]]
#, , 1
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#, , 2
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8
#[[2]]
#, , 1
# [,1] [,2]
#[1,] 9 11
#[2,] 10 12
#, , 2
# [,1] [,2]
#[1,] 13 15
#[2,] 14 16
NOTE: Both the solutions are one-line solutions
Related
I have a question about adding up the column of the matrix
for example:
I have a matrix
[,1] [,2] [,3]
[1,] 1 3 1
[2,] 2 4 2
I want it to be
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 6 8
We can apply cumsum on each row by looping over the rows with apply and MARGIN specified as 1 and transpose the output
t(apply(m1, 1, cumsum))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
Or with a for loop
for(i in seq_len(ncol(m1))[-1]) m1[,i] <- m1[, i] + m1[, i-1]
Or another option is to split it a list of vectors with asplit and then Reduce with + and accumulate = TRUE
do.call(cbind, Reduce(`+`, asplit(m1, 2), accumulate = TRUE))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
or with a convenient function rowCumsums from matrixStats
library(matrixStats)
rowCumsums(m1)
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
data
m1 <- cbind(1:2, 3:4, 1:2)
I have a question about adding up the column of the matrix
for example:
I have a matrix
[,1] [,2] [,3]
[1,] 1 3 1
[2,] 2 4 2
I want it to be
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 6 8
We can apply cumsum on each row by looping over the rows with apply and MARGIN specified as 1 and transpose the output
t(apply(m1, 1, cumsum))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
Or with a for loop
for(i in seq_len(ncol(m1))[-1]) m1[,i] <- m1[, i] + m1[, i-1]
Or another option is to split it a list of vectors with asplit and then Reduce with + and accumulate = TRUE
do.call(cbind, Reduce(`+`, asplit(m1, 2), accumulate = TRUE))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
or with a convenient function rowCumsums from matrixStats
library(matrixStats)
rowCumsums(m1)
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
data
m1 <- cbind(1:2, 3:4, 1:2)
Is there a more succinct, one-liner way to do the following?
x <- array(1:12, dim = c(3, 2, 2))
> x[1,,]
[,1] [,2]
[1,] 1 7
[2,] 4 10
> x[2,,]
[,1] [,2]
[1,] 2 8
[2,] 5 11
> x[3,,]
[,1] [,2]
[1,] 3 9
[2,] 6 12
# Reduce 3d array to 2d (Is there a more elegant way?)
y <- x
dim(y) <- c(nrow(y), 4)
> y
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
You can just feed your original array to the array constructor again, and use dim to get the dimension you want to preserve:
y <- array(x, dim = c(dim(x)[1], 4))
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
If you wanted a version that doesn't rely on hardcoding the number of columns:
y <- array(x, dim = c(dim(x)[1], dim(x)[2] * dim(x)[3]))
This should be easy but I can't think of a more elegant way to create an addition table, such as:
x <- 1:3
cbind(x + x[1], x + x[2], x + x[3])
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 3 4 5
[3,] 4 5 6
I tried various versions of lapply() to no avail.
You can either use outer or sapply or expand.grid (in combination with rowSums)
x = 1:3
outer(x, x, "+")
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
sapply(seq_along(x), function(i) sapply(seq_along(x), function(j) x[i]+x[j]))
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
matrix(rowSums(expand.grid(x, x)), ncol = length(x))
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
You could do this:
m <- diag(length(x))
m[] <- x[col(m)] + x[row(m)]
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
OR
matrix(x,length(x),length(x),byrow = TRUE) + x
I wanna build an nxm matrix, n< m, and i want each element Mij = i^j
Any ideas? I tried multiplying various vectors etc but i never get the correct result.
n <- 3
m <- 4
outer(seq_len(n), seq_len(m), "^")
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
You can also use sapply:
t(sapply(1:n, `^`, 1:m))
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
Or even faster:
matrix(1:n, ncol=m, nrow=n)^matrix(1:m, ncol=m, nrow=n, byrow=T)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81