将整齐的 select 参数传递给内部函数,同时保持 "missingness"
Passing tidy select arguments to inner functions while maintaining "missingness"
谁能帮我找出解决这个问题的规范“tidyeval”方法:
outer()
接受一个数据框 data
和一个可选的(!)整洁选择参数 var
.
var
传递给 inner()
inner()
仅 执行 select()
如果 var
不丢失
- 要求:
inner()
和outer()
的签名应该相同,因为inner()可能会被独立调用
这是我的方法,但它不起作用。
问题:missing(var)
returns TRUE
在 outer()
但 FALSE
在 inner()
.
inner <- function(data, var) {
print(missing(var))
if (missing(var)) data else dplyr::select(data, {{ var }})
}
outer <- function(data, var) {
print(missing(var))
inner(data, !!rlang::enquo(var))
}
outer(mtcars)
#> [1] TRUE
#> [1] FALSE
#> data frame with 0 columns and 6 rows
inner(mtcars)
#> [1] TRUE
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
...
我天真的解决方案是在外部检查 missing(var)
并相应地更改对 inner()
的调用(见下文),但我想知道是否有一种方法可以传递 var
参数没有任何这样的检查?
# works as desired
outer <- function(data, var) {
print(missing(var))
if (missing(var)) inner(data) else inner(data, !!rlang::enquo(var))
}
啊,对不起!我不知道为什么我认为 !!enquo()
是必要的。事实证明,传递可选参数而不改变其“缺失”就这么简单:
inner <- function(data, var) {
print(missing(var))
if (missing(var)) {
print(colnames(data))
} else {
print(colnames(dplyr::select(data, {{ var }})))
}
}
outer <- function(data, var) {
print(missing(var))
inner(data, var)
}
outer(mtcars, dplyr::starts_with("m"))
#> [1] FALSE
#> [1] FALSE
#> [1] "mpg"
outer(mtcars)
#> [1] TRUE
#> [1] TRUE
#> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
编辑:显示如何查询缺失并在参数不缺失时应用整洁选择。
一种方法是给 var
足够的默认参数并无条件地将其传递给 select()
:
inner <- function(data, var = everything()) {
dplyr::select(data, {{ var }})
}
outer <- function(data, var = everything()) {
inner(data, {{ var }})
}
names(outer(mtcars))
#> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
names(outer(mtcars, starts_with("d")))
#> [1] "disp" "drat"
对于更复杂的情况(希望不需要),您需要解开 !!
和 enquo()
步骤,它们在单个 {{
操作中合并。然后你可以检查解散的quosure:
inner <- function(data, var) {
var <- enquo(var)
if (quo_is_missing(var)) {
data
} else {
dplyr::select(data, !!var)
}
}
outer <- function(data, var) {
inner(data, {{ var }})
}
谁能帮我找出解决这个问题的规范“tidyeval”方法:
outer()
接受一个数据框data
和一个可选的(!)整洁选择参数var
.var
传递给inner()
inner()
仅 执行select()
如果var
不丢失- 要求:
inner()
和outer()
的签名应该相同,因为inner()可能会被独立调用
这是我的方法,但它不起作用。
问题:missing(var)
returns TRUE
在 outer()
但 FALSE
在 inner()
.
inner <- function(data, var) {
print(missing(var))
if (missing(var)) data else dplyr::select(data, {{ var }})
}
outer <- function(data, var) {
print(missing(var))
inner(data, !!rlang::enquo(var))
}
outer(mtcars)
#> [1] TRUE
#> [1] FALSE
#> data frame with 0 columns and 6 rows
inner(mtcars)
#> [1] TRUE
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
...
我天真的解决方案是在外部检查 missing(var)
并相应地更改对 inner()
的调用(见下文),但我想知道是否有一种方法可以传递 var
参数没有任何这样的检查?
# works as desired
outer <- function(data, var) {
print(missing(var))
if (missing(var)) inner(data) else inner(data, !!rlang::enquo(var))
}
啊,对不起!我不知道为什么我认为 !!enquo()
是必要的。事实证明,传递可选参数而不改变其“缺失”就这么简单:
inner <- function(data, var) {
print(missing(var))
if (missing(var)) {
print(colnames(data))
} else {
print(colnames(dplyr::select(data, {{ var }})))
}
}
outer <- function(data, var) {
print(missing(var))
inner(data, var)
}
outer(mtcars, dplyr::starts_with("m"))
#> [1] FALSE
#> [1] FALSE
#> [1] "mpg"
outer(mtcars)
#> [1] TRUE
#> [1] TRUE
#> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
编辑:显示如何查询缺失并在参数不缺失时应用整洁选择。
一种方法是给 var
足够的默认参数并无条件地将其传递给 select()
:
inner <- function(data, var = everything()) {
dplyr::select(data, {{ var }})
}
outer <- function(data, var = everything()) {
inner(data, {{ var }})
}
names(outer(mtcars))
#> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
names(outer(mtcars, starts_with("d")))
#> [1] "disp" "drat"
对于更复杂的情况(希望不需要),您需要解开 !!
和 enquo()
步骤,它们在单个 {{
操作中合并。然后你可以检查解散的quosure:
inner <- function(data, var) {
var <- enquo(var)
if (quo_is_missing(var)) {
data
} else {
dplyr::select(data, !!var)
}
}
outer <- function(data, var) {
inner(data, {{ var }})
}