shift matrix elements in R - r

n <- 5
a <- matrix(c(1:n**2),nrow = n, byrow = T)
output is
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 6 7 8 9 10
[3,] 11 12 13 14 15
[4,] 16 17 18 19 20
[5,] 21 22 23 24 25
how do I shift the '1' to the current position of '25' to look like this:
[,1] [,2] [,3] [,4] [,5]
[1,] 2 3 4 5 6
[2,] 7 8 9 10 11
[3,] 12 13 14 15 16
[4,] 17 18 19 20 21
[5,] 22 23 24 25 1

a <- t(a); a[] <- c(a[-1], a[1]); a <- t(a)
a
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 3 4 5 6
# [2,] 7 8 9 10 11
# [3,] 12 13 14 15 16
# [4,] 17 18 19 20 21
# [5,] 22 23 24 25 1
c(a) unwinds or unlists the matrix into a vector. It does this column-first, so c(a) results in [1] 1 6 11 16 21 2 .... We want it to be row-first, though, so
t(a) transposes it, so that what was a row-first is now column-first, allowing c(a) and such to work.
c(a[-1], a[1]) is just "concatenate all except the first with the first", the classic way to put the first element of a vector at the end.
a[] <- is a way to do calcs on its values where the calcs do not preserve the "dimensionality" of the object.
After we've rearranged, we then transpose back to the original shape and row/column-order.

Here is a base R one-liner
> t(`dim<-`(t(a)[seq_along(a)%%length(a)+1],rev(dim(a))))
[,1] [,2] [,3] [,4] [,5]
[1,] 2 3 4 5 6
[2,] 7 8 9 10 11
[3,] 12 13 14 15 16
[4,] 17 18 19 20 21
[5,] 22 23 24 25 1

Related

Vector to list of matrices

I´m trying convert a vector to multiple matrices and save them in a list.
#Create list to save matrix
BSEPRA=vector("list", 420)
#Vector size 6720
temporalRA
I need to build 4*4 size matrices with the first 16 elements then with the next ones (17:32) and so on up to 6705:6720 to have 420 and save them in the list. But this doesn't work:
for (i in 1:length(temporalRA)){
temp2<-matrix(temporalRA[seq(1,6720, 16), ],nrow = 4,ncol = 4, )
BSEPRA[[i]]=temp2
}
vec <- 1:32
split(vec, (seq_along(vec) - 1) %/% (4*4))
# $`0`
# [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# $`1`
# [1] 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
lapply(split(vec, (seq_along(vec) - 1) %/% 16), matrix, nrow = 4, ncol = 4)
# $`0`
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
# $`1`
# [,1] [,2] [,3] [,4]
# [1,] 17 21 25 29
# [2,] 18 22 26 30
# [3,] 19 23 27 31
# [4,] 20 24 28 32
If there's any concern that you will not have a perfect multiple of 16, I encourage you to take one extra step.
The problem:
vec <- 1:30
vecs <- split(vec, (seq_along(vec) - 1) %/% (4*4))
vecs
# $`0`
# [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# $`1`
# [1] 17 18 19 20 21 22 23 24 25 26 27 28 29 30
lapply(vecs, matrix, nrow = 4)
# Warning in FUN(X[[i]], ...) :
# data length [14] is not a sub-multiple or multiple of the number of rows [4]
# $`0`
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
# $`1`
# [,1] [,2] [,3] [,4]
# [1,] 17 21 25 29
# [2,] 18 22 26 30
# [3,] 19 23 27 17
# [4,] 20 24 28 18
(Notice how 17:18 are "recycled".)
The fix:
vec <- 1:30
vecs <- split(vec, (seq_along(vec) - 1) %/% (4*4))
vecs <- lapply(vecs, `length<-`, max(lengths(vecs)))
vecs
# $`0`
# [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# $`1`
# [1] 17 18 19 20 21 22 23 24 25 26 27 28 29 30 NA NA
lapply(vecs, matrix, nrow = 4)
# $`0`
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
# $`1`
# [,1] [,2] [,3] [,4]
# [1,] 17 21 25 29
# [2,] 18 22 26 30
# [3,] 19 23 27 NA
# [4,] 20 24 28 NA
Another approach that I think will be more efficient than splitting the vector and iterating over the list to make matrices is to make an array and split it:
vec <- 1:32
mdim <- 4
mdimsq <- mdim^2
asplit(array(vec, dim = c(mdim, mdim, length(vec) / mdimsq)), 3)
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
[[2]]
[,1] [,2] [,3] [,4]
[1,] 17 21 25 29
[2,] 18 22 26 30
[3,] 19 23 27 31
[4,] 20 24 28 32
Likewise, if the vector is not a perfect multiple it can be padded with NA:
vec <- 1:30
vln <- ceiling(length(vec)/mdimsq) * mdimsq
if (length(vec) < vln) vec[vln] <- NA
asplit(array(vec, dim = c(mdim, mdim, length(vec) / mdimsq)), 3)
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
[[2]]
[,1] [,2] [,3] [,4]
[1,] 17 21 25 29
[2,] 18 22 26 30
[3,] 19 23 27 NA
[4,] 20 24 28 NA

creating a matrix with a nested for loop

This is a practice question to prep for an exam. I'm given the following code:
W=matrix(1:16,byrow=T,ncol=4)
print(W)
fmat=function(W){
n=nrow(W)
for (i in 1:n){
for (j in 1:n){
W[j,i]=W[i,j]+W[j,i]
}
}
return(W)
}
print(fmat(W))
We have to "run" the code on paper and then check our answers by running the code in R. I wrote out the correct matrix for W but I got fmat(W) wrong. R gives me the following output for fmat(W):
[,1] [,2] [,3] [,4]
[1,] 2 9 15 21
[2,] 7 12 24 30
[3,] 12 17 22 39
[4,] 17 22 27 32
where I had written down that fmat(W) would equal:
[,1] [,2] [,3] [,4]
[1,] 2 7 12 17
[2,] 7 12 17 22
[3,] 12 17 22 27
[4,] 17 22 27 32
What exactly is going on here? I had interpreted the function to calculate that, for example, w[2,1]=w[1,2]+w[2,1], which is 2+5=7.
In you code, W is overwritten in your nested for loop by columns and then by rows.
To visualize the progress, you can add print(W) before your value assignment W[j,i] = W[i,j]+W[j,i], i.e.,
fmat=function(W){
n=nrow(W)
for (i in 1:n){
for (j in 1:n){
print(W)
W[j,i]=W[i,j]+W[j,i]
}
}
return(W)
}
such that
> fmat(W)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 2 3 4
[2,] 7 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 2 3 4
[2,] 7 6 7 8
[3,] 12 10 11 12
[4,] 13 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 2 3 4
[2,] 7 6 7 8
[3,] 12 10 11 12
[4,] 17 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 3 4
[2,] 7 6 7 8
[3,] 12 10 11 12
[4,] 17 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 3 4
[2,] 7 12 7 8
[3,] 12 10 11 12
[4,] 17 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 3 4
[2,] 7 12 7 8
[3,] 12 17 11 12
[4,] 17 14 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 3 4
[2,] 7 12 7 8
[3,] 12 17 11 12
[4,] 17 22 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 4
[2,] 7 12 7 8
[3,] 12 17 11 12
[4,] 17 22 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 4
[2,] 7 12 24 8
[3,] 12 17 11 12
[4,] 17 22 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 4
[2,] 7 12 24 8
[3,] 12 17 22 12
[4,] 17 22 15 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 4
[2,] 7 12 24 8
[3,] 12 17 22 12
[4,] 17 22 27 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 21
[2,] 7 12 24 8
[3,] 12 17 22 12
[4,] 17 22 27 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 21
[2,] 7 12 24 30
[3,] 12 17 22 12
[4,] 17 22 27 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 21
[2,] 7 12 24 30
[3,] 12 17 22 39
[4,] 17 22 27 16
[,1] [,2] [,3] [,4]
[1,] 2 9 15 21
[2,] 7 12 24 30
[3,] 12 17 22 39
[4,] 17 22 27 32

array_reshape() not reshaping arrays as desired

I have "old_array", I want to reshape it to become "new_array" using array_reshape()
old_array <- array(seq(1,30,1),c(2,3,5))
new_array <- t(array(seq(1,30,1),c(6,5)))
The old_array is:
, , 1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
, , 2
[,1] [,2] [,3]
[1,] 7 9 11
[2,] 8 10 12
, , 3
[,1] [,2] [,3]
[1,] 13 15 17
[2,] 14 16 18
, , 4
[,1] [,2] [,3]
[1,] 19 21 23
[2,] 20 22 24
, , 5
[,1] [,2] [,3]
[1,] 25 27 29
[2,] 26 28 30
The new_array is:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 7 8 9 10 11 12
[3,] 13 14 15 16 17 18
[4,] 19 20 21 22 23 24
[5,] 25 26 27 28 29 30
I tried the following code, however the reshaped array is not the way I want:
array_reshape(old_array,c(6,5))
Expected results:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 7 8 9 10 11 12
[3,] 13 14 15 16 17 18
[4,] 19 20 21 22 23 24
[5,] 25 26 27 28 29 30
Actual results:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 7 13 19 25
[2,] 3 9 15 21 27
[3,] 5 11 17 23 29
[4,] 2 8 14 20 26
[5,] 4 10 16 22 28
[6,] 6 12 18 24 30
You can call matrix and specify the dimensions you desire. Given how R fills matrices, you need to specify byrow = TRUE in this scenario:
old_array <- array(seq(1,30,1),c(2,3,5))
matrix(old_array, nrow = dim(old_array)[3], ncol = prod(dim(old_array)[1:2]), byrow = TRUE)
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] 1 2 3 4 5 6
#> [2,] 7 8 9 10 11 12
#> [3,] 13 14 15 16 17 18
#> [4,] 19 20 21 22 23 24
#> [5,] 25 26 27 28 29 30
Created on 2019-03-31 by the reprex package (v0.2.1)
First, you want a 5x6 matrix. Your current code is asking for a return of 6x5 so you would want to write
array_reshape(old_array, c(5,6))
However, your old_array is returning 5 different matrices all 2x3. Since you are filling it in by row, it looks like array_reshape will take the first value from each row of each separate matrix and then since you are telling it to have 6 columns it then grabs the second value of the first matrix to fill out the first row of the 5x6. It then repeats this pattern to fill in the other 4 rows. This will return:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 7 13 19 25 3
[2,] 9 15 21 27 5 11
[3,] 17 23 29 2 8 14
[4,] 20 26 4 10 16 22
[5,] 28 6 12 18 24 30
Can you remove c(2,3,5) from your old_array line? It will work fine then. Otherwise array_reshape is not the appropriate function in this case. But, if you really want to use it, you can tell it to fill a 6x5 matrix by column and then transpose the matrix. This will give you the result you want:
t(array_reshape(old_array, c(6,5), "F"))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 7 8 9 10 11 12
[3,] 13 14 15 16 17 18
[4,] 19 20 21 22 23 24
[5,] 25 26 27 28 29 30

Creating larger matrix from original matrix with overlap columns in R

Imagine we have one matrix of 5*5 (25 elements)
m<-matrix(1:25,5,5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
I want to produce large matrix with different dimensions from the matrix “m”
For example 5*8, now my second column of new matrix must have overlap with the first one and so on.
So bigger dimension (e.g 5*8) matrix would be like : (it is just example and not sure the amount of shift is correct)
[,1] [,2] [,3] [,4] ……………………[,8]
[1,] 1 4 7 10 …………………… 19
[2,] 2 5 8 11 …………………… 20
[3,] 3 6 9 12 …………………… 21
[4,] 4 7 10 13 …………………… 22
[5,] 5 8 11 14 …………………… 23
In fact in each column we have a shift back to some elements of last column in order to prevent from reaching the last element of original matrix and producing NA value.
Please anyone knows how to create such a larger matrix?
The hardest part for me is to calculate the amount of SHIFT value regarding to the size of larger matrix. The larger matrix must cover almost all elements of the original one. (it is ok to miss some last elements)
thanks
I'm not sure what you want, but this might be helpful.
rows <- 5
cols <- 8
overlap <- 1
matrix(rep(seq(1,cols)*(rows-overlap),each=rows)+seq(1,rows)-(rows-overlap),nrow=rows)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 5 9 13 17 21 25 29
[2,] 2 6 10 14 18 22 26 30
[3,] 3 7 11 15 19 23 27 31
[4,] 4 8 12 16 20 24 28 32
[5,] 5 9 13 17 21 25 29 33
overlap <- 2
matrix(rep(seq(1,cols)*(rows-overlap),each=rows)+seq(1,rows)-(rows-overlap),nrow=rows)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 4 7 10 13 16 19 22
[2,] 2 5 8 11 14 17 20 23
[3,] 3 6 9 12 15 18 21 24
[4,] 4 7 10 13 16 19 22 25
[5,] 5 8 11 14 17 20 23 26
overlap <- 3
matrix(rep(seq(1,cols)*(rows-overlap),each=rows)+seq(1,rows)-(rows-overlap),nrow=rows)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 3 5 7 9 11 13 15
[2,] 2 4 6 8 10 12 14 16
[3,] 3 5 7 9 11 13 15 17
[4,] 4 6 8 10 12 14 16 18
[5,] 5 7 9 11 13 15 17 19
the maximum efficiency of coverage is: (the best value of overlap)
> overlap<-ceiling(rows*(1-length(dna1)/(cols*rows)))+round(rows/cols)

Replicate rows of a matrix in R

Suppose I have a matrix m and a positive integer vector v, what I want to do is get a new matrix m_new and each row of m (say m[i, ]) are replicated by v[i] times in m_new. For example:
m = matrix(1:6, nrow = 3)
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
v = c(3, 1, 2)
And m_new should be:
[,1] [,2]
[1,] 1 4 # m[1, ] is replicated by
[2,] 1 4 # v[1] = 3
[3,] 1 4 # times
[4,] 2 5
[5,] 3 6
[6,] 3 6
A for loop will make it for the small case:
m_new = matrix(0, sum(v), ncol(m))
k = 1
for(i in 1:nrow(m)){
for(j in k:(k+v[i]-1)){
m_new[j, ] = m[i, ]
}
k = k + v[i]
}
, but the row number of m in real world is usually big. Is there any effient way to do this?
m[rep(1:nrow(m), times = v), ]
# [,1] [,2]
# [1,] 1 4
# [2,] 1 4
# [3,] 1 4
# [4,] 2 5
# [5,] 3 6
# [6,] 3 6
> m <- matrix(1:25, ncol=5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
> apply(m, 2, function(c) rep(c,v))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 2 7 12 17 22
[4,] 3 8 13 18 23
[5,] 3 8 13 18 23
[6,] 3 8 13 18 23
[7,] 4 9 14 19 24
[8,] 4 9 14 19 24
[9,] 4 9 14 19 24
[10,] 4 9 14 19 24
[11,] 5 10 15 20 25
[12,] 5 10 15 20 25
[13,] 5 10 15 20 25
[14,] 5 10 15 20 25
[15,] 5 10 15 20 25

Resources