【问题标题】:grepl in R to find matches to any of a list of character stringsR中的grepl查找与任何字符串列表的匹配项
【发布时间】:2014-08-19 19:57:31
【问题描述】:

是否可以在引用值列表时使用 grepl 参数,也许使用 %in% 运算符?我想获取下面的数据,如果动物名称中有“狗”或“猫”,我想返回一个特定的值,比如“keep”;如果它没有“狗”或“猫”,我想返回“丢弃”。

data <- data.frame(animal = sample(c("cat","dog","bird", 'doggy','kittycat'), 50, replace = T))

现在,如果我只是通过严格匹配值来做到这一点,比如“猫”和“狗”,我可以使用以下方法:

matches <- c("cat","dog")

data$keep <- ifelse(data$animal %in% matches, "Keep", "Discard")

但使用 grep 或 grepl 仅指列表中的第一个参数:

data$keep <- ifelse(grepl(matches, data$animal), "Keep","Discard")

返回

Warning message:
In grepl(matches, data$animal) :
  argument 'pattern' has length > 1 and only the first element will be used

注意,我在搜索中看到了这个帖子,但这似乎不起作用: grep using a character vector with multiple patterns

【问题讨论】:

  • 如果您离开 unique,我认为 Brian Diggs 对链接问题的回答提供了所需的代码。和beginneR的回答基本一样。
  • 当你使用像sample这样没有set.seed的函数时,它不被认为是一个可重现的例子

标签: r regex grepl


【解决方案1】:

您可以在grepl 的正则表达式中使用“或”(|) 语句。

ifelse(grepl("dog|cat", data$animal), "keep", "discard")
# [1] "keep"    "keep"    "discard" "keep"    "keep"    "keep"    "keep"    "discard"
# [9] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "discard" "keep"   
#[17] "discard" "keep"    "keep"    "discard" "keep"    "keep"    "discard" "keep"   
#[25] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"   
#[33] "keep"    "discard" "keep"    "discard" "keep"    "discard" "keep"    "keep"   
#[41] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"   
#[49] "keep"    "discard"

正则表达式dog|cat 告诉正则表达式引擎查找"dog""cat",并返回两者的匹配项。

【讨论】:

    【解决方案2】:

    不确定您尝试了什么,但这似乎有效:

    data$keep <- ifelse(grepl(paste(matches, collapse = "|"), data$animal), "Keep","Discard")
    

    与您链接到的答案类似。

    诀窍是使用粘贴:

    paste(matches, collapse = "|")
    #[1] "cat|dog"
    

    因此它创建了一个包含 dog 或 cat 的正则表达式,并且还可以处理一长串模式而无需输入每个模式。

    编辑:

    如果您稍后根据“保留”和“丢弃”条目对 data.frame 进行子集化,您可以更直接地使用:

    data[grepl(paste(matches, collapse = "|"), data$animal),]
    

    这样,grepl 的结果为 TRUE 或 FALSE 将用于子集。

    【讨论】:

    • 感谢您使用结果作为索引,解决了我长期以来的烦恼!
    【解决方案3】:

    尽量避免ifelse。例如,这很好用

    c("Discard", "Keep")[grepl("(dog|cat)", data$animal) + 1]
    

    对于123 种子,您将获得

    ##  [1] "Keep"    "Keep"    "Discard" "Keep"    "Keep"    "Keep"    "Discard" "Keep"   
    ##  [9] "Discard" "Discard" "Keep"    "Discard" "Keep"    "Discard" "Keep"    "Keep"   
    ## [17] "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"   
    ## [25] "Keep"    "Keep"    "Discard" "Discard" "Keep"    "Keep"    "Keep"    "Keep"   
    ## [33] "Keep"    "Keep"    "Keep"    "Discard" "Keep"    "Keep"    "Keep"    "Keep"   
    ## [41] "Keep"    "Discard" "Discard" "Keep"    "Keep"    "Keep"    "Keep"    "Discard"
    ## [49] "Keep"    "Keep"   
    

    【讨论】:

    • set.seed(123) 为随机生成器播种。
    • @RichardScriven,因为 OP 使用 sample 提供了他的数据集,因此我无法提供他可以在不设置种子的情况下验证的输出
    • @DavidArenburg,为什么要避免“ifelse”?
    • @MarcTulla,因为ifelse(虽然是矢量化的)相对较慢,尤其是在嵌入多个ifelse 语句的情况下。因此,如果我可以轻松避免它,我更喜欢这样做。虽然我猜这是个人选择
    • @DavidArenburg,这是有道理的,我注意到它会减慢速度,尤其是在大数据集上。如果我确实需要执行“ifelse”类型的操作,下面是 beginneR 的首选方法吗?类似于:data[grepl(paste(matches, collapse = "|"), data$animal),]
    猜你喜欢
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多