I want to get the row-column coordinates for all nonzero elements in a matrix M. If M isn't too big, it's straightforward:
m <- matrix(sample(0:1, 25, TRUE, prob=c(0.75, 0.25)), 5, 5)
#[,1] [,2] [,3] [,4] [,5]
#[1,] 0 0 0 0 0
#[2,] 1 1 0 0 0
#[3,] 0 0 0 1 0
#[4,] 0 0 1 0 0
#[5,] 0 0 0 0 0
nz <- which(m != 0)
cbind(row(m)[nz], col(m)[nz])
#[,1] [,2]
#[1,] 2 1
#[2,] 2 2
#[3,] 4 3
#[4,] 3 4
However, in my case M is a sparse matrix (created using the Matrix package), whose dimensions can be very large. If I call row(M) and col(M) like above, I'll be generating a couple of dense matrices the same size as M, which I definitely don't want to do.
Is there a way of getting a result like the above without creating dense matrices along the way?
I think you want
which(m!=0,arr.ind=TRUE)
Looking at showMethods("which"), it seems that this is set up to work efficiently with sparse matrices. You can also get the answer more directly (but inscrutably) for a sparse, column-oriented matrix by manipulating the internal #p (column pointer) and #i (row pointer) slots:
mm <- Matrix(m)
dp <- diff(mm#p)
cbind(mm#i+1,rep(seq_along(dp),dp))
Related
I have a few vectors that I would like to arrange into square matrices of the same dimensions for future multiplication. Some vectors are shorters than others so I would like to add zeros to the shorters ones so that all the resulting matrices are of the same dimension.
I tried to add 0 to the tail of the shorter vectors but I haven't been able to generate the reducible matrices that I want. Below are some pseudo data. Thank you for your time!
seq_a <- rep(1,4)
seq_b <- rep(1,3)
matA <- diag(seq_a)
matB <- matrix(c(diag(seq_b),0),nrow=4,ncol = 4)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 0
[2,] 0 0 0 0
[3,] 0 0 1 1
[4,] 0 0 0 0
Warning message:
In matrix(c(diag(seq_c), 0), nrow = 4, ncol = 4) :
data length [10] is not a sub-multiple or multiple of the number of rows [4]
The desired matB should be
[,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 0 1 0 0
[3,] 0 0 1 0
[4,] 0 0 0 0
That is just a typo: you should first pad the vector, and then convert it to a diagonal matrix.
matB <- diag( c(seq_b,0) )
Suppose I have a list of matrices. Suppose further I have found the smallest values by the column.
Here is my last question
I really need to know from which matrix each smallest value is selected. My original function is very complicated. Therefore, I provided a simple example. I have one idea and really do not know to implement it correctly in R.
My idea is:
Suppose that [i,j] is the elements of the matrix. Then,
if(d[[1]][i,j] < d[[2]][i,j]){
d[[1]][i,j] <– "x"
}else { d[[2]][i,j] <– "z"}
So, I would like to sign the name of the matrix that corresponds to each smallest value. Then, store the names in a separate matrix. So, then I can see the values in one matrix and their corresponding names (from where they come from) in another matrix
For example,
y <- c(3,2,4,5,6, 4,5,5,6,7)
x[lower.tri(x,diag=F)] <- y
> x
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 3 0 0 0 0
[3,] 2 6 0 0 0
[4,] 4 4 5 0 0
[5,] 5 5 6 7 0
k <- c(1,4,5,2,5,-4,4,4,4,5)
z[lower.tri(z,diag=F)] <- k
> z
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 1 0 0 0 0
[3,] 4 5 0 0 0
[4,] 5 -4 4 0 0
[5,] 2 4 4 5 0
d <- list(z, x)
Then:
do.call(pmin, d) (answered by #akrun)
Then, I will only get the matrix with smallest values. I would like to know where each value is come from?
Any idea or help, please?
You can use Map and do.call to create your own functions that will be applied element-wise to a list of inputs,
in your case a list of matrices.
pwhich.min <- function(...) {
which.min(c(...)) # which.min takes a single vector as input
}
di <- unlist(do.call(Map, c(list(f = pwhich.min), d)))
dim(di) <- dim(x) # take dimension from one of the inputs
di
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 1 1 1 1
[3,] 1 2 1 1 1
[4,] 1 2 2 1 1
[5,] 2 2 2 2 1
EDIT:
To elaborate,
you could do something like Map(f = min, z, x) to apply min to each pair of values in z and x,
although in that case min already supports arbitrary amount of inputs through an ellipsis (...).
By contrast,
which.min only takes a single vector as input,
so you need a wrapper with an ellipsis that combines all values into a vector
(pwhich.min above).
Since you may want to have more than two matrices,
you can put them all in a list,
and use do.call to put each element in the list as a parameter to the function you specify in f.
Or another option would be to convert it to a 3D array and use apply with which.min
apply(array(unlist(d), c(5, 5, 2)), c(1, 2), which.min)
Or with pmap from purrr
library(purrr)
pmap_int(d, ~ which.min(c(...))) %>%
array(., dim(x))
I have a low triangle matrix:
> Mat1
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 1 0 0 0 0
[3,] 3 3 0 0 0
[4,] 4 4 4 0 0
[5,] 4 1 1 3 0
lower.tri returns a matrix of logicals the same size of a given matrix with entries TRUE in the lower or upper triangle (R help).
Then lets
lowt <– lower.tri(Mat1)
xx <– Mat1[lowt]
xx
[1] 1 3 4 4 3 4 1 4 1 3
My question is how does Mat1[lowt] work? how do we use the function as an element by using [ ]?! what is the idea? any help please?
how do we use the function as an element by using [ ]?!
lowt is not a function, but a boolean matrix, as you said yourself:
lowt <– lower.tri(Mat1) saves the return variable of lower.tri in lowt; Mat1[lowt] therefore returns values from Mat1, by logical indexing - a widely used concept in R.
I'm currently trying to manipulate a matrix full of zeros that I want to fill with numbers.
The purpose of the matrix is to describe a distribution of density.
The thing is, in order to do so, I only have three vectors describing non-zero values that are in the matrix.
That is, the first contains the ordinate value of the cell that contains a number, the second contains the abscissa value and the third contains the density value.
For instance, if I have a density of 3 in the [3,2] cell, I'd have three vectors as so:
vector1 = (3), vector2 = (2), vector3 = (3)
I have unsuccessfully tried to fill it with a for loop, and since I'm not very skilled with R I'm having a hard time figuring out how to fill that matrix.
Thanks in advance for your answers, should you have any question please don't hesitate.
Using R built-in vectorised methods, this is a beautiful breeze. You are looking for the [<- replacement function. Here is an example:
m <- matrix( 0 , 4 , 4 )
# [,1] [,2] [,3] [,4]
#[1,] 0 0 0 0
#[2,] 0 0 0 0
#[3,] 0 0 0 0
#[4,] 0 0 0 0
v1 <- c( 3 , 2 , 1 )
v2 <- c( 2 , 1 , 4 )
v3 <- c( 10, 20 , 30 )
m[ cbind( v1 , v2 ) ] <- v3
# [,1] [,2] [,3] [,4]
#[1,] 0 0 0 30
#[2,] 20 0 0 0
#[3,] 0 10 0 0
#[4,] 0 0 0 0
This question already has answers here:
How to replace non-diagonal elements in a matrix?
(6 answers)
Closed 9 years ago.
Okay, I asked this question earlier but I got bashed (deservedly) for not specifying anything and showing no sign of previous attempt. So let me try again..
I'm using R, and I have a 463✕463 matrix. What I would like to do is to replace all elements other than the diagonal ones (X11, X22, X33,...,Xjj) with zero.
E.g. I want:
[1 4 5
2 3 5
3 9 8]
to be:
[1 0 0
0 3 0
0 0 8]
When I use the diag() function, it simply gives me a column vector of the diagonal values. I imagine I can use the replace() function somehow combined with a "if not diagonal" logic...but I am lost.
And yes, as some here have guessed, I am probably much younger than many people here and am completely new at this...so please put me in the right direction. Really appreciate all your help!
In R, the diag method has two functions.
It returns the diagonal of a matrix. I.e.
m <- matrix(1:9, ncol=3)
m
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 2 5 8
# [3,] 3 6 9
diag(m)
# [1] 1 5 9
It can construct a diagonal matrix.
diag(1:3)
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 2 0
# [3,] 0 0 3
So in your case, extract the diagonal from your existing matrix and supply it to diag:
diag(diag(m))
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 5 0
# [3,] 0 0 9
using outer
You can use the following to compute a logical matrix which describes the non-diagonal entries of a n×n matrix:
outer(1:n, 1:n, function(i,j) i!=j)
Applied to your example:
> m <- matrix(c(1,2,3,4,3,9,5,5,8),ncol=3)
> m
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 3 5
[3,] 3 9 8
> m[outer(1:3, 1:3, function(i,j) i!=j)] <- 0
> m
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 3 0
[3,] 0 0 8
using triangles
A possible alternative would be combining the two triangles on either side of the diagonal. In this case, you use the matrix m itself as input to determine the size.
upper.tri(m) | lower.tri(m)
Applied to your use case:
> m[upper.tri(m) | lower.tri(m)] <- 0
It seems you already got this answer in response to your original post…
m[ col(m)==row(m) ] <- 0
> m <- matrix(1:9, 3)
> m[ col(m)==row(m) ]
[1] 1 5 9
> m[ col(m)!=row(m) ] <- 0
> m
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 5 0
[3,] 0 0 9