我正试图围绕非标准评估,因为它在rlang包中进行了解释。考虑到这个目标,我的问题是:
如何编写
dplyr::select.list()
符合 tidy 评估原则的函数?
这是我目前如何编写包装器的示例dplyr::select()
:
select_wrapper <- function(x, ...) {
vars <- rlang::quos(...)
dplyr::select(x, !!!vars)
}
这适用于数据帧,例如,
> select_wrapper(mtcars, cyl, mpg)
> ## cyl mpg
> ## Mazda RX4 6 21.0
> ## Mazda RX4 Wag 6 21.0
> ## Datsun 710 4 22.8
> ## Hornet 4 Drive 6 21.4
> ## Hornet Sportabout 8 18.7
> ## Valiant 6 18.1
但不在名单上:
attr(mtcars, "test") <- "asdf"
mtcars_list <- attributes(mtcars)
select_wrapper(mtcars_list, row.names, test)
> ## 1: c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb")
> ## 2: c("Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", "Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", "Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", "Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", "Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", "Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", "Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", "Volvo 142E")
> ## 3: data.frame
> ## 4: asdf
> ## Selection:
老实说,我不确定上面的输出中发生了什么......它返回一个交互式提示,要求我选择我想要的元素。这不是很理想,imo。
无论如何,我想要完成的是一个select.list()
函数,它返回我通过非标准评估选择的命名元素列表。这是我的解决方案,但感觉太老套了:
listdf <- function(x) {
as.data.frame(lapply(x, function(x) I(list(x))))
}
dflist <- function(x) {
x <- lapply(x, unlist, recursive = FALSE)
lapply(x, unclass)
}
select.list <- function(x, ...) {
dots <- rlang::quos(...)
if (length(dots) == 0L) return(list())
x <- listdf(x)
dflist(dplyr::select(x, !!!dots))
}
library(dplyr)
attr(mtcars, "test") <- "asdf"
select(attributes(mtcars), test, row.names)
有没有更干净、更整洁的评估一致的方法来做到这一点?