Importing incomplete data to matrix in R - 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

Related

How to use vector elements as coordinates for matrix positions in r?

I'd like to use elements of a vector that consists strictly of double digit figures as a mapping to specific matrix positions. For instance, consider the following:
mat1 <- rbind(c(12,31,22,13),c(3,1,5,7))
mat <- matrix(rep( 0, len=25), nrow = 5)
What I'd like to do is use mat1[1,1] to access position 1 2 of mat, and at that position, I'd like the corresponding value of 3 to be stored.
I've tried converting mat1's elements to strings, splitting them, storing them, calling the as.numeric() function on the vector in which they're stored and finally running a loop, and while I ultimately got it to work, I now have close to a million loops in my program. I'd appreciate any ideas!
We can strsplit the first row of 'mat', convert it to a row/column index, and use that to assign the corresponding elements of 'mat' with the second rows of 'mat1'
i1 <- do.call(rbind, lapply(strsplit(as.character(mat1[1,]),""), as.numeric))
mat[i1] <- mat1[2,]
mat
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 3 7 0 0
#[2,] 0 5 0 0 0
#[3,] 1 0 0 0 0
#[4,] 0 0 0 0 0
#[5,] 0 0 0 0 0
Or with substr
m1 <- mat1[1,]
i1 <- cbind(as.integer(substr(m1, 1, 1)), as.integer(substr(m1, 2, 2)))
mat[i1] <- mat1[2,]

Create reducible matrices, perhaps with diag()

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) )

Efficiently obtaining nonzero element coordinates of sparse matrix

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))

R: Populating a matrix using data from two other matrices using condition

I am new to R. I have two matrices:
Amat<-matrix(data=c(11:20,NA,NA,NA,NA,25:30),nrow = 4,ncol = 5)
Bmat<-matrix(data=c(1:6,NA,NA,NA,NA,11:20),nrow = 4,ncol = 5)
I want to build a third matrix Cmat of dimension 4x5 (same as Amat & Bmat) in such a way that data from Amat and Bmat are comapred as below:
if(is.na(Amat)!="TRUE" && is.na(Bmat)!="TRUE") {1} else {0}
i.e. Cmat should be filled with '1' for the respective position if both matrices (Amat & Bmat) doesn't have NA.
Can anyone help me to approach for this without going for loop? Thanks in advance!
We can do this by coercing the logical matrix (!is.na(Amat) & !is.na(Bmat)) to binary (+)
Cmat <- +(!is.na(Amat) & !is.na(Bmat))
Cmat
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 1 0 0 1
#[2,] 1 1 0 0 1
#[3,] 1 0 0 1 1
#[4,] 1 0 0 1 1
Or other variations include
+(!is.na(Amat*Bmat))
Or
+(!is.na(Amat + Bmat))

Element wise multiplication of first 4 columns by last 4 columns

I'm trying to do an element wise multiplication of the first 2 columns by the next 2 columns and add the result on the fifth column
for example :
> x = diag(4)
[,1] [,2] [,3] [,4] C1*C3 + C2*C4
[1,] 1 0 0 0 1*0 + 0*0
[2,] 0 1 0 0 0*0 + 1*0
[3,] 0 0 1 0 0*1 +0*0
[4,] 0 0 0 1 0*0 +0*1
Thank you!
You can do this pretty directly in base R.
cbind(x, rowSums(x[,1:2] * x[,3:4]))
Although going by what you show in your 'results' you are doing every other column which is a simple modification
cbind(x, rowSums(x[,c(1,3)] * x[,c(2,4)]))

Resources