首页 > 解决方案 > R dplyr:通过向量定义的多个正则表达式过滤数据

问题描述

我有一个数据框,我想从中选择重要的列,然后过滤行以包含特定的结尾。

正则表达式使使用xx$符号定义我的结束值变得简单。但是,如何改变多个可能的结尾(xx$, yy$)?

虚拟示例:

require(dplyr)

x <- c("aa", "aa", "aa", "bb", "cc", "cc", "cc")
y <- c(101, 102, 113, 201, 202, 344, 407)
type = rep("zz", 7)
df = data.frame(x, y, type)    

# Select all expressions that starts end by "7"
df %>%
  select(x, y) %>%
  filter(grepl("7$", y))

# It seems working when I explicitly define my variables, but I need to use it as a vector instead of values?
df %>%
  select(x, y) %>%
  filter(grepl("[2|7]$", y))  # need to modify this using multiple endings


# How to modify this expression, to use vector of endings (ids) instead?
ids = c(7,2)     # define vector of my values

df %>%
     select(x, y) %>%
     filter(grepl("ids$", y))  # how to change "grepl(ids, y)??"

预期输出:

   x   y type
1 aa 102   zz
2 cc 202   zz
3 cc 407   zz

基于此问题的示例:正则表达式 (RegEx) 和 dplyr::filter()

标签: rregexdplyr

解决方案


您可以使用

df %>% 
  select(x, y) %> filter(grepl(paste0("(?:", paste(ids, collapse="|"), ")$"), y))

paste0("(?:", paste(ids, collapse="|"), ")$")部分将构建一个交替模式,由于末尾的$锚点,该模式仅在字符串的末尾匹配。

注意:如果值可以具有特殊的正则表达式元字符,则需要先转义字符向量中的值:

regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
df %>% 
      select(x, y) %> filter(grepl(paste0("(?:", paste(regex.escape(ids), collapse="|"), ")$"), y))
                                                       ^^^^^^^^^^^^^^^^^

例如,paste0("(?:", paste(c("7", "8", "ids"), collapse="|"), ")$")输出 (?:7|8|ids)$

  • (?:- 一个非捕获组的开始,它将作为备选方案的容器,以便$锚应用于所有备选方案,而不仅仅是最后一个,匹配任何一个
    • 7- 一个7字符
  • |- 或者
  • 8- 一个8字符
  • |- 或者
  • ids- 一个ids子串
  • )- 小组结束
  • $- 字符串的结尾。

推荐阅读