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
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.
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]")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With