2

我有以下数据框:

dat <- data.frame(time   = runif(20),
                  group1 = rep(1:2, times = 10),
                  group2 = rep(1:2, each = 10),
                  group3 = rep(3:4, each = 10))

我现在正在编写一个my_function采用以下形式的函数:

my_function(data, time_var = time, group_vars = c(group1, group2))

如果我没记错的话,我将 group_vars 作为符号传递给我的函数,对吗?

但是,在我的函数中,我想首先进行一些错误检查,如果传递给函数的变量存在于数据中。对于时间变量,我成功了,但我不知道如何将 group_vars 列表转换为字符串向量,使其看起来像c("group1", "group2").

我当前的功能如下:

my_function <- function (data, time_var = NULL, group_vars = NULL)
{
  time_var          <- enquo(time_var)
  time_var_string   <- as_label(time_var)
  group_vars        <- enquos(group_vars)

  # is "time" variable part of the dataset?
  if (!time_var_string %in% colnames(data))
  {
    stop(paste0("The variable '", time_var_string, "' doesn't exist in your data set. Please check for typos."))
  }
}

我想扩展后一部分,以便我也可以以!group_vars %in% colnames(data). 我知道我可以将 group_var 变量作为字符串向量传递给函数,但出于其他原因我不想这样做。

4

2 回答 2

1

enquos这里是错误的函数:它对多个参数进行操作,但您只传递一个参数。只需使用enquo. 但是,无论哪种方式,结果都不能直接使用,因为您没有得到未评估名称的向量——您得到的是未评估的ccall

恐怕使用它有点复杂:

group_vars_expr = quo_squash(group_vars)
group_var_names = if (is_symbol(group_vars_expr)) {
    as_name(group_vars_expr)
} else {
    stopifnot(is_call(group_vars_expr))
    stopifnot(identical(group_vars_expr[[1L]], sym('c')))
    stopifnot(all(purrr::map_lgl(group_vars_expr[-1L], is_symbol)))
    purrr::map_chr(group_vars_expr[-1L], as_name)
}
stopifnot(all(group_var_names %in% colnames(data)))
于 2019-11-14T15:37:51.223 回答
1

如果您想以c()这种方式使用,您可能需要selections。在参数中进行选择的一种简单方法是与 接口dplyr::select()

my_function <- function(data, group_vars = NULL) {
  group_vars <- names(dplyr::select(data, {{ group_vars }}))
  group_vars
}

mtcars %>% my_function(c(cyl, mpg))
#> [1] "cyl" "mpg"

mtcars %>% my_function(starts_with("d"))
#> [1] "disp" "drat"
于 2019-11-14T17:15:21.507 回答