按字符列名筛选数据帧(以dplyr为单位)

按字符列名筛选数据帧(以dplyr为单位),r,dplyr,R,Dplyr,我有一个数据帧,希望通过两种方式之一对其进行过滤,即“this”列或“that”列。我希望能够将列名作为变量引用。如何(在dplyr中,如果有区别的话)通过变量引用列名 library(dplyr) df <- data.frame(this = c(1, 2, 2), that = c(1, 1, 2)) df # this that # 1 1 1 # 2 2 1 # 3 2 2 df %>% filter(this == 1) # t

我有一个数据帧,希望通过两种方式之一对其进行过滤,即“this”列或“that”列。我希望能够将列名作为变量引用。如何(在
dplyr
中,如果有区别的话)通过变量引用列名

library(dplyr)
df <- data.frame(this = c(1, 2, 2), that = c(1, 1, 2))
df
#   this that
# 1    1    1
# 2    2    1
# 3    2    2
df %>% filter(this == 1)
#   this that
# 1    1    1

如何将
列的值
转换为列名?

我将避免同时使用
get()
。在这种情况下,这似乎是相当危险的,特别是如果你正在编程的话。您可以使用未计算的调用或粘贴的字符串,但需要使用
filter()
而不是
filter()

选项2-使用
粘贴()
(显然更简单):

关于这两个选项的主要内容是我们需要使用
filter\uuz()
而不是
filter()
。事实上,从我所读到的内容来看,如果您使用
dplyr
编程,您应该始终使用
*.\u()
函数


我用这篇文章作为一个有用的参考:,我用的是
dplyr
0.3.0.2版。

关于Richard的解决方案,只想补充一点,如果你的专栏是字符。您可以添加
shQuote
以按字符值筛选

例如,您可以使用

df %>% filter_(paste(column, "==", shQuote("a")))
如果您有多个筛选器,可以在
粘贴中指定
collapse=“&”

df %>$ filter_(paste(c("column1","column2"), "==", shQuote(c("a","b")), collapse = "&"))

从当前dplyr帮助文件(我强调):

dplyr用于提供每个动词的两个版本,每个版本的后缀为下划线。这些版本具有标准的求值(SE)语义:它们不像NSE动词那样按代码获取参数,而是按值获取参数。他们的目的是使使用dplyr编程成为可能。但是,dplyr现在使用整洁的求值语义。NSE动词仍然捕获它们的参数,但是现在可以取消这些参数的部分引用。这提供了NSE谓词的完整编程功能。因此,带下划线的版本现在是多余的

因此,我们基本上需要做两件事,才能在
dplyr::filter()
中引用变量
列的值
“this”

  • 我们需要将字符类型的变量
    转换为字符类型。

    使用base R,这可以通过函数
    as.symbol()
    它是
    as.name()
    的别名。前者是 因为它

    遵循更现代的术语(R类型而不是S模式)

    或者,也可以通过从tidyverse获得相同的结果

  • 我们需要从1中取消引用符号)。

    不引用的确切含义可以在小插曲中学习 . 这是通过
    实现的

    (在早期版本的
    dplyr
    (或底层的
    rlang
    )中,曾经有
    !!
    与单个
    冲突的情况(包括您的情况),但这不再是问题。)

  • 适用于您的示例:

    library(dplyr)
    df <- data.frame(this = c(1, 2, 2),
                     that = c(1, 1, 2))
    column <- "this"
    
    df %>% filter(!!as.symbol(column) == 1)
    #   this that
    # 1    1    1
    
    库(dplyr)
    
    df与上文解释的Salim B相似,但略有变化:

    df %>% filter(1 == !!as.name(column))
    
    i、 e.只需反转条件,因为
    否则将正常工作
    像


    以下是最新dplyr版本的另一个解决方案:

    df <- data.frame(this = c(1, 2, 2),
                     that = c(1, 1, 2))
    column <- "this"
    
    df %>% filter(.[[column]] == 1)
    
    #  this that
    #1    1    1
    

    df或在

    library(dplyr)
    df %>% 
       filter_at(vars(column), any_vars(. == 1))
    

    最新的方法是使用
    my.data.frame%>%过滤器(.data[[myName]]==1)
    ,其中
    myName
    是包含列名的环境变量。

    为什么要这样做?试图参数化变量的选择?我有一个数据集,其中包含两种类型的内容,每种类型有不同的列。我想以这种方式处理问题,因为我使用Shiny来制作交互式可视化,我想让人们选择要查看的对象类型,然后使用相同的代码来提取数据,根据他们的选择输入列名。几乎发布了我的问题,发现:)选项1是一个强大的解决方案,正如@hadley在SO和vignette(“nse”)的几篇文章中所建议的那样。然而,它似乎与哈德利优雅的函数调用风格背道而驰。它不能以更简单的方式包装和呈现吗?为什么get()被认为是危险的?这对于较旧版本的
    dpylr
    来说是一个很好的答案,但是下划线函数已经被弃用,因此@Salim-B下面的答案更好。对于后一种情况,您可以使用一些额外的圆括号
    df%>%filter((!!as.name(column))==1)
    Great,但是“'UQ()'和'UQS()”在rlang 0.2.0中被软性弃用,以使准旋转的语法更加一致。”感谢@ggll,我更新了答案,以说明dplyr/rlang最近的改进。
    library(dplyr)
    df <- data.frame(this = c(1, 2, 2),
                     that = c(1, 1, 2))
    column <- "this"
    
    df %>% filter(!!as.symbol(column) == 1)
    #   this that
    # 1    1    1
    
    df %>% filter(1 == !!as.name(column))
    
    !!(as.name(column)==1)
    
    df <- data.frame(this = c(1, 2, 2),
                     that = c(1, 1, 2))
    column <- "this"
    
    df %>% filter(.[[column]] == 1)
    
    #  this that
    #1    1    1
    
    library(dplyr)
    df %>% 
       filter_at(vars(column), any_vars(. == 1))