该.env代词用来指代对象的环境(而不是一个data.frame内)以及内业等dplyr动词,但返回一个错误slice_max。为什么?考虑以下函数:
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(rlang)
f1 <- function(y) {
d <- tibble(x = runif(20))
d %>%
slice_max(order_by = .data$x, n = .env$y)
}
f2 <- function(y) {
d <- tibble(x = runif(20))
d %>%
filter(.data$x >= .env$y)
}
f3 <- function(y) {
d <- tibble(x = runif(20))
d %>%
mutate(z = .env$y)
}
f1(2)
#> Error: `n` must be a single number.
f2(0.8)
#> # A tibble: 8 x 1
#> x
#> <dbl>
#> 1 0.936
#> 2 0.812
#> 3 0.998
#> 4 0.962
#> 5 0.901
#> 6 0.875
#> 7 1.00
#> 8 0.919
f3(2)
#> # A tibble: 20 x 2
#> x z
#> <dbl> <dbl>
#> 1 0.0318 2
#> 2 0.928 2
#> 3 0.983 2
#> 4 0.622 2
#> 5 0.583 2
#> 6 0.0314 2
#> 7 0.481 2
#> 8 0.791 2
#> 9 0.476 2
#> 10 0.599 2
#> 11 0.468 2
#> 12 0.234 2
#> 13 0.276 2
#> 14 0.382 2
#> 15 0.914 2
#> 16 0.736 2
#> 17 0.572 2
#> 18 0.863 2
#> 19 0.337 2
#> 20 0.515 2
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v0.3.0)于 2020 年 11 月 16 日创建
错误是从dplyr:::check_slice_size调用的函数中抛出的slice_max.data.frame。该函数的第 7:9 行是:
if (!is.numeric(n) || length(n) != 1) {
abort("`n` must be a single number.")
}
Run Code Online (Sandbox Code Playgroud)
所以n必须是一个长度为一的数字。该.env代词没有在这里实现。
那么这是一个错误吗?我会争辩说它不是。.env这里不需要,因为n参数不使用 tidy 评估,也不应该使用它。由于只有n一个数字才有意义,因此使用 tidy 评估有意义的唯一情况是在单行小标题中。但是如果你知道你有一个单行的小标题,那么调用slice_max. 这是第 22 条规则:您唯一能够使用 tidy 评估的时间就是这样做没有用的时候。因此,这是一个很好的设计决策。
您可以放心,没有歧义。如果你y在这里使用,它总是按照你的意图解释.env$y:
library(dplyr)
library(rlang)
f1 <- function(y) {
d <- tibble(x = runif(20), y = rnorm(20))
d %>%
slice_max(order_by = .data$x, n = y)
}
f1(2)
#> # A tibble: 2 x 2
#> x y
#> <dbl> <dbl>
#> 1 0.971 -1.65
#> 2 0.918 0.151
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v0.3.0)于 2020 年 11 月 16 日创建