rshraim
rshraim

Reputation: 15

Fill logical matrix with values from list

My question is about filling in values by logical selection. I have a matrix

> mymat
               test
sample      1     2     3     4     5
  1sample FALSE FALSE  TRUE FALSE FALSE
  2sample FALSE FALSE  TRUE  TRUE FALSE
  3sample  TRUE FALSE FALSE FALSE FALSE
  4sample FALSE FALSE FALSE FALSE FALSE
  5sample FALSE FALSE FALSE FALSE FALSE

and a list of values

> mylist
[[1]]
[1] "a"

[[2]]
[1] "b"

[[3]]
[1] "c"

[[4]]
[1] "d"

[[5]]
[1] "e"

I need to fill in the matrix (or create new data structure) where the element from the nth list is matched to the nth column in the matrix as many times as the row value is TRUE so the resulting data would look like this:

> mymat
               test
sample      1   2    3     4     5
  1sample <NA> <NA>  c   <NA> <NA>
  2sample <NA> <NA>  c    d   <NA>
  3sample    a <NA> <NA> <NA> <NA>
  4sample <NA> <NA> <NA> <NA> <NA>
  5sample <NA> <NA> <NA> <NA> <NA>

Upvotes: 1

Views: 123

Answers (3)

lmo
lmo

Reputation: 38500

Another alternative using matrix indexing is

# construct matrix of NAs
myMat2 <- myMat * NA
# fill in letter values
myMat2[myMat] <- unlist(mylist)[myMat * col(myMat)]

data

myMat <- 
structure(c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(5L, 
5L))
mylist <- as.list(letters[1:5])

Upvotes: 1

akrun
akrun

Reputation: 887078

Here is an option using replace

dim<-`(replace(unlist(mylist)[col(mymat)], !mymat, NA), dim(mymat))
#   [,1] [,2] [,3] [,4] [,5]
#[1,] NA   NA   "c"  NA   NA  
#[2,] NA   NA   "c"  "d"  NA  
#[3,] "a"  NA   NA   NA   NA  
#[4,] NA   NA   NA   NA   NA  
#[5,] NA   NA   NA   NA   NA  

Or if we need to change the mymat

mymat[] <- replace(unlist(mylist)[col(mymat)], !mymat, NA)
mymat
#         test
#sample    1   2  3   4   5 
#  1sample NA  NA "c" NA  NA
#  2sample NA  NA "c" "d" NA
#  3sample "a" NA NA  NA  NA
#  4sample NA  NA NA  NA  NA
#  5sample NA  NA NA  NA  NA

Upvotes: 3

Cath
Cath

Reputation: 24074

You can change your list into a matrix and replace with the value in the matrix when appropriate.

mylist_mat <-  matrix(rep(unlist(mylist), each=nrow(mymat)), ncol=ncol(mymat))
res_mat <- matrix(NA, ncol=ncol(mymat), nrow=nrow(mymat))
res_mat[mymat] <- mylist_mat[mymat]
res_mat
#     [,1] [,2] [,3] [,4] [,5]
#[1,] NA   NA   "c"  NA   NA  
#[2,] NA   NA   "c"  "d"  NA  
#[3,] "a"  NA   NA   NA   NA  
#[4,] NA   NA   NA   NA   NA  
#[5,] NA   NA   NA   NA   NA 

Upvotes: 3

Related Questions