我想编写一个在dplyr
链中使用的函数,用于按给定变量排列分组数据,然后检查该变量是否严格增加整数(例如,1,2,3,... )。为了澄清,我的意思是按顺序排列每个整数,而不仅仅是增加整数。所以1,2,4 ......应该失败。
这个想法最终会有这样的东西,看起来像这样,并且如果x不是1,2,3,则为每个组提供错误。
d %>% group_by(group) %>% check(x)
我已经写了一个似乎有效的SE版本,如下所示,但我仍坚持使用NSE版本。
check_ <- function(.data, var) {
checkint <- function(x) { stopifnot(x == seq_along(x)) }
do(.data, {
. <- dplyr::arrange_(., var)
checkint(lazyeval::lazy_eval(var, data=.))
.
})
}
在文档中,看起来我应该使用lazy
来处理单个变量,但是当我传入的变量也存在于全局环境中时,这不起作用
checkX <- function(.data, var) {
check_(.data, lazyeval::lazy(var))
}
d <- expand.grid(group=1:2, x=3:1)
x <- 5 ## put an "x" in the global environment
d %>% group_by(group) %>% checkX(x)
## Error: incorrect size (1), expecting : 3
我确实有一个似乎有效的NSE版本,但调用lazy_dots
感觉不对,因为我只想要一个变量。
check <- function(.data, ...) {
check_(.data, lazyeval::lazy_dots(...)[[1]])
}
答案 0 :(得分:2)
看起来lazyeval
一直在变化。 latest vignette甚至没有引用lazy()
函数。它似乎确实存在范围内变量的问题(更多内容在底部)。现在我们的功能受到了鼓励,尽管他们还没有进入所有“整齐的”。
看起来你想要的功能是expr_find
。如果我们将checkX
定义为
checkX <- function(.data, var) {
check_(.data, lazyeval::expr_find(var))
}
然后这将起作用
x <- 5
d %>% group_by(group) %>% checkX(x)
(或者至少与lazyeval_0.2.0
和dplyr_0.5.0
相同)
但回到old vignette
的第一个例子library(lazyeval)
# `x` does not exist here
f <- function(x = a - b) {
lazy(x)
}
f()
# <lazy>
# expr: a - b
# env: <environment: 0x000000000663d618>
exists("x")
# [1] FALSE
f(x)
# <lazy>
# expr: x
# env: <environment: R_GlobalEnv>
x <- 101
f(x)
# <lazy>
# expr: 101
# env: <environment: R_GlobalEnv>
或另一个更简单的例子
# rm(x)
lazy(x)
# <lazy>
# expr: x
# env: <environment: R_GlobalEnv>
x <- 100
lazy(x)
# <lazy>
# expr: 100
# env: <environment: R_GlobalEnv>
它在某处评估参数x,因此如果它存在于它所来自的环境中,它就永远不会保存在惰性对象中。