应用函数超过2个字符向量返回列表 - purrr

时间:2016-01-03 06:51:41

标签: r string sapply

我正在使用purrr做一些工作,并希望针对此问题提供完整的管道解决方案。我正在使用sapply,但认为这不是最佳解决方案。它适用于这个小型演示,但在实际数据中,ch1的长度大于50,000,而ch2大于100。

library(stringr)
library(purrr)

ch1 <- c("something very interesting or perhaps it is not", "lions, tigers and elephants are safari animals", "once upon a time there was a big castle",
         "I have not seen anything as a big as elephants")

ch2 <- c("big", "not")

对于ch2的每个元素,我们希望看到它们是否出现在ch1的每个元素中。

str_detect(ch1, ch2[1]) # FALSE FALSE  TRUE  TRUE
str_detect(ch1, ch2[2]) # TRUE FALSE FALSE  TRUE

尝试使用purrr在所有ch1上应用函数:

ch1 %>% map_lgl(str_detect(., ch2[2]))  # TRUE FALSE FALSE  TRUE

我可以使用ch2

为整个sapply执行此操作
sapply(ch2, function(x) ch1 %>% map_lgl(str_detect(., x)))

      big   not
[1,] FALSE  TRUE
[2,] FALSE FALSE
[3,]  TRUE FALSE
[4,]  TRUE  TRUE

然而,对于真实的数据集,我认为必须有一个完整的purrr解决方案 - 比如使用map2,即使用两个列表 - 但很明显它不能成为特定的一个它需要相同长度的列表。

1 个答案:

答案 0 :(得分:1)

以下内容在大型数据集上可能比帖子中的代码快一些,会返回一个向量列表。

library(stringr)
library(purrr
lst <- ch2 %>% split(ch2) %>% 
  map( ~ str_detect(ch1, .x))

要返回矩阵,您可以使用以下内容:

mat <- ch2 %>% split(ch2) %>% 
      map( ~ str_detect(ch1, .x)) %>%
      map_call(cbind)

但是,由于map_call只是do.call的一个瘦包装,因此可能有点慢。如果您可以使用dplyr并使用data.frame作为结果,则可能会更快一些:

library(dplyr)
df <- ch2 %>% split(ch2) %>% 
      map( ~ str_detect(ch1, .x)) %>%
      as_data_frame() 

<强>加

以下是使用map2

生成带有命名列的矩阵的解决方案
# solution using map2
mat2 <- ch1 %>% list %>%
        map2(ch2,  ~ str_detect(.x, .y)) %>%
        map_call(cbind)
colnames(mat2) <- ch2

产生具有列名称的矩阵的最直接的可能是:

names(ch2) <- ch2
mat3 <- ch2 %>% map( ~ str_detect(ch1, .x)) %>% 
        map_call(cbind)