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

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.

Related

R: How to convert a vector into matrix without replicating the vector?

Here's my problem:
I have a vector and I want to convert it into a matrix with fixed number of columns, but I don't want to replicate the vector to fill the matrix when it's necessary.
For example:
My vector has a length of 15, and I want a matrix with 4 columns.I wish to get the matrix wit 15 elements from the vector and a 0 for the last element in the matrix.
How can I do this?
Edit:
Sorry for not stating the question clearly and misguiding you guys with my example. In my program,I don't know the length of my vector, it depends on other parameters and this question involves with a loop, so I need a general solution that can solve many different cases, not just my example.
Thanks for answering.
You could subset your vector to a multiple of the number of columns (so as to include all the elements). This will add necessary amount of NA to the vector. Then convert to matrix.
x = 1:15
matrix(x[1:(4 * ceiling(length(x)/4))], ncol = 4)
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
If you want to replace NA with 0, you can do so using is.na() in another step
We can also do this with dim<- and length<-
n <- 4
n1 <- ceiling(length(x)/n)
`dim<-`(`length<-`(x, n*n1), c(n1, n))
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
data
x <- 1:15

Strange behavior of apply/ reverse function in R

I have a simple matrix:
mat = rbind(c(1:3),c(4:6),c(7:9))
mat
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 8 9
I want to now reverse the matrix row-wise. That is I want to obtain:
revMat
# [,1] [,2] [,3]
# [1,] 3 2 1
# [2,] 6 5 4
# [3,] 9 8 7
To do this I tried
apply(mat, 1, rev)
And the result was:
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 2 5 8
# [3,] 1 4 7
I find this to be extremely strange. It's like the rows are reversed and then the final matrix is transposed. I don't understand why. If I try simply, for instance,
apply(mat, 2, rev)
it gives me the expected reversal of each column
# [,1] [,2] [,3]
# [1,] 7 8 9
# [2,] 4 5 6
# [3,] 1 2 3
Therefore to obtain the final result I have to perform
t(apply(t(bg), 2, rev))
Thus obtaining the required matrix is NOT a problem for me, but I don't understand the "anomaly" in the behavior of apply/ reverse. Can anyone explain this to me?
Edit: To make clear the distinction, I already know how to do the reversal. I want to know WHY this happens. How to is clear from many earlier questions including
How to reverse a matrix in R?
apply always puts the result in the first dimension. See ?apply for more information. Assuming this input:
mat <- matrix(1:9, 3, byrow = TRUE)
here are some alternatives:
1) transpose
t(apply(mat, 1, rev))
2) avoid apply with indexing
mat[, 3:1]
3) iapply An idempotent apply was posted here:
https://stat.ethz.ch/pipermail/r-help/2006-January/086064.html
Using that we have:
iapply(mat, 1, rev)
There was also an idempotent apply, iapply, in version 0.8.0 of the reshape package (but not in the latest version of reshape): https://cran.r-project.org/src/contrib/Archive/reshape/
4) rollapply rollapply in the zoo package can be used:
library(zoo)
rollapply(mat, 1, rev, by.column = FALSE)
5) tapply The tapply expression here returns a list giving us the opportunity to put it together in the way we want -- in this case using rbind:
do.call("rbind", tapply(mat, row(mat), rev))
6) multiply by a reverse diagonal matrix Since rev is a linear operator it can be represented by a matrix:
mat %*% apply(diag(3), 1, rev)
or
mat %*% (row(mat) + col(mat) == 3+1)
If you look at the help for apply(), this is exactly the behavior you would expect:
Value
If each call to FUN returns a vector of length n, then apply returns
an array of dimension c(n, dim(X)[MARGIN]) if n > 1.
a nice option to do what you want is to use indexing:
mat[,ncol(mat):1]

how unroll a matrix in 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)

Preserve structure, when indexing a matrix with another matrix in R

Dear StackOverflowers,
I have an integer matrix in R and I would like to subset it so that I remove 1 specified cell in each column. So that, for instance, a 4x3 matrix becomes a 3x3 matrix. I have tried doing it by creating the second logical matrix of the same dimensions.
(subject.matrix <- matrix(1:12, nrow = 4))
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
(query.matrix <- matrix(c(T, T, F, T, T, F, T, T, T, T, T, F), nrow = 4))
[,1] [,2] [,3]
[1,] TRUE TRUE TRUE
[2,] TRUE FALSE TRUE
[3,] FALSE TRUE TRUE
[4,] TRUE TRUE FALSE
The problem is that, when I index the first matrix by the second one, it is simplified to an integer vector.
subject.matrix[query.matrix]
[1] 1 2 4 5 7 8 9 10 11
I've tried adding drop=F, but to no avail. I know, I can just wrap the resulting vector into a 3x3 matrix. So the expected outcome would be:
matrix(subject.matrix[query.matrix], nrow = 3)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
But I wonder if there's a more elegant/direct solution. I'm also not attached to using a logical matrix as the index, if that means a simpler solution. Perhaps, I could subset it with a vector of indices for the rows to be removed in each column, which in this case would translate into c(3, 2, 4).
Many thanks!
Edit based on #LyzandeR suggestion: My final goal was to take column sums of the resulting matrix. So replacing the redundant values with NA's seems to be the best way to go.
I think that the only way you can preserve the matrix structure would be to use a more general way of your question edit i.e.:
matrix(subject.matrix[query.matrix], ncol = ncol(subject.matrix))
You could even convert it into a function if you plan on using it multiple times:
subset.mat <- function(mat, index, cols=ncol(mat)) {
matrix(mat[index], ncol = cols)
}
Output:
> subset.mat(subject.matrix, query.matrix)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
Also (sorry just read your updated comment) you might consider using NAs in the matrix instead of subsetting them out, which will allow you to calculate the column sums as you say:
subject.matrix[!query.matrix] <- NA
subject.matrix
# [,1] [,2] [,3]
#[1,] 1 5 9
#[2,] 2 NA 10
#[3,] NA 7 11
#[4,] 4 8 NA
This is a little brute-forceish, but I think you'll be able to extrapolate it into something more general:
new.matrix = matrix(ncol = ncol(subject.matrix), nrow = nrow(subject.matrix) - 1)
for(i in 1:ncol(subject.matrix)){
new.matrix[,i] = subject.matrix[,i][query.matrix[,i] == TRUE]
}
new.matrix
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
Essentially, I just initialized an empty matrix, and then iterated through each column of subject.matrix taking only the TRUE values for query.matrix.

assigning random or automatized names for e.g. matrices in R [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
generate variable names (something like get())
If I want to create matrices with different names in an automatized way, I run into problems.
For example, I want to create three matrices named a1,a2 and a3.
x<-1:3
a<-"a"
listofnames<-paste(a,x) ## a vector with the names that I want to use for my matrices
My problem is to assign a matrix the different names from the vector I created.
For example, to create a matrix called a1 (the first "name" in my vector), this will of course not work at all:
listofnames[1]<-matrix(ncol=2,nrow=2)
But how would I do it?
I've been looking on the internet but can't find any answer..
Thank you so much for your help
Use assign as in:
x<-1:3
a<-"a"
listofnames <-paste(a,x)
set.seed(001)
for(i in 1:length(listofnames)){
assign(listofnames[i], matrix(sample(9), ncol=3))
}
get(listofnames[1])
[,1] [,2] [,3]
[1,] 3 6 8
[2,] 9 2 7
[3,] 5 4 1
get(listofnames[2])
[,1] [,2] [,3]
[1,] 1 5 6
[2,] 2 7 3
[3,] 8 4 9
get(listofnames[3])
[,1] [,2] [,3]
[1,] 4 2 5
[2,] 7 9 3
[3,] 8 1 6
Once you assign matrices to the names contained in listofnames you can access by using get function as shown above. If you only do listofnames[1] this will give you the firt name in listofnames but not the elements stored under that name, to do so you must use get(listofnames[1])
It might be better if you explain exactly what you are trying to achieve, but you might also want to explore assign():
x <- 1:3
a <- "a"
listofnames <- paste(a, x, sep="")
assign(listofnames[1], matrix(nrow = 2, ncol = 2))
a1
[,1] [,2]
[1,] NA NA
[2,] NA NA

Resources