【问题标题】:Arrange function in dplyr 0.7.1dplyr 0.7.1 中的排列函数
【发布时间】:2017-07-13 18:57:31
【问题描述】:

我在使用 dplyr 编写函数时尝试使用新的 quo 功能并遇到以下问题:

df <- tibble(
  g1 = c(1, 1, 2, 2, 2),
  g2 = c(1, 2, 1, 3, 1),
  a = sample(5), 
  b = sample(5)
)

按变量排列数据框很简单:

my_arrange <- function(df, arrange_var) {
  quo_arrange_var <- enquo(arrange_var)
  df %>%
    arrange(!!quo_arrange_var)
}

但是如果我想设置优惠订单怎么办?例如,任何排列变量都有 2 作为顶部变量,然后正常排序。对于以前版本的 dplyr,我会使用:

arrange(-(arrange_var == 2), arrange_var)

但在新结构中,我不确定如何处理。我试过了:

my_arrange <- function(df, arrange_var) {
  quo_arrange_var <- enquo(arrange_var)

  df %>%
    arrange(-!!quo_arrange_var==2, !!quo_arrange_var)
}

但我得到了错误

 Error in arrange_impl(.data, dots) : 
  incorrect size (1) at position 1, expecting : 5 

我也尝试过使用 quo_name:

my_arrange <- function(df, arrange_var) {
  quo_arrange_var <- enquo(arrange_var)

  df %>%
    arrange(-!!(paste0(quo_name(quo_arrange_var), "==2")), !!quo_arrange_var)
}

但得到这个错误:

 Error in arrange_impl(.data, dots) : 
  Evaluation error: invalid argument to unary operator. 

任何帮助将不胜感激

【问题讨论】:

    标签: r dplyr tidyverse rlang tidyeval


    【解决方案1】:

    最简单的解决方法是在 bang-bang 周围加上括号。这与!== 的运算符优先级有关。当您拥有!!a==b 时,即使您想要(!!a)==b,它也会被解析为!!(a==b)。并且由于某种原因,您可以将 quosure 与数值 quo(a)==2 进行比较,返回 FALSE,因此您的表达式正在评估为 arrange(-FALSE, g2),这会给您相同的错误消息。

    my_arrange <- function(df, arrange_var) {
      quo_arrange_var <- enquo(arrange_var)
    
      df %>%
        arrange(-((!!quo_arrange_var)==2), !!quo_arrange_var)
    }
    my_arrange(df, g2)
    # # A tibble: 5 x 4
    #      g1    g2     a     b
    #   <dbl> <dbl> <int> <int>
    # 1     1     2     5     4
    # 2     1     1     2     5
    # 3     2     1     4     3
    # 4     2     1     3     1
    # 5     2     3     1     2
    

    【讨论】:

      【解决方案2】:

      tidyverse 已经进化,不再需要enquo。相反,我们将表达式括在双括号 {{ }}(也就是我们 embrace 它们)中。

      library("tidyverse")
      
      df <- tibble(
        g1 = c(1, 1, 2, 2, 2),
        g2 = c(1, 2, 1, 3, 1),
        a = sample(5),
        b = sample(5)
      )
      
      my_arrange <- function(df, arrange_var) {
        df %>%
          arrange(desc({{ arrange_var }} == 2), {{ arrange_var }})
      }
      my_arrange(df, g2)
      #> # A tibble: 5 × 4
      #>      g1    g2     a     b
      #>   <dbl> <dbl> <int> <int>
      #> 1     1     2     1     2
      #> 2     1     1     4     5
      #> 3     2     1     3     3
      #> 4     2     1     5     1
      #> 5     2     3     2     4
      
      packageVersion("tidyverse")
      #> [1] '1.3.1'
      

      reprex package (v2.0.1) 于 2022-03-17 创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-25
        • 2018-08-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-26
        • 1970-01-01
        相关资源
        最近更新 更多