R过滤包含特定词语组合的行

5

我正在处理文本数据,正在寻找解决过滤问题的方案。

我已经找到了一个解决方案,该方案可以过滤包含'Word 1' 或者 'Word 2'的行。

以下是可再现的代码:

df=data.frame(UID=c(1,2,3,4,5),Text=c("the quick brown fox jumped over the lazy dog",
                                 "long live the king",
                                 "I love my dog a lot",
                                 "Tomorrow will be a rainy day",
                                 "Tomorrow will be a sunny day"))


#Filter for rows that contain "brown" OR "dog"
filtered_results_1=dplyr::filter(df, grepl('brown|dog', Text))

然而,当我筛选同时包含'Word 1'和'Word 2'的行时,它不起作用。

#Filter for rows that contain "brown" AND "dog"
filtered_results_2=dplyr::filter(df, grepl('brown & dog', Text))

无法确定正确的语法,需要帮助,谢谢。

5个回答

5
您可以使用 stringr::str_count 函数:
dplyr::mutate(df, test = stringr::str_count(Text,'brown|dog'))
#   UID                                         Text test
# 1   1 the quick brown fox jumped over the lazy dog    2
# 2   2                           long live the king    0
# 3   3                          I love my dog a lot    1
# 4   4                 Tomorrow will be a rainy day    0
# 5   5                 Tomorrow will be a sunny day    0

dplyr::filter(df, stringr::str_count(Text,'brown|dog') == 2)
#   UID                                         Text
# 1   1 the quick brown fox jumped over the lazy dog

它会计算dogbrown出现的次数。

以下方法比较通用,虽然不太优雅,但你可以方便地将搜索词放入一个向量中:

dplyr::filter(df, purrr::map_int(strsplit(as.character(Text),'[[:punct:] ]'),
               ~sum(unique(.) %in% c("brown","dog"))) == 2)

#   UID                                         Text
# 1   1 the quick brown fox jumped over the lazy dog

1
我在想,如果一个字符串中有两个“dog”,那么这会被计算为2吗? - BENY
啊,是的,它确实会,但这个解决方案并不通用,你发现得很好。 - moodymudskipper

3

我们可以使用双重的 grepl

dplyr::filter(df, grepl('\\bbrown\\b', Text) & grepl('\\bdog\\b', Text))

或者使用条件,在检查单词'brown'后面跟着单词'dog'(注意单词边界\\b以确保它不会匹配其他任何东西),或者是'dog'后面跟着'brown'。
dplyr::filter(df, grepl("\\bbrown\\b.*\\bdog\\b|\\bdog\\b.*\\bbrown\\b", Text))
#   UID                                         Text
#1   1 the quick brown fox jumped over the lazy dog

注意:它检查单词边界,字符串中同时存在'brown'和'dog'两个单词


也可以使用基础R实现

subset(df, grepl("\\bbrown\\b.*\\bdog\\b|\\bdog\\b.*\\bbrown\\b", Text))

1
尝试这个解决方案:

filtered_results_2=dplyr::filter(df, grepl('brown.*dog|dog.*brown', Text))
filtered_results_2
  UID                                         Text
1   1 the quick brown fox jumped over the lazy dog

1
使用 sqldf
library(sqldf)
sqldf("select * from df where Text like '%dog%' AND Text like '%brown%'")

输出:

    UID                                         Text
     1   1 the quick brown fox jumped over the lazy dog

1
与之前的答案类似,但使用base
df[grepl("(?=.*dog)(?=.*brown)", df$Text, perl = TRUE),]
  UID                                         Text
1   1 the quick brown fox jumped over the lazy dog

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