How to change elements in one matrix indexed in another matrix? - r

I have two matrices A and B. Matrix B is a two-column matrix, each row containing one index of an element in matrix A. I want to change those elements in matrix A, which are indexed by each row in matrix B, to 0.
Is there a way to avoid using the loop shown below?
> A <- matrix(1:12, 3, 4)
> B <- matrix(c(1, 2, 2, 2, 3, 4), byrow = TRUE, ncol = 2)
> A
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
> B
[,1] [,2]
[1,] 1 2
[2,] 2 2
[3,] 3 4
> for (i in 1:nrow(B)) {
+ A[B[i, 1], B[i, 2]] <- 0
+ }
> A
[,1] [,2] [,3] [,4]
[1,] 1 0 7 10
[2,] 2 0 8 11
[3,] 3 6 9 0

It's done like this
A[B] <- 0;

Related

Solve linear equation system b=0

I found this code to resolve a linear equation system with b=0, but I would like to know why with the first matrix only one column is returned and with the second matrix two columns are returned.
library(MASS)
Null(t(A))
R > (A <- matrix(c(1,2,3,2,4,7), ncol = 3, byrow = TRUE))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 7
R > Null(t(A))
[,1]
[1,] -8.944272e-01
[2,] 4.472136e-01
[3,] 7.771561e-16
R > (A <- matrix(c(1,2,3,2,4,6), ncol = 3, byrow = TRUE))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 6
R > Null(t(A))
[,1] [,2]
[1,] -0.5345225 -0.8017837
[2,] 0.7745419 -0.3381871
[3,] -0.3381871 0.4927193
library(MASS)
A <- matrix(c(1,2,3,2,4,7), ncol = 3, byrow = T)
t(A)
#> [,1] [,2]
#> [1,] 1 2
#> [2,] 2 4
#> [3,] 3 7
B <- matrix(c(1,2,3,2,4,6), ncol = 3, byrow = T)
t(B)
#> [,1] [,2]
#> [1,] 1 2
#> [2,] 2 4
#> [3,] 3 6
From the above, you can see that in your last case, all the rows are linearly combination of one another. In your 1st case, 2 rows are linear combinations.
You have a rank of 2 vs 1 and thus answers of 2 vs 1.

understanding elements in a matrix

I'm trying to understand more about matrices in R and I stumbled upon this query. Could someone explain to me why x[2:3, 2:2] returns 5 and 6?
Am I right to say that, 2:3, 2:2, simply refers to row 2, column 2 and row 3 column 2?
> x <- matrix(c(1:6), ncol = 2)
> x
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
>
>
> x[2:3, 2:2]
[1] 5 6
If that's the case, why is it that having a 3x3 matrix returns such a strange value?
> x <- matrix(c(1:9), ncol = 3)
> x
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> x[1:2, 3:2, drop = F]
[,1] [,2]
[1,] 7 4
[2,] 8 5

R mean values of a sum of Matrices without divide for points equal zero

A = matrix(c(1,2,3, 0, 2, 2, 0,2 ,3), nrow=3, ncol=3)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 2 2 2
[3,] 3 2 3
B = matrix(c(1,2,3, 1, 4, 2, 2,2 ,1), nrow=3, ncol=3)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 4 2
[3,] 3 2 1
C = A + B /(Sum numbers diff of zero)
C = matrix(c(1,2,3, 1, 3, 2, 2,2 ,2), nrow=3, ncol=3)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 3 2
[3,] 3 2 2
I need do it for a list of N matrices (mat_vect[[i]]):
list_mat_vect[[i]] <- assign(paste("a", i, sep = ""), mat_vect[[i]])
Sum matrix and get mean value
mat_sum_mean = Reduce("+", list_mat_vect) / length(file_list)
Here is dividing for all numbers, including the zeros. I dont want that.
You can do
(A+B)/((A!=0) + (B!=0))
to get
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 3 2
[3,] 3 2 2
Here != tests for equality with zero returning TRUE or FALSE. When we add those up, the TRUEs are treated like 1 and the FALSEs become 0.
You can do this with a list of matrices as well
list_mat_vect<-list(A,B)
Reduce("+", list_mat_vect) / Reduce("+", lapply(list_mat_vect, function(x) x!=0))

R apply on a matrix a function of columns and row index

I would like to apply on a matrix a function of both the value, the row index and the column index for every value in the matrix and get the transformed matrix.
For example
mat<-matrix(c(1,2,3,4),2,2)
mat
[,1] [,2]
[1,] 1 3
[2,] 2 4
f<-function(x,i,j){x+i+j}
mat2 <- my.apply(f,mat)
mat2
[,1] [,2]
[1,] 3 6
[2,] 5 8
The example above is for illustration purposes, f can be much more complex.
apply does not do the job, because of the way the extra arguments are handled.
apply(mat,1:2,f,seq_along(mat[,1]),seq_along(mat[1,]))
, , 1
[,1] [,2]
[1,] 3 4
[2,] 5 6
, , 2
[,1] [,2]
[1,] 5 6
[2,] 7 8
I can not find either a way with the lapply family. A for loop can do the job but it won't be efficient nor elegant.
Any suggestions?
Thanks
Try mapply
mat <- matrix(c(1, 2, 3, 4), 2, 2)
mat
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
matrix(mapply(function(x, i, j) x + i + j, mat, row(mat), col(mat)), nrow = nrow(mat))
## [,1] [,2]
## [1,] 3 6
## [2,] 5 8
Here is an ugly use of apply, just for some quick and dirty job. The trick is adding an additional column (or row) for row (or column) indices.
mat <- matrix(c(1, 2, 3, 4), 2, 2)
t(apply(cbind(mat, 1:nrow(mat)), 1, function(x){x[1:ncol(mat)] + 1:ncol(mat) + x[ncol(mat)+1]}))
## [,1] [,2]
##[1,] 3 5
##[2,] 6 8
If you have a function f(x, i, j) already, you can also try:
apply(cbind(mat, 1:nrow(mat)), 1, function(x){a = numeric(); for(j in 1:ncol(mat)){a[j] = f(x[j], x[ncol(mat)+1], j)}; a})

Filtering out rows in a matrix containing only 0 in R

I have the matrix
m <- matrix(c(1, 0, 3, 4, 0, 6), 3)
I need to filter out rows where both columns have a value of 0 in effect returning the matrix:
m <- matrix(c(1, 3, 4, 6), 3)
I have tried
m[m[, 1] > 0 & m[, 2] > 0]
but this returns a vector instead of a matrix stripped of rows with only 0. This should be simple but I am stuck.
Thanks,
-Elizabeth
In case you had many columns
m
[,1] [,2]
[1,] 1 4
[2,] 0 0
[3,] 3 6
m^2
[,1] [,2]
[1,] 1 16
[2,] 0 0
[3,] 9 36
rowSums(m^2)
[1] 17 0 45
m[rowSums(m^2)>0,]
[,1] [,2]
[1,] 1 4
[2,] 3 6
You are just missing a "," in your own solution.
Use
m[m[,1]>0 & m[,2]>0,]
and it will work:
> m[m[,1]>0 & m[,2]>0,]
[,1] [,2]
[1,] 1 4
[2,] 3 6

Resources