Set some values in a matrix equal to zero - r

I have a matrix with ID values at grid points and I have a vector containing some of those ID's. I would like to write a function so that for all the ID's contained in the vector, the corresponding ID in the matrix is set to 0.
For example:
ID <- matrix(c(2,3), nrow=2)
A <- matrix(c(0, 0, 2, 2, 0, 3,
1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 4,
1, 0, 1, 0, 0, 4), nrow=4, byrow=TRUE)
I would like to transform my matrix A so that the 2's and 3 become 0.
I found a way to do this manually with the "if" function, setting conditions:
a <- nrow(A)
b <- ncol(A)
vide <- array(NaN, dim=c(a,b))
for (i in c(1:a)) {for (j in c(1:b)) {
if ( (A[i,j]==ID[1,1]) | (A[i,j]==ID[2,1]) ) {
vide[i,j]==0} else {vide[i,j]=A[i,j]}
}
}
vide[is.na(vide)] <- 0
But I would like to create an automatic function that will do this for all the ID's contained in the ID vector, regardless of the number of rows. Because I will then run this over many years and the ID matrix will not always have the same number of rows. Is there a way to do that ?
I also tried another way, to make R write the conditions in the "if" function by itself:
d <- nrow(ID)
Cond <- array(NaN, dim=c(d,1))
for (k in c(1:d)) {
Cond[k,1]=paste("(A[i,j]==ID[",k,",1]) ", sep="")
}
Cond <- t(Cond)
Cond <- paste(Cond,collapse="| ")
Cond <- noquote(Cond)
for (i in c(1:a)) {for (j in c(1:b)) {
if (Cond) {
vide[i,j]==0
} else {
vide[i,j]=A[i,j]
}
}
but the problem is that Cond is a character matrix and I get the error message "argument is not interpretable as logical".
I am a beginner in R so maybe there is an easier way to do what I would like to do ? I tried searching on Internet but never seemed to find something appropriate to my case. Thanks for your help!

How's this? The trick is to handle matrix is a vector. R will take care of the second dimension on the fly. What I do below is find where in A elements from ID appear and overwrite them with a zero.
> A
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 2 2 0 3
[2,] 1 0 0 0 0 0
[3,] 0 1 0 0 0 4
[4,] 1 0 1 0 0 4
> A[A %in% ID] <- 0
> A
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 0 0 0
[2,] 1 0 0 0 0 0
[3,] 0 1 0 0 0 4
[4,] 1 0 1 0 0 4

Related

How to set if condition for a row of matrix inside for lapply function in R

I have a data set where I need to calculate Kendall's tau pair-wisely (between each pair of variables). I want to store the result in a matrix. However, I would like to find the result and if each value at a current row is less than a specific value, then I would like the loop to stop and do not calculate the next correlation (next row), and return 0 values for all entries for all the next rows. I want to do that with lapply function (if possible). In other words, I would like to set a function that works for each row. Then, apply my condition. That is, I can build a function that works for each row separately, then, if the previous row met the condition, all the values in the next rows set to zero.
For example,
Suppose I have the following matrix:
structure(c(5, 4, 3, 1, 2, 0, 4, 3, 2, 1, 0, 0, 3, 2, 1, 0, 0,
0, 2, 1, 0, 0, 0, 0, 1), .Dim = c(5L, 5L))
Matrix1
[,1] [,2] [,3] [,4] [,5]
[1,] 5 0 0 0 0
[2,] 4 4 0 0 0
[3,] 3 3 3 0 0
[4,] 1 2 2 2 0
[5,] 2 1 1 1 1
Suppose I would like to find the square root of each entry of the matrix row by row. Then, if all entries of each row are >= 1.6 then, the entries of this row and all comping rows are set to zero, and the for loop stop, return me the matrix as follows:
Matrix1
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 0
[4,] 1 1.4 1.4 1.4 0
[5,] 1.4 1 1 1 1
Any help, please?
Here is one with nested for loop.
Initialize the object to be stored ('r.tau') as a matrix with dim attributes from the number of cols (ncol) of the dataset
Do a nested loop on the sequence of columns
If the indexes are not equal, calculate the cor of the columns subset inside the inner loop
Outside the inner loop, add a condition to check whether all the values in that particular row (excluding the 0) are less than or equal to 0.2
If condition from 4 is TRUE, set the row to 0 and break out of the loop
r.tau <- matrix(0, ncol(data), ncol(data))
i1 <- seq_len(ncol(data))
for(i in i1) {
for(j in i1) {
if(i != j) {
r.tau[i, j] <- cor(data[, i], data[, j])
}
}
# // just adding print statements for debugging
print(r.tau[i, ])
print(all(setdiff(r.tau[i, ], 0) <= 0.2, na.rm = TRUE))
if(all(setdiff(r.tau[i, ], 0) <= 0.2, na.rm = TRUE)) {
r.tau[i, ] <- 0
break
}
}
Updated
For the updated condition, we need only a single loop and it can be done from reverse sequence
i1 <- rev(seq_len(ncol(Matrix1)))
for(i in i1) {
Matrix1[i, ] <- sqrt(Matrix1[i, ])
if(all(setdiff(Matrix1[i, ], 0) >= 1.6)) {
Matrix1[i:1, ] <- 0
break
}
}
-output
Matrix1
[,1] [,2] [,3] [,4] [,5]
[1,] 0.000000 0.000000 0.000000 0.000000 0
[2,] 0.000000 0.000000 0.000000 0.000000 0
[3,] 0.000000 0.000000 0.000000 0.000000 0
[4,] 1.000000 1.414214 1.414214 1.414214 0
[5,] 1.414214 1.000000 1.000000 1.000000 1
Or if we need a double loop (for other purpose)
i1 <- rev(seq_len(ncol(Matrix1)))
for(i in i1) {
for(j in i1) {
Matrix1[i, j] <- sqrt(Matrix1[i, j])
}
if(all(setdiff(Matrix1[i, j], 0) >= 1.6)) {
Matrix1[i:1, ] <- 0
break
}
}

Conditional combinations matrixes in r

How can I create all binary combinations of matrices with the condition that there can only be a single 1 per column and row. The example will clarify. This particular example must have 6 matrices of combinations, I am showing only the first 2.
c1 <- matrix(c(1, 0, 0, 0, 1, 0, 0, 0, 1), nrow = 3) #First combination
c2 <- matrix(c(0, 1, 0, 1, 0, 0, 0, 0, 1), nrow = 3) #Second combination
What you are asking for is equivalent to finding all permutations of length = n where n = nrow(c1) (or c2 above). Using the FUN argument of permuteGeneral from RcppAlgos (I am the author), we can easily generate the desired outcome:
n <- 3L
myIdentity <- diag(nrow = n)
library(RcppAlgos)
permuteGeneral(n, n, FUN = function(x) myIdentity[x, ])
[[1]]
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
[[2]]
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 0 1
[3,] 0 1 0
[[3]]
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 0
[3,] 0 0 1
[[4]]
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 0 0 1
[3,] 1 0 0
[[5]]
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 1 0 0
[3,] 0 1 0
[[6]]
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 0 1 0
[3,] 1 0 0
There are many other ways of generating the requested output. Most notably, utilizing the tried and true combinat package, we can get a similar result (the output will be in a different order):
combinat::permn(3, fun = function(x) myIdentity[x, ])
Now that we have reduced the problem to simply generating permutations, we can use any of the great packages (arrangements, gtools, multicool, partitions, etc.) for generating permutations to obtain our desired result with the help of lapply:
library(arrangements)
myPerms <- permutations(n)
lapply(1:nrow(myPerms), function(x) myIdentity[myPerms[x,], ])

How do I generate following matrix?

I have solution matrix(say A) to the indefinite equation x1+x2+x3+x4 = 6. Also, I have another matrix(say B) with columns are
0 1 0 1
0 0 1 1
I want to generate matrices using rows of A and the columns of B.
For an example, let (2,0,1,3) is the one solution(one row) of the matrix A. Then, the columns of my new matrix are
0 0 0 1 1 1
0 0 1 1 1 1
Columns of this new matrix are the multiples of columns of B. i.e., first column 2-times, third column 1-time and fourth column 3-times. I want to use this procedure all the rows of matrix A.
use rep:
b <- matrix(c(0, 0, 1, 0, 0, 1, 1, 1), nrow = 2)
a <- c(2, 0, 1, 3)
b[, rep(1:ncol(b), a)]
if a has many rows:
lapply(1:nrow(a), function(i) b[, rep(1:ncol(b), a[i, ])])
> B <- rbind(c(0, 1, 0, 1), c( 0, 0, 1, 1))
> A <- rbind(c(2,0,1,3), c(2,0,1,3))
> do.call(rbind, lapply(1:nrow(A), function(jj) t(sapply(1:nrow(B), function(j) do.call(c, lapply(1:4, function(i) rep(B[j,i], A[jj,i]))) ))))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 1 1 1
[2,] 0 0 1 1 1 1
[3,] 0 0 0 1 1 1
[4,] 0 0 1 1 1 1

R: Generating a sparse matrix with exactly one value per row (dummy coding)

I am trying to generate a sparse matrix in R to represent some dummy-coded variables. Thus, the matrix should have exactly one '1' per row (all other values being zero). So, something like this:
0 0 1 0
1 0 0 0
0 1 0 0
0 0 0 1
Is there a reasonable way to generate such a matrix? The best thing I can come up with is to create j vectors representing each possible line and then sample from those; but that seems a little kludgy. Any better suggestions?
Edit: Here is what I ultimately did; indeed sampled from a list of vectors. The solutions below are, I guess, superior, especially for scaling.
matrix(unlist(sample(list(c(1, 0, 0, 0), c(0, 1, 0, 0), c(0, 0, 1, 0), c(0, 0, 0, 1)),
size=93, replace=TRUE)), 93, 4, byrow=TRUE)
If you wanted to create a random dummy matrix, a quick way would be to create a function like this:
Dummy <- function(nrow, ncol) {
M <- matrix(0L, nrow = nrow, ncol = ncol)
M[cbind(sequence(nrow), sample(ncol, nrow, TRUE))] <- 1L
M
}
The first line of the function just creates an empty matrix of zeroes. The second line uses matrix indexing to replace exactly one value per row with a one. The third line just returns the output. I'm not sure how you were planning on creating/using your j vectors, but this is how I would suggest approaching it....
Usage is simple: You just need to specify the number of rows and the number of columns that the final matrix should have.
Example:
set.seed(1) ## for reproducibility
Dummy(3, 3)
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 1 0
# [3,] 0 1 0
Dummy(6, 4)
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 1 0 0 0
# [3,] 0 0 0 1
# [4,] 0 0 0 1
# [5,] 0 0 1 0
# [6,] 0 0 1 0
You could use model.matrix():
x <- factor(LETTERS[1:4])
model.matrix(~ 0 + x)

Replacing row-values in matrix by its row index

I use a r-matrix (for example [[0,0,0,1],[0,1,0,1],[1,0,0,0],[0,0,1,1]]) representing
a raster. I'd like to replace every value except 0 with its row index value. Is there something like
matrix[matrix==1] <- row_index
so that my result would look like [[0,0,0,1],[0,2,0,2],[3,0,0,0],[0,0,4,4]]?
I am using R 2.15.1 on a Mac (10.7.5) and RPY2 2.2.6 to start the R-Methods.
Or is there any other way to get reasonable results for statistical functions like histogram, chi_square etc.?
For a succinct, expressive solution, I'd be likely to use this:
m <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
nrow = 4, byrow = TRUE)
m[m!=0] <- row(m)[m!=0]
m
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 2 0 2
# [3,] 3 0 0 0
# [4,] 0 0 4 4
Hopefully all hell won't break loose for suggesting a for loop, but we'll see:
Here's your matrix
mymat <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
nrow = 4, byrow = TRUE)
mymat
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 1 0 1
# [3,] 1 0 0 0
# [4,] 0 0 1 1
Here's a for loop that uses basic subsetting to identify the cases you want to replace.
for (i in 1:nrow(mymat)) {
mymat[i, ][mymat[i, ] != 0] <- i
}
Here's the result.
mymat
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 2 0 2
# [3,] 3 0 0 0
# [4,] 0 0 4 4
Maybe I'm missing the point of your question, but how about
> m <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
+ nrow = 4, byrow = TRUE)
> m * 1:nrow(m)
[,1] [,2] [,3] [,4]
[1,] 0 0 0 1
[2,] 0 2 0 2
[3,] 3 0 0 0
[4,] 0 0 4 4
>
(ETA: R fills in matrices by column, and the itemwise product operator makes the two matrices involved conformant by replicating them column by column until they fit. The * operator here winds up multiplying each item by the row to which it belongs.)

Resources