1

假设我们有一些向量和数据框:

a <- c(1, 2, 0, 1)
b <- c(6, 4)
df1 <- data_frame(x = c(6, 8, 12), y = c(24, 18, 16))

我们使用非标准评估编写了一个函数,该函数计算数据帧列的平均值和向量的平均值。

calculate_means <- function(df, column, vector) {
  column <- enquo(column)
  summarise(df, mean_column = mean(!!column), mean_vector = mean(vector))
}

calculate_means(df1, x, a)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        8.67        1.00

calculate_means(df1, y, b)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        19.3        5.00

这按预期工作。但是,如果我们编写相同的函数但为参数选择其他名称会发生​​什么?

calculate_means <- function(df, x, y) {
  x <- enquo(x)
  summarise(df, mean_column = mean(!!x), mean_vector = mean(y))
}

calculate_means(df1, x, a)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        8.67        19.3

calculate_means(df1, y, b)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        19.3        19.3

第一个参数的评估与以前相同,但第二个参数始终评估数据帧的“y”列。它不应该分别评估向量“a”和“b”吗?

4

2 回答 2

0

我们可以globalenv()用来获取对象列表,通过将对象名称作为字符串传递来获取对象的值,并在summarise语句中使用它

calculate_means <- function(df, x, y) {
  x <- enquo(x)
  y <- quo_name(enquo(y))
  v1 <- globalenv()[[y]]

  df %>%
       summarise(mean_column = mean(!! x),
       mean_vector = mean(v1))
 }

calculate_means(df1, x, a)
# A tibble: 1 x 2
#   mean_column mean_vector
#        <dbl>       <dbl>
#1        8.67        1.00

calculate_means(df1, y, b)
# A tibble: 1 x 2
#   mean_column mean_vector
#        <dbl>       <dbl>
#1        19.3        5.00

假设,如果我们还需要获取mean'y' 列

calculate_means <- function(df, x, y) {
  x <- enquo(x)
  y <- quo_name(enquo(y))
  v1 <- globalenv()[[y]]

  df %>%
       summarise(mean_column = mean(!! x),
       mean_vector = mean(v1),
       mean_column2 = mean(.data$y))
 }

calculate_means(df1, x, a)
# A tibble: 1 x 3
#  mean_column mean_vector mean_column2
#        <dbl>       <dbl>        <dbl>
#1        8.67        1.00         19.3
于 2018-02-21T12:08:06.610 回答
0

实际参数中的变量summarise首先在第一个参数中指定的数据帧中查找,并且如果在该数据帧中找不到,summarise则仅在调用者中查找。summarise因此,通过硬编码ysummarise参数中,它总是会df1首先查找它。

1)我们可以使用!避免这种情况。论据!!不在 data 参数中查找。

calculate_means2 <- function(df, x, y) {
  x <- enquo(x)
  summarise(df, mean_column = mean(!!x), mean_vector = mean(!!y))
}

calculate_means2(df1, y, b)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        19.3        5.00

2)我们可以as_quosure用来强调这一点。这会将 的值放入yquosure 公式中。在示例中,y <- as_quosure(y)将导致新的 quosure 包含~c(6, 4).

calculate_means3 <- function(df, x, y) {
  x <- enquo(x)
  y <- rlang::as_quosure(y)
  summarise(df, mean_column = mean(!!x), mean_vector = mean(!!y))
}

calculate_means3(df1, y, b)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        19.3        5.00

3)当然,我们可以只使用不太可能在数据框中使用的正式参数名称:

calculate_means4 <- function(df, x, y.) {
  x <- enquo(x)
  summarise(df, mean_column = mean(!!x), mean_vector = mean(y.))
}

calculate_means4(df1, y, b)
# A tibble: 1 x 2
  mean_column mean_vector
        <dbl>       <dbl>
1        19.3        5.00
于 2018-02-21T13:48:02.327 回答