Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a boolean matrix from a matrix

Tags:

r

matrix

stringr

I have the following matrix:

> myletters <- matrix(letters[1:4], ncol = 2)
> myletters
     [,1] [,2]
[1,] "a"  "c" 
[2,] "b"  "d" 

Now I want to check whether there is an "a" or "c" in each cell.

> str_detect(myletters, "[ac]")
[1]  TRUE FALSE  TRUE FALSE

Now I have a logical vector but I want to have a matrix. My desired output would be:

      [,1]  [,2]
[1,]  TRUE  TRUE
[2,] FALSE FALSE

Don't get me wrong, of course I know some possibilities how to come up with this but I think a solution like matrix(str_detect(myletters, "[ac]"), ncol = 2) is quite ugly. There has to be a better way? And I don't know why this happens. What's the difference between this situation and the following where I get my desired output?

> matrix(1:4, ncol = 2) > 2
      [,1] [,2]
[1,] FALSE TRUE
[2,] FALSE TRUE
like image 599
TobiSonne Avatar asked Sep 26 '26 04:09

TobiSonne


2 Answers

One option is

out <- `dim<-`(myletters %in% c("a", "c"), dim(myletters))
out
#      [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

The function `dim<-` does

Retrieve or set the dimension of an object.

like image 134
markus Avatar answered Sep 27 '26 19:09

markus


We can assign it back to get the structure of the original data on the lhs of <-. A matrix is a vector with dim attributes. When we use str_detect, the attributes are lost and thus we get a plain vector.

library(stringr)
out <- myletters
out[] <- str_detect(myletters, "[ac]")
class(out) <- "logical"  
out
#     [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

Or another way to do this on the fly is using structure

structure(str_detect(myletters, "[ac]"), dim = dim(myletters))
#      [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

Or use apply

apply(myletters, 2, str_detect, "[ac]")
#       [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

Or if we need purrr syntax, convert to data.frame and apply map over the columns

library(purrr)
as.data.frame(myletters) %>%
    map_df(str_detect, "[ac]")

When we convert to data.frame, the mutate_all can also be applied

library(dplyr)
as.data.frame(myletters) %>%
      mutate_all(str_detect, "[ac]")
like image 33
akrun Avatar answered Sep 27 '26 20:09

akrun



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!