Ernie Ernie - 2 months ago 6
R Question

Setting matrix values comparing to vector in R

I want to set NA's in every element of a matrix where the value in a column is greater than or equal to the value of a given vector. For example, I can create a matrix:

set.seed(1)
zz <- matrix(data = round(10L * runif(12)), nrow = 4, ncol = 3)


which gives for zz:

[,1] [,2] [,3]
[1,] 8 5 7
[2,] 6 5 1
[3,] 5 10 3
[4,] 9 1 9


and for the comparison vector (for example):

xx <- round(10L * runif(4))


where xx is:

[1] 6 3 8 2


if I perform this operation:

apply(zz,2,function(x) x >= xx)


I get:

[,1] [,2] [,3]
[1,] TRUE FALSE TRUE
[2,] TRUE TRUE FALSE
[3,] FALSE TRUE FALSE
[4,] TRUE FALSE TRUE


What I want is everywhere I have a TRUE element I want an NA and everywhere I have a FALSE I get the number in the zz matrix (e.g., manually ...):

NA 5 NA
NA NA 1
5 NA 3
NA 1 NA


I can cobble together some "for" loops to do what I want, but is there a vector-based way to do this??

Thanks for any tips.

Answer

Here is one option to get the expected output. We get a logical matrix (zz >= xx), using NA^ on that returns NA for the TRUE values and 1 for the FALSE, then multiply it with original matrix 'zz' so that NA remains as such while the 1 changes to the corresponding value in 'zz'.

NA^(zz >= xx)*zz
#     [,1] [,2] [,3]
#[1,]   NA    5   NA
#[2,]   NA   NA    1
#[3,]    5   NA    3
#[4,]   NA    1   NA

Or another option is ifelse

ifelse(zz >= xx, NA, zz)

data

zz <- structure(c(8, 6, 5, 9, 5, 5, 10, 1, 7, 1, 3, 9), .Dim = c(4L, 3L))
xx <- c(6, 3, 8, 2)
Comments