【问题标题】:Use both empty and string filters in dplyr's filter在 dplyr 的过滤器中同时使用空和字符串过滤器
【发布时间】:2025-12-06 14:25:01
【问题描述】:

我正在使用已弃用的 dplyr::filter_() 更新旧脚本以使用 dplyr::filter()。但是我不能再让它为空的过滤器字符串工作了:

例子:

library(dplyr)
my_df <- tibble::tibble(x = sample(c(0:9), 100, replace = TRUE))

不推荐使用的filter_() 适用于字符串和空字符串

fil1 <- "x == 5"
filter_(mydf, .dots = fil1) # works

fil2 <- NULL
filter_(mydf, .dots = fil2) # works, returns all values

NSE 版本仅适用于带引号的过滤器值,但不适用于空值

fil1 = quo(x == 5)
filter(my_df, !!enquo(fil1)) # works

fil2 = NULL
filter(my_df, !!enquo(fil2)) 
Error: Argument 2 filter condition does not evaluate to a logical vector

fil2 = quo(NULL)
filter(my_df, !!enquo(fil2))
Error: Argument 2 filter condition does not evaluate to a logical vector

我看到了三种可能的方法:

  • 以不同方式引用NULL
  • 用另一个表达式代替NULL
  • filter() 中使用另一个参数

【问题讨论】:

  • 你说它在脚本中,有什么理由不能将它包装在条件中并测试“nullness”吗?
  • @Chuck P - 当然可以,但这似乎是一个丑陋的解决方法,我必须在几个地方这样做,最糟糕的是,我对如何做到这一点仍然没有好奇心将 NULL 输入 filter()。
  • 没有看到你的整个剧本会很丑,没有评论。不过,我为您提供了第二个子弹的解决方法。

标签: r dplyr nse


【解决方案1】:

如果您将过滤器指定为表达式列表(或 NULL),则可以使用 unquote-splice 运算符有效地将它们“粘贴”为过滤器的参数。使用parse_exprs() 将字符串转换为表达式:

fil1 <- rlang::exprs(x == 5)          # Note the s on exprs
filter(my_df, !!!fil1)                # Works

fil2 <- NULL                          # NULL
filter(my_df, !!!fil2)                # Also works

fil3 <- rlang::parse_exprs("x==5")    # Again, note the plural s
filter(my_df, !!!fil3)                # Also works

第一个和第三个调用实际上是filter(my_df, x==5),而第二个调用实际上是filter(my_df,)

【讨论】:

    【解决方案2】:

    如果我对您的理解正确@timm-s,第二个项目符号选项意味着我可以提供此解决方案。

    set.seed(2020)
    library(dplyr)
    
    my_df <- tibble::tibble(x = sample(c(0:9), 100, replace = TRUE))
    
    fil1 <- quo(x == 5)
    filter(my_df, !!enquo(fil1)) # works
    #> # A tibble: 11 x 1
    #>        x
    #>    <int>
    #>  1     5
    #>  2     5
    #>  3     5
    #>  4     5
    #>  5     5
    #>  6     5
    #>  7     5
    #>  8     5
    #>  9     5
    #> 10     5
    #> 11     5
    
    fil2 <- TRUE
    filter(my_df, !!enquo(fil2)) 
    #> # A tibble: 100 x 1
    #>        x
    #>    <int>
    #>  1     6
    #>  2     5
    #>  3     7
    #>  4     0
    #>  5     0
    #>  6     3
    #>  7     9
    #>  8     5
    #>  9     0
    #> 10     7
    #> # … with 90 more rows
    

    它仅仅依赖于filter 依赖于真/假这一事实,所以与其告诉它什么都不告诉它真实。对我来说,真正的问题是为什么 filter_ 认为 NULL 是真的 LOL。

    多玩一点,发现空箱可以简化更多

    fil3 <- TRUE
    filter(my_df, fil3) 
    

    也可以,但可能不适合您的情况。

    【讨论】: