【问题标题】:how do I filter using dplyr for list of character strings ignoring numbers after a decimal place如何使用 dplyr 过滤字符串列表,忽略小数点后的数字
【发布时间】:2020-09-03 23:37:04
【问题描述】:

我在名为“id”的 data.frame 中有以下列:

   example_0test0|EMM3.71|NTERM| 
   example_0test1|_EMM92.2|CTERM| 
   example_0test2|_EMM92.2|NTERM| 
   example_0test0|EMM1|NTERM| 
   example_0test0|EMM100|NTERM| 
   example_0test0|EMM1.11|NTERM| 
   example_0test0|EMM1.123|NTERM| 

我想使用 dplyr 过滤器函数过滤精确字符列表,例如(保持简单):EMM1,以提供以下输出:

> test_df2
                              id col1 col2
1     example_0test0|EMM1|NTERM| 10.4 exp4
2  example_0test0|EMM1.11|NTERM| 10.3 exp6
3 example_0test0|EMM1.123|NTERM| 10.3 exp7

我有一个像这样保存的字符的因子列表,我想用作过滤术语的输入:

"EMM1|EMM101|EMM103|EMM104|EMM108.1|EMM11|EMM113|EMM114|EMM116.1|EMM118|EMM12|EMM123|EMM19.4|EMM197|EMM2|"

我尝试过使用“filter”和“str_detect”的组合,但如果我的搜索列表包含“EMM1”,我想包含“EMM1.0”或“EMM1.1”之类的内容

我怀疑列中的每个 EMM 术语都包含在“|”中比如 "text|EMM1.0|text" 有没有办法用它来过滤?

这是我正在使用的 data.frame 类型的一个小例子:

> dput(test_df)
structure(list(id = c("example_0test0|EMM3.71|NTERM|", "example_0test1|_EMM92.2|CTERM|", 
"example_0test2|_EMM92.2|NTERM|", "example_0test0|EMM1|NTERM|", 
"example_0test0|EMM100|NTERM|", "example_0test0|EMM1.11|NTERM|", 
"example_0test0|EMM1.123|NTERM|"), col1 = c(10.1, 10.2, 10.3, 
10.4, 10.3, 10.3, 10.3), col2 = c("exp1", "exp2", "exp3", "exp4", 
"exp5", "exp6", "exp7")), class = "data.frame", row.names = c(NA, 
-7L))

【问题讨论】:

  • 已编辑帖子。请记住,上面的预期输出是过滤一个术语“EMM1”以返回所有包含“EMM1”、“EMM1.11”等内容的内容,但实际上我有数百个需要过滤,就像问题中的因子列表一样...谢谢
  • 我下面的解决方案是给出你显示的预期输出
  • 我更新了解决方案。可能会有所帮助
  • subset(test_df, grepl(pat, id)) 不起作用? patpat <- "EMM1|EMM101|EMM103|EMM104|EMM108.1|EMM11|EMM113|EMM114|EMM116.1|EMM118|EMM12|EMM123|EMM19.4|EMM197|EMM2" 哪里?
  • @RonakShah 这给出了以 EMM1 开头的所有内容,例如 emm106.9 EMM109.0 等,但这是我所追求的那种东西

标签: r dplyr


【解决方案1】:

你可以使用:

pat <- "EMM1|EMM101|EMM103|EMM104|EMM108.1|EMM11|EMM113|EMM114|EMM116.1|EMM118|EMM12|EMM123|EMM19.4|EMM197|EMM2"
subset(test_df, grepl(sprintf('(%s)(\\.|\\|)', pat), id))


#                              id col1 col2
#4     example_0test0|EMM1|NTERM| 10.4 exp4
#6  example_0test0|EMM1.11|NTERM| 10.3 exp6
#7 example_0test0|EMM1.123|NTERM| 10.3 exp7

pat 包含我们想要的所有"EMM" 值,另外我们使用sprintf 创建一个模式,仅返回那些在pat 值之后具有".""|" 的值。


我们也可以将它与filterstr_detect 类似地使用。

library(dplyr)
library(stringr)

test_df %>% filter(str_detect(id, sprintf('(%s)(\\.|\\|)', pat)))

【讨论】:

    【解决方案2】:

    我们可以使用str_detect

    library(dplyr)
    library(stringr)
    test_df %>% 
        filter(str_detect(id, "EMM1\\||(EMM1\\.\\d+)"))
    #                              id col1 col2
    #1     example_0test0|EMM1|NTERM| 10.4 exp4
    #2  example_0test0|EMM1.11|NTERM| 10.3 exp6
    #3 example_0test0|EMM1.123|NTERM| 10.3 exp7
    

    如果我们基于另一个表中的列进行过滤,我们可以删除 . 和后面的数字

    patvec <- sub("\\.\\d+$", "", df2$id)
    i1 <- Reduce(`|`, lapply(paste0(patvec, "\\||(", patvec, "\\.\\d+)"),
          function(pat),
             grepl(pat, test_df$id)))
    subset(test_df, i1)
    

    【讨论】:

    • 这看起来像问题中简单示例的预期输出,但我想过滤数百个类似的术语,所以像“EMM1\\||”一样输入它们等是行不通的。谢谢
    • @reubenmcg 在你的模式列表中,它也显示为EMM100,所以,当描述说不匹配“EMM100”时我不清楚
    • 我已经删除了这个问题的艺术,我可以看到它是多么令人困惑。对不起
    • 我不确定你的意思。我现在也从字符串中删除了 EMM100。因此,即使您使用问题中的示例字符串来过滤示例 data.frame,我仍然希望在问题中取回相同的预期输出表。
    • 嗯,如果我还没有字符串,我知道这会有什么帮助。但是可以说我想使用提供的字符串来过滤提供的 data.table。因此,使用您答案的第一个 parr,但我不想用 \\|| 键入所有单个 EMM等
    【解决方案3】:

    或者你可以使用基本 R 方法

     df[grepl("EMM1(\\.\\d{1,})|EMM1\\|", df$id),]
     #                          id col1 col2
     # 4     example_0test0|EMM1|NTERM| 10.4 exp4
     # 6  example_0test0|EMM1.11|NTERM| 10.3 exp6
     # 7 example_0test0|EMM1.123|NTERM| 10.3 exp7
    
    • EMM1(\\.\\d{1,}):用点和数字捕获组 EMM1

    【讨论】:

    • 再次进行这种工作,并使用给出的示例,但如问题中所述,我有一个 19 个“EMM”的列表来过滤(如“pat”中所示)并且不要不想每次都打出来?
    猜你喜欢
    • 1970-01-01
    • 2014-07-15
    • 2017-05-10
    • 2021-12-27
    • 1970-01-01
    • 2021-06-16
    • 2020-05-01
    • 2020-08-15
    • 1970-01-01
    相关资源
    最近更新 更多