【问题标题】:Dplyr "Arrange" function not working when passing arguments to it inside a functionDplyr“排列”函数在函数内部传递参数时不起作用
【发布时间】:2019-09-25 20:58:31
【问题描述】:

我一直在查看有关在自定义函数中将参数传递给 dplyr 函数的帖子,但我无法解决以下情况:

我创建了以下函数来获取数据框的子集。

library(Lahman)

top_leaders <- function(df, metric, n) {
     # metric is the name of the column of Batting df which I would like to analyze
     # n is the number of top players leaders on that metric

    stat_leader <- enquo(metric)

    df %>%
      dplyr::select(playerID, !!stat_leader) %>% 
      dplyr::top_n(n)
  }

因为这个函数在该统计数据上对 n 个玩家的领导者进行了子集化,所以效果很好。例如:

> top_leaders(Lahman::Batting, "R", 5)
Selecting by R
   playerID   R
1 oneilti01 167
2 brownto01 177
3 hamilbi01 198
4  ruthba01 177
5 gehrilo01 167

尽管如此,我希望对结果进行排序,所以我使用 include arrange 函数来按 stat 对其进行排序。

top_leaders <- function(df, metric, n) {
    stat_leader <- enquo(metric)

    df %>%
      dplyr::select(playerID, !!stat_leader) %>% 
      dplyr::top_n(n) %>%
      dplyr::arrange(desc(!!stat_leader))
  }

但它给出了以下错误:

Selecting by R
 Error: incorrect size (1) at position 1, expecting : 5 

我后来尝试使用arrange_(desc(!!stat_leader)) 也出现另一个错误:

Selecting by R
 Error: Quosures can only be unquoted within a quasiquotation context.

  # Bad:
  list(!!myquosure)

  # Good:
  dplyr::mutate(data, !!myquosure)

所以我不知道如何解决这个问题。

【问题讨论】:

  • 当您使用裸列名称(即R而不是"R")调用它时是否有效?这就是这些基于dplyr 的函数中的约定

标签: r dplyr


【解决方案1】:

利用Rlang's new curly-curly notation

top_leaders <- function(df, playerID, metric, n) {
  df %>%
    dplyr::select({{playerID}}, {{metric}}) %>% 
    dplyr::top_n(n) %>%
    dplyr::arrange(desc({{metric}})) %>% 
    return(.)
}

top_leaders(as_tibble(Lahman::Batting), playerID, R, 5)

#Selecting by R
## A tibble: 5 x 2
#  playerID      R
#  <chr>     <int>
#1 hamilbi01   198
#2 brownto01   177
#3 ruthba01    177
#4 oneilti01   167
#5 gehrilo01   167

您也需要将 playerID 传递给函数,但这是一个小改动。

【讨论】:

    【解决方案2】:

    我们可能需要在此处转换为symbol,因为我们正在传递一个字符串。

    top_leaders <- function(df, metric, n) {
        stat_leader <- ensym(metric)
    
         df %>%
           dplyr::select(playerID, !!stat_leader) %>% 
           dplyr::top_n(n) %>%
           dplyr::arrange(desc(!!stat_leader))
         }
    top_leaders(Lahman::Batting, "R", 5)
    #Selecting by R
    #   playerID   R
    #1 hamilbi01 198
    #2 brownto01 177
    #3  ruthba01 177
    #4 oneilti01 167
    #5 gehrilo01 167
    

    如果我们传递不带引号的变量名,它也可以工作

    top_leaders(Lahman::Batting, R, 5)
    #Selecting by R
    #   playerID   R
    #1 hamilbi01 198
    #2 brownto01 177
    #3  ruthba01 177
    #4 oneilti01 167
    #5 gehrilo01 167
    

    使用 OP 的函数,它只需要不带引号的参数而不是带引号的参数

    【讨论】:

    • 谢谢@akrun。这也行得通,并且对是否引用的论点保持灵活是很好的,
    猜你喜欢
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 2019-11-28
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    相关资源
    最近更新 更多