creating a matrix with a nested for loop - r

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

Related

shift matrix elements in 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

How to multiply a matrix by a known vector to return an array

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

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)

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