how unroll a matrix in R - r

For example, I have a matrix:
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
I want it to become
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 2 3 4 5 6 7 8
[2,] 9 10 11 12 13 14 15 16
Thanks.

Let me expand on Zheyuan Li's answer, since these things can be a bit mysterious for the uninitiated. Basically, the same matrix function used to create a matrix from a vector, can also be used to reshape a matrix.
All one needs to realize is that a matrix is much like a vector but with a $dim attribute for its shape, and that the values of that underlying vector are stored by column.
To create your original matrix, you could do:
A <- matrix(1:16, nrow=4, byrow=TRUE)
print(attributes(A))
The byrow argument tells matrix to allocate the elements of the input vector in a rowwise fashion to the matrix, instead of columnwise.
However, it does not change the fact that after this allocation, the internal storing of values in the matrix is still by column. The byrow argument has then simply changed the ordering of elements in the underlying vector, as can easily be seen:
print(as.numeric(A))
What we need to get your desired output, is to first get the sequence in your matrix ordered by column - so that the underlying vector is 1:16 again. For this we can use the transpose function t(). After the transpose, we can bring the now nicely ordered values into the desired 2x8 shape in a rowwise fashion. So:
B <- matrix(t(A), nrow=2, byrow=TRUE)
print(B)

Related

How to update matrix value in R based on comparison of two matrix?

How to generate a matrix based on a comparison of two matrices. I have (column,row) matrix A (10,1) and B (10, 100). Matrix A is compared to each row of matrix B if the value of B is smaller than A then value B is updated to a value of A.
n.units<-100
n.option<-10
A<-rnorm(n.option,1,0.2)
B<-matrix(rnorm(n.option*n.units,1,0.2)n.col=n.units)
renew <-function(){Thresholds=obj.value }
update1 <- apply((Thresholds < obj.value),1,renew)
I am new to R programming, please give some advice to solve it.
I guess what you are trying can be achieved with pmax. Try
pmax(B, A)
You have a numeric vector A which is compared with matrix B. 1st element of A is compared with first row of B and the maximum value is selected. Same goes for all other rows since pmax recycles the shorter vector to the longer vector length. Also note that pmax(B, A) gives different structure than pmax(A, B) although the value is the same.
Just to make it easier to understand, consider this example
mat <- matrix(1:10, ncol = 5)
mat
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 3 5 7 9
#[2,] 2 4 6 8 10
pmax(mat, c(3, 7))
# [,1] [,2] [,3] [,4] [,5]
#[1,] 3 3 5 7 9
#[2,] 7 7 7 8 10
Here 1st row is compared with 3 and second row is compared with 7 and maximum value is selected.

Explicitly providing nrow and ncol to `as.matrix` does not create dimensions

I am creating a simple 3x3 matrix with 9 values using the as.matrix() function. But the output I am seeing seems to be incorrect. What am I missing?
Here's what I am doing:
> s <- as.matrix(c(3,4,5,6,7,8,9,10,11),nrow = 3,ncol = 3)
What I expect to see:
> s
[,1] [,2] [,3]
[1,] 3 6 9
[2,] 4 7 10
[3,] 5 8 11
But What I actually see:
> s
[,1]
[1,] 3
[2,] 4
[3,] 5
[4,] 6
[5,] 7
[6,] 8
[7,] 9
[8,] 10
[9,] 11
>
What am I missing?
The documentation for as.matrix() function says that nrow and ncol are used to defined the desired number of rows and columns.
Any pointers?
as.matrix has no nrow and ncol parameter. What you need is actually matrix. Check ?as.matrix
matrix(c(3,4,5,6,7,8,9,10,11),nrow = 3,ncol = 3)
# [,1] [,2] [,3]
#[1,] 3 6 9
#[2,] 4 7 10
#[3,] 5 8 11
You offered a vector as the first argument to as.matrix and the help page (Details section) says:
The default method for as.matrix calls as.vector(x), and hence e.g. coerces factors to character vectors.
When coercing a vector, it produces a one-column matrix, and promotes the names (if any) of the vector to the rownames of the matrix.
The usage section doesn't actually include ncol or nrow in the argument list to as.matrix. They just get ignored. The code to look at is:
as.matrix.default
That code does preserve matrix dimension if the first argument has them.
I find that using as.matrix is a good way to get print to produce a left-justified one column listing of atomic character vectors.

R: Picking values from matrix by indice matrix

I have a datamatrix with n rows and m columns (in this case n=192, m=1142) and an indice matrix of nxp (192x114). Each row of the indice matrix shows the column numbers of the elements that I would like to pick from the matching row of the datamatrix. Thus I have a situation something like this (with example values):
data<-matrix(1:30, nrow=3)
data
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 4 7 10 13 16 19 22 25 28
[2,] 2 5 8 11 14 17 20 23 26 29
[3,] 3 6 9 12 15 18 21 24 27 30
columnindices<-matrix(sample(1:10,size=9, replace=TRUE),nrow=3)
columnindices
[,1] [,2] [,3]
[1,] 8 7 4
[2,] 10 8 10
[3,] 8 10 2
I would like to pick values from the datamatrix rows using the in columnindices matrix, so that the resulting matrix would look like this
[,1] [,2] [,3]
[1,] 22 19 10
[2,] 29 23 29
[3,] 24 30 6
I tried using a for loop:
result<-0
for(i in 1:3) {
result[i]<-data[i,][columnindices[,i]]
print[i]
}
but this doesn't show the wished result. I guess my problem should be rather simply solved, but unfortunately regardless many hours of work and multiple searches I still haven't been able to solve it (I am rookie). I would really appreciate some help!
Your loop is just a little bit off:
result <- matrix(rep(NA, 9), nrow = 3)
for(i in 1:3){
result[i,] <- data[i, columnindices[i,]]
}
> result
[,1] [,2] [,3]
[1,] 25 13 7
[2,] 29 29 23
[3,] 15 15 18
Note that the matrix is not exactly the one you posted as expected result because the code for your example columnindices does not match the matrix you posted below. Code should work as you want it.
The for-loop way described by #LAP is easier to understand and to implement.
If you would like to have something universal, i.e. you don't need to
adjust row number every time, you may utilise the mapply function:
result <- mapply(
FUN = function(i, j) data[i,j],
row(columnindices),
columnindices)
dim(result) <- dim(columnindices)
mapply loop through every element of two matrices,
row(columnindices) is for i row index
columnindices is for j column index.
It returns a vector, which you have to coerce to the initial columnindices dimension.

How to append a vector as a column in R matrix?

Suppose I have a matrix similar as the one show below in R.
[,1] [,2] [,3]
[1,] 2 4 3
[2,] 2 5 7
How can append a column to the front like below.
[,1] [,2] [,3] [,4]
[1,] 1 2 4 3
[2,] 1 1 5 7
Lastly, the matrix has many rows.
use cbind
cbind(c(1,2), matrix(1:6, nrow=2))
So in case you work with bigger data, imagine your matrix is saved as m and you have a vector my_vector you want to add as a column in front of this matrix, the command would be
new_m <- cbind(my_vector, m)
Make sure the dimension of your vector fit the number of rows in your matrix.
In case you want to add rows instead of columns, the command is called rbind and is used in exactly the same way.

Subset matrix with arrays in r

It is probably fairly basic but I have not found an easy solution.
Assume I have a three-dimensional matrix:
m <- array(seq_len(18),dim=c(3,3,2))
and I would like to subset the matrix with the arrays of indexes:
idxrows <- c(1,2,3)
idxcols <- c(1,1,2)
obtaining the arrays in position (1,1),(2,1) and (3,2), that is:
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 10 14 18
I have tried m[idxrows,idxcols,] but without any luck.
Is there anyway to do it (without obviously using a for loop)?
Not sure if there is any easy built in extract syntax, but you can work around this with mapply:
mapply(function(i, j) m[i,j,], idxrows, idxcols)
# [,1] [,2] [,3]
#[1,] 1 2 6
#[2,] 10 11 15
Or slightly more convoluted, create a index matrix whose columns match the dimensions of the original array:
thirdDim <- dim(m)[3]
index <- cbind(rep(idxrows, each = thirdDim), rep(idxcols, each = thirdDim), 1:thirdDim)
matrix(m[index], nrow = thirdDim)
# [,1] [,2] [,3]
#[1,] 1 2 6
#[2,] 10 11 15

Resources