【问题标题】:How to subset a dataframe using multiple regular expressions in variable names?如何使用变量名中的多个正则表达式对数据框进行子集化?
【发布时间】:2019-08-29 07:23:39
【问题描述】:

我有一个包含 500 多个命名变量的数据框,我只想选择名称包含字符串“xyz”和“abc”的列。第一个字母有时大写,有时不大写,所以我使用正则表达式“[Aa]bc”等。

我在一个名为 df 的数据框中拥有完整的数据集,我正在通过使用 grep() 从 df 中选择变量来构建一个名为 df2 的新数据框。我可以一次做一个,然后用 cbind() 将它们粘在一起,但我想知道如何一次性完成所有操作。

我以为我可以将多个条件传递给 grep(),但似乎卡在了这里。

一个非常简单的例子:

df <- data.frame(abc=1:3, def=4:6, Xyz=7:9, Abc=10:12, xyz=13:15)

  abc def Xyz Abc xyz
1   1   4   7  10  13
2   2   5   8  11  14
3   3   6   9  12  15

我使用两条单​​独的行成功获得了我需要的列:

df2 <- df[,grep("[Aa]bc", names(df), value=TRUE)]
df3 <- df[,grep("[Xx]yz", names(df), value=TRUE)]
df4 <- cbind(df2, df3)

当我尝试使用以下方法一次完成所有这些操作时:

df2 <- df[,grep("[Aa]bc" | "[Xx]yz", names(df), value=TRUE)]

我收到以下错误:

“[Aa]bc”中的错误| "[Xx]yz" : 操作仅适用于 数字、逻辑或复杂类型

我也尝试将条件作为字符串列表传递给 grep,但它不起作用:

df2 <- df[,grep(c("[Aa]bc", "[Xx]yz"), names(df), value=TRUE)]

它只使用了带有警告的第一个列表项:

在 grep(c("[Aa]bc", "[Xx]yz"), names(df), value = TRUE) 中:参数 'pattern' 的长度 > 1 并且只使用第一个元素

所以它只选择了带有“[Aa]bc”的列,并跳过了“[Xx]yz”。

有更简单的方法吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    有一个参数ignore.case,如果设置为TRUE,那么它会忽略(大写/小写)大小写,即

    df[grepl('xyz|abc', names(df), ignore.case = TRUE)]
    
    #   abc Xyz Abc
    #1   1   7  10
    #2   2   8  11
    #3   3   9  12
    

    【讨论】:

    • 谢谢!这也有效。我只是因为没有将所有正则表达式都放在同一个引号中而挂断了电话。
    【解决方案2】:

    您需要将正则表达式包含在一个字符串本身中

    df[,grep("[Aa]bc|[Xx]yz", names(df))]
    
    #  abc Xyz Abc
    #1   1   7  10
    #2   2   8  11
    #3   3   9  12
    

    【讨论】:

      【解决方案3】:

      我们也可以使用“纯粹的”RegEx 方式来忽略大小写。否则,可以将ignore.case 设置为TRUE,如图所示:

      df[grepl("(?i)[a-c]|(?i)[x-z]", names(df))]
        abc Xyz Abc
      1   1   7  10
      2   2   8  11
      3   3   9  12
      

      我们也可以使用stringi

      df[stri_detect(names(df), regex = "xyz|abc",case_insensitive = TRUE)]
        abc Xyz Abc
      1   1   7  10
      2   2   8  11
      3   3   9  12
      

      tidyverse 方法:

       library(dplyr)
        library(stringi)
      
      df %>% 
        purrr::keep(stri_detect(names(df),
                                 regex = "xyz|abc",case_insensitive = TRUE))
        abc Xyz Abc
      1   1   7  10
      2   2   8  11
      3   3   9  12
      

      【讨论】:

      • 如果将ignore.case 设置为true,为什么在正则表达式(第一种情况)中使用大写字母?我在这里错过了什么?
      • 我在看到 OP 的实际预期输出之前回答了。被cbind 弄糊涂了,所以可能忘记编辑了。无论如何,我已经将其删除,只会展示一种 tidyverse 方法。
      • 哦,好的。我有点正则表达式盲,所以我无法翻译那个正则表达式,因此我的问题是如果我错过了什么。
      • grep也有ignore.case
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 2012-01-28
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 2020-02-16
      相关资源
      最近更新 更多