从一个矩阵创建一个布尔矩阵

3

我有以下矩阵:

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

现在我想检查每个单元格中是否有"a"或"c"。

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

现在我有一个逻辑向量,但我想要一个矩阵。我的期望输出是:
      [,1]  [,2]
[1,]  TRUE  TRUE
[2,] FALSE FALSE

别误会,我当然知道一些可能的方法来解决这个问题,但我认为像matrix(str_detect(myletters, "[ac]"), ncol = 2)这样的解决方案相当丑陋。肯定有更好的方法吧? 而我不知道为什么会发生这种情况。以下是我得到期望输出的情况与上述情况之间的区别在哪里?

> matrix(1:4, ncol = 2) > 2
      [,1] [,2]
[1,] FALSE TRUE
[2,] FALSE TRUE

myletters == "a" | myletters == "c" 对于示例矩阵起作用。 - G. Grothendieck
3个回答

2

一种选择是

out <- `dim<-`(myletters %in% c("a", "c"), dim(myletters))
out
#      [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE
`dim<-`函数用于检索或设置对象的维度。

1
我们可以将其重新分配回来,以获取左侧<-的原始数据结构。一个矩阵是一个带有dim属性的向量。当我们使用str_detect时,属性会丢失,因此我们得到一个普通的向量。
library(stringr)
out <- myletters
out[] <- str_detect(myletters, "[ac]")
class(out) <- "logical"  
out
#     [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

或者另一种即时实现的方法是使用structure

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

或者使用apply
apply(myletters, 2, str_detect, "[ac]")
#       [,1]  [,2]
#[1,]  TRUE  TRUE
#[2,] FALSE FALSE

或者如果我们需要使用purrr语法,将其转换为data.frame并在列上应用map

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

当我们转换为 data.frame 时,也可以应用 mutate_all
library(dplyr)
as.data.frame(myletters) %>%
      mutate_all(str_detect, "[ac]")

谢谢!我喜欢使用apply的方式。你知道我怎么用purrr函数实现这个吗?通常我更喜欢它们而不是apply家族。 - TobiSonne
1
@TobiSonne,Thee purrr家族的map函数可以循环遍历数据框的列。在这里,它是一个矩阵,所以你可能需要将其转换为data.frametibble,例如as.data.frame(myletters) %>% map_df(str_detect, "[ac]") - akrun
1
哦,当然!我的数据最初是一个 data.frame,所以这个解决方案甚至更好!感谢您的绝佳答案! - TobiSonne

0

类似于@akrun提供的apply解决方案,这里是一个使用base R、结合apply()grepl()的解决方案。

apply(myletters, 2, function(v) grepl("[ac]",v))

这提供了

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接