【问题标题】:R dplyr: Drop multiple columnsR dplyr:删除多列
【发布时间】:2016-06-20 17:56:29
【问题描述】:

我有一个要删除的数据框和该数据框中的列列表。我们以iris 数据集为例。我想删除 Sepal.LengthSepal.Width 并仅使用剩余的列。如何使用 dplyr 包中的 selectselect_ 执行此操作?

这是我迄今为止尝试过的:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

-drop.cols 中的错误:一元运算符的参数无效

iris %>% select_(.dots = -drop.cols)

-drop.cols 中的错误:一元运算符的参数无效

iris %>% select(!drop.cols)

!drop.cols 中的错误:参数类型无效

iris %>% select_(.dots = !drop.cols)

!drop.cols 中的错误:参数类型无效

我觉得我遗漏了一些明显的东西,因为这些似乎是一个应该已经存在的非常有用的操作。在 Github 上,有人发帖 a similar issue,Hadley 说要使用“负索引”。这就是(我认为)我尝试过的方法,但无济于事。有什么建议吗?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    查看关于 select_vars 的帮助。这为您提供了一些关于如何使用它的额外想法。

    在你的情况下:

    iris %>% select(-one_of(drop.cols))
    

    【讨论】:

    • 谢谢。出于某种原因,这适用于iris,但不适用于我的实际数据框(iris 是一个玩具示例)。我的数据框包含 4558 行和 147 列。我收到的错误消息是Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes。知道为什么会发生这种情况吗?
    • 啊,看来我搞错了。我不小心使用了select_vars 而不是select。现在它完美运行了!
    • 我们应该在哪里找到像one_of 这样的内置函数?除非我遗漏了什么,否则它不会出现在包文档中 (help(package='dplyr'))。
    • @geotheory,实际上 one_of 已记录在案。见help(one_of, package = "dplyr")。至少它在包版本 0.5.0 中。但它有助于阅读哈德利在他的一个包有更新时发布的blogs。一些函数记录在其他函数中。不幸的是,这需要阅读所有文档,当我想要一些不是立即显而易见或不可能的功能时,我通常会这样做。
    • 谢谢。就文档而言,您如何首先了解这些功能?
    【解决方案2】:

    也试试

    ## Notice the lack of quotes
    iris %>% select (-c(Sepal.Length, Sepal.Width))
    

    【讨论】:

    • 太棒了!当我们必须通过从控制台复制粘贴名称来删除列时非常有用。
    【解决方案3】:

    除了select(-one_of(drop.cols)) 之外,还有其他几个使用select() 删除列的选项,这些选项不涉及定义所有特定列名(使用 dplyr starwars 示例数据来获得更多种类的列名):

    starwars %>% 
      select(-(name:mass)) %>%        # the range of columns from 'name' to 'mass'
      select(-contains('color')) %>%  # any column name that contains 'color'
      select(-starts_with('bi')) %>%  # any column name that starts with 'bi'
      select(-ends_with('er')) %>%    # any column name that ends with 'er'
      select(-matches('^f.+s$')) %>%  # any column name matching the regex pattern
      select_if(~!is.list(.)) %>%     # not by column name but by data type
      head(2)
    
    # A tibble: 2 x 2
    homeworld species
      <chr>     <chr>  
    1 Tatooine  Human  
    2 Tatooine  Droid 
    

    【讨论】:

    • select_if(~!is.list(.)) 是否等同于 select_if(is.list(.))
    • 在这种情况下,~ 是定义匿名函数的 purrr 简写,它不是另一个符号。例如,这两个意思相同function(x) {!is.list(x)}~!is.list(.)。将~ 视为function(.) 的简写。
    【解决方案4】:

    注意select() 函数,因为它在 dplyr 和 MASS 包中都使用,所以如果加载 MASS,select() 可能无法正常工作。要找出加载了哪些包,请键入 sessionInfo() 并在“其他附加包:”部分中查找它。如果已加载,请输入detach( "package:MASS", unload = TRUE ),您的select() 函数应该会再次运行。

    【讨论】:

    • 或者您可以直接在包命名空间中访问该函数,如dplyr::select()
    • 我经常遇到这个问题。现在我通常在脚本的顶部定义一个新函数dselect &lt;- dplyr::select()
    • 稍后加载的包优先。在加载所有包后,我总是p_load(tidyverse),以确保函数不会被另一个包无意中屏蔽。
    【解决方案5】:

    我们可以试试

    iris %>% 
          select_(.dots= setdiff(names(.),drop.cols))
    

    【讨论】:

    • 感谢@akrun,这非常有效。然而,鉴于围绕dplyr 使基本分析任务易于读写的能力的炒作,我对实际的解决方案看起来像是一种解决方法感到失望。
    • @NavaneethanSanthanam 实际上,其他解决方案中的one_of 是可行的方法。我忘了。
    【解决方案6】:

    另一种方法是将不需要的列更改为NULL,这样可以避免嵌入括号:

    head(iris,2) %>% mutate_at(drop.cols, ~NULL)
    #   Petal.Length Petal.Width Species
    # 1          1.4         0.2  setosa
    # 2          1.4         0.2  setosa
    

    【讨论】:

    • 如果列不存在,这也不会发出警告。
    【解决方案7】:

    如果列名中有特殊字符,selectselect_ 可能无法按预期工作。 使用"."dplyr 的此属性。参考问题中的数据集,可以用下面这行来解决这个问题:

    drop.cols <- c('Sepal.Length', 'Sepal.Width')
      iris %>% .[,setdiff(names(.),drop.cols)]
    

    【讨论】:

    • 不鼓励仅使用代码的答案。请就答案的工作原理以及它与现有答案的不同之处提供一些解释。
    • 谢谢!!出于这个确切原因,上述其他解决方案均无效。
    【解决方案8】:

    对于任何到达这里并希望删除 范围 列的人。

    最小可重现示例

    像这样删除 范围 列:

    iris %>% 
      select(-(Sepal.Width:Petal.Width)) %>% 
      head
    
    #   Sepal.Length Species
    # 1          5.1  setosa
    # 2          4.9  setosa
    # 3          4.7  setosa
    # 4          4.6  setosa
    # 5          5.0  setosa
    # 6          5.4  setosa
    

    注意:

    • 列名周围的() 很重要,必须使用

    【讨论】:

      【解决方案9】:

      我也遇到了同样的问题,但主要错误在于包含具有另一个与“select()”同名的函数定义的库。对我来说,它与 MASS 包选择功能发生冲突。

      分离 MASS 库后,错误停止。

      【讨论】:

      • 请注意,您也可以通过 dplyr 库中的 select 指定 dplyr::select
      【解决方案10】:

      你可以试试

      iris %>% select(-!!drop.cols)
      

      【讨论】:

        猜你喜欢
        • 2020-03-18
        • 2022-08-03
        • 2021-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        相关资源
        最近更新 更多