如何在函数内的 if 条件内使用 dplyr NSE?

How to use dplyr NSE inside an if condition inside a function?

我有一个接受 NSE 参数的函数。

假设我有一个需要排序的列。我想创建一个函数,该函数可以根据在函数参数中输入的名称对列的名称进行排序。 但是,如果我不使用该参数,我希望它不对列进行排序,因此我使用 column_name = NULL 作为默认参数(或 column_name = NA

sort_tibble <- function(column_name = NULL) {
  tibble_data <- tibble::tibble(NSE_name = c(0.2, -0.4, 1.7, 0.09, -0.6, -1))
  if (!is.null(({{ column_name }}))) {
    tibble_data <- tibble_data %>% arrange({{ column_name }})

    # Do stuff
  }
}

sort_tibble(NSE_name)
#> Error in sort_tibble(NSE_name): objet 'NSE_name' not found

reprex package (v2.0.1)

于 2022-04-11 创建

然而,尽管引号、{{var}} 或 rlang::eval_tidy 有多少种组合,但我找不到让 R 理解 column_name 不为空(因此使用)的想法。它找不到它,因为它不是一个变量而是一个整洁的评估,除了它没有在整洁的函数中使用。

我终于找到了解决办法!

这里的想法不是直接尝试使用 {{var}} 为 dplyr 注入数据,而是首先使用字符串作为函数参数输入,并允许使用 [=12= 通过 dplyr 对其进行评估] 和 !!。这允许其他非整洁操作在函数中工作,包括子集数据框或仅评估参数是否为空(这是我的 if 函数的条件)。

我参考了https://tidyeval.tidyverse.org/sec-why-how.html#unquoting-code

使用sym()将字符串变成一个符号。 符号需要被评估为 dplyr

中的列
sym("NSE_name")
# NSE_name

然后使用!!将评估注入代码

library(tidyverse)
f1 <- function(order = NULL) {
  df <-
    tibble::tibble(NSE_name = c(0.2, -0.4, 1.7, 0.09, -0.6, -1))
  f2(order = order)
}

f2 <- function(order = NULL) {
  if (!is.null(order)) {
    
    ordered_df <- df %>% arrange(!!sym(order))
    return(ordered_df)
  }
  else print ("No order")
}

f1(order = "NSE_name")
f1()