I have an example dataframe s1
s1=data.frame(c1=c("red","green","blue","yellow","orange","black","white"),col1=c("car1","car2","car3","car4","car5","car6","car7"))
s1=s1 %>% remove_rownames %>% column_to_rownames(var="c1")
There is only one column-col1 and the row names are red,green, blue and so on.
col1
red car1
green car2
blue car3
yellow car4
orange car5
black car6
white car7
I also have a matrix containg only 1' and 0's
m1= matrix(c(1,0,0,1,0),nrow =7, ncol =3, byrow = TRUE)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 1 0 1
[3,] 0 0 1
[4,] 0 1 0
[5,] 0 1 0
[6,] 1 0 0
[7,] 1 0 1
I want to create a list such that each element of the list contains the row names of s1, only if the corresponding element of the matrix is 1. I need to iterate this over all columns of the matrix.
the output should looks something like this
l1=list(c("red","green","black","white"),c("yellow","orange"),c("green","blue","white"))
I tried using this code but i was unable to apply it to every column
row.names(s1)[which(m1[,1]==1)]
Note that both the actual dataframe and matrix are much bigger. Thank you!
CodePudding user response:
Split by columns of 'm1' with asplit
on a logical matrix and use the index for subsetting the rownames of 's1'
lapply(asplit(m1 == 1, 2), function(x) row.names(s1)[x])
-output
[[1]]
[1] "red" "green" "black" "white"
[[2]]
[1] "yellow" "orange"
[[3]]
[1] "green" "blue" "white"
Or use apply
with MARGIN=2
to loop over the columns and subset
apply(m1==1, 2, function(x) row.names(s1)[x])
CodePudding user response:
A more primitive and involved solution:
l1 <- ifelse(m1==1, rownames(s1), '') %>%
t() %>%
split(seq(nrow(.))) %>%
lapply(\(x){x[x!='']})
l1
$`1`
[1] "red" "green" "black" "white"
$`2`
[1] "yellow" "orange"
$`3`
[1] "green" "blue" "white"