查找字符串列表的每个元素与R中向量的每个字符串之间的匹配(避免'for')

时间:2017-06-02 15:50:34

标签: r list for-loop vector grepl

我在数据框中有两列我想要比较的字符串。第一个是字符串向量,第二个是每个元素中带有迷你向量字符串的列表。想象一下有这样一个数据框:

    V                 L 
"Anameone"     "name" "asd" 
"Bnametwo"         "dfg"
"Cnamethree"   "hey" "C" "hi"

我想看看L的第一个元素中的某些单词是否出现在V的第一个元素中,如果L的第二个元素中的某些单词出现在V的第二个元素中......所以上。

我可以用这样的循环做我想要的事情:

for (i in c(1:3)){ df$matches[i] <- any(df$L[[i]],grepl, df$V[i],ignore.case = T)) }

因此输出为:

> df$matches
[1] "TRUE"  "FALSE" "TRUE"

但实际上我有大约100.000而不是3行,确实需要太长时间。我无法弄清楚如何更有效地完成这项工作,任何想法?我没有使用索引的所有其他尝试最终都得到了本例中的矩阵3x3,因为它比较了“all with all”,我认为这可能比for更糟糕。

3 个答案:

答案 0 :(得分:1)

这样的东西?

df <- data.frame(V = c('Anameone','Bnametwo','Cnamethree'),
                 L = I(list(c('name','asd'),c('dfg'),c('hey','C','hi'))))

sapply(1:nrow(df), function(x) any(sapply(df$L[[x]], function(y) grepl(y, df$V[x]))))
# [1]  TRUE FALSE  TRUE

答案 1 :(得分:0)

sapply应该工作:

df<-data.frame(V=c("Anameone","Bnametwo","Cnamethree"),
           L=I(list(c("name","asd"),"dfg",c("hey","C","hi"))))


sapply(as.character(df$V),function(x)

{grepl(paste(unlist(df$L[1]),collapse="|"),x)})

您必须检查它是否比使用for循环更快。我无法再创造你的榜样。

答案 2 :(得分:0)

您可以使用purrr::map2_lgl()对这两列进行迭代,测试l的每个元素是否在vstringr::str_detect(),然后使用any()来如果有任何匹配,请获取TRUEFALSE

library(dplyr)
library(purrr)
library(stringr)

df <- tibble(
  v = c("Anameone", "Bnametwo", "Cnamethree"),
  l = list(c("name", "asd"), "dfg", c("hey", "C", "hi"))
)

mutate(df, matches = map2_lgl(v, l, ~ str_detect(.x, .y) %>% any()))

#> # A tibble: 3 x 3
#>            v         l matches
#>        <chr>    <list>   <lgl>
#> 1   Anameone <chr [2]>    TRUE
#> 2   Bnametwo <chr [1]>   FALSE
#> 3 Cnamethree <chr [3]>    TRUE