【问题标题】:filtering some strings but some of them not! with grepl过滤一些字符串,但其中一些没有!用 grepl
【发布时间】:2017-10-30 06:22:39
【问题描述】:

我正在尝试过滤数据中的一些字符串。例如,我想过滤掉“AxxBy”字符串,但我想保留这个字符串“AxxByy”! x 和 y 代表位数!

这是我尝试过的,

data <- data.frame(pair=paste(paste('A',c(seq(1:4),10,11),sep=''),paste('B',c(2,3,4,22,33,44),sep=''),sep='')) 
    pair
1   A1B2
2   A2B3
3   A3B4
4  A4B22
5 A10B33
6 A11B44

我想删除那些以 A1 开头但不是 A10 和 A11 的对。与 B2 相同,但保留 B22!等等

x <- c(paste('A',1,sep=''), paste('B',2,sep='')) # filtering conditions

library(dplyr)
df <- data%>%
  filter(!grepl(paste(x,collapse='|'),pair))

 pair
1 A2B3
2 A3B4

在这篇文章中Filtering observations in dplyr in combination with grepl 可以通过正则表达式函数添加以"^x|xx$" 开头的行,但如果过滤条件在管道之外定义,我还没有看到任何帖子。

预期输出

  pair
    1   A2B33
    2   A3B4
    3   A4B22
    4   A10B33
    6   A11B44

规则的要点是;如果 'A' 后面有两位数,则将 B 放入 AxxB 和 !grepl x 输入中定义的 xx 数字的所有内容。如果只有 'B' 并且一个数字是 'By' 给出 !grepl 'By$' 而不是 'Byy' 输入。当然,这包括 'AxBy$' 和 'AxxBy$' 仅此而已。我仍然无法概括@alistaire 解决方案!

【问题讨论】:

  • 过滤掉对的规则是什么?它只是“A1”和“B2”,即那些特定的字母与那些特定的数字配对吗?在您的解释中,您似乎说您希望过滤掉 B22 并保留 B2,但是您的预期输出显示相反。
  • @Marius 规则很简单。根据x 中的决定,删除以A1 开头的字符串,但不删除A10B2 相同的内容。对不起,我重新编辑了 OP。谢谢指正。
  • @Marius 的问题仍然是一个很好的问题:规则是什么。大概,您不只有这 6 个条目。它们都是A(一些数字)B(一些数字)的形式吗?你真的只想消除 A1B(anything) 和 A(numbers)B2
  • data %&gt;% filter(!grepl('A1B|B2$', pair))?您的示例与您的示例数据不符。
  • 所以折叠你的模式:paste0(x, ifelse(grepl('A', x), 'B', '$'), collapse = '|')

标签: r filter dplyr grepl


【解决方案1】:

OP 已要求 过滤掉“AxxBy”字符串,但希望保留字符串“AxxByy”(其中“x”和“y”表示数字。

通常,指定要保留的内容比指定要删除的内容更容易。保留遵守模式“AxxByy”的字符串正则表达式

"^A\\d{2}B\\d{2}$"

可用于^ 表示字符串的开头,\\d{2} 正好是两个数字的序列,$ 表示字符串的结尾。 AB 代表他们自己。

有了这个正则表达式,dplyrgrepl()可以用来过滤输入数据框DF

library(dplyr)
#which rows are kept?
kept <- DF %>%
+   filter(grepl("^A\\d{2}B\\d{2}$", pair))
kept
#    pair
#1 A10B33
#2 A11B44

# which rows are removed?
removed <- DF %>%
+   filter(!grepl("^A\\d{2}B\\d{2}$", pair))
removed
#      pair
#1     A1B2
#2     A2B3
#3     A3B4
#4    A4B22
#5       AB
#6        A
#7        B
#8       A1
#9      A12
#10      B1
#11     B12
#12 AA12B34
#13 A12BB34

请注意,我添加了一些用于演示的边缘案例。


顺便说一句:如果只需要过滤矢量pair,则不需要dplyr。因此,在基础 R 中,替代表达式

pair[grepl("^A\\d{2}B\\d{2}$", pair)]
grep("^A\\d{2}B\\d{2}$", pair, value = TRUE)

都返回要保留的字符串:

[1] "A10B33" "A11B44"

同时

pair[!grepl("^A\\d{2}B\\d{2}$", pair)]

返回删除的字符串:

 [1] "A1B2"    "A2B3"    "A3B4"    "A4B22"   "AB"      "A"       "B"       "A1"     
 [9] "A12"     "B1"      "B12"     "AA12B34" "A12BB34"

数据

由 OP 给出,但附加了一些边缘情况:

# create vector of test patterns using paste0() instead of paste(..., sep = "")
pair <- paste0("A", c(1:4, 10, 11), "B", c(2, 3, 4, 22, 33, 44))
# alternatvely use sprintf()
pair <- sprintf("A%iB%i", c(1:4, 10, 11), c(2, 3, 4, 22, 33, 44))
# add some edge cases
pair <- append(pair, c("AB", "A", "B", "A1", "A12", "B1", "B12", "AA12B34", "A12BB34"))
# create data frame
DF <- data.frame(pair)
DF
#      pair
#1     A1B2
#2     A2B3
#3     A3B4
#4    A4B22
#5   A10B33
#6   A11B44
#7       AB
#8        A
#9        B
#10      A1
#11     A12
#12      B1
#13     B12
#14 AA12B34
#15 A12BB34

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 2022-09-28
    • 1970-01-01
    相关资源
    最近更新 更多