R 使用tidy求值选择命名的[list]元素
我正试着将我的头脑集中在非标准评估上,因为它在包中被解释。考虑到这一目标,我的问题是: 如何编写符合整洁评估原则的R 使用tidy求值选择命名的[list]元素,r,rlang,tidyeval,non-standard-evaluation,R,Rlang,Tidyeval,Non Standard Evaluation,我正试着将我的头脑集中在非标准评估上,因为它在包中被解释。考虑到这一目标,我的问题是: 如何编写符合整洁评估原则的dplyr::select.list()函数 下面是一个示例,说明我当前如何围绕dplyr::select()编写包装器: 但不在名单上: attr(mtcars, "test") <- "asdf" mtcars_list <- attributes(mtcars) select_wrapper(mtcars_list, row.names, test) > ##
dplyr::select.list()
函数
下面是一个示例,说明我当前如何围绕dplyr::select()
编写包装器:
但不在名单上:
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:
是否有一种更干净、更整洁的评估一致性方法可以做到这一点?我认为dplyr适用于dfs
select
之所以会在列表中做一些非常奇怪的事情,是因为它并不是专门为此而设计的。我甚至不知道为什么会发生这种情况(我曾经遇到过交互式列表的事情,当时我非常困惑)
[
是为列表选择
但是[
需要字符串。因此,您的问题实际上是将裸参数转换为字符串,以便在[
中使用:
library(tidyverse)
l <- letters
names(l) <- letters
l
select.list <- function(x, ...) {
vars <- rlang::quos(...) %>% map(quo_text) %>% unlist()
x[vars]
}
select.list(l, a, b)
a b
"a" "b"
库(tidyverse)
l您可以使用tidyselect,它实现了select()
的后端:
select2我也提出了类似的解决方案(通过deparse
或exprs
转换为字符串),但我不知道quo\u text
!我想知道这些解决方案是(还是)?另外,我同意dplyr不是为列表而设计的。我正在组合保留属性的函数,因此将一些dplyr方法转换为列表会很有帮助。嗯。听起来你需要为你正在寻找的东西编写单元测试,并针对它们测试各种解决方案。还有“translate dplyr methods”,您是想包装一个dplyr方法并在列表中调用它,还是想查看dplyr源代码并直接进行翻译?任何一个都可能非常困难,所以祝您好运,是的,我没有尝试重新创建dplyr:)。但我正在尝试使用任务(用于保存数据帧属性的函数)学习rlang/tidy eval。因此,我的tidy eval问题更具理论性——将名称转换为字符串是否被视为符合卫生标准——而较少涉及单元测试(我同意这一点仍然很重要)。谢谢你!这将是select的包装器,用于新的[list like]课堂上。我只是不想为这个问题解释所有这些:)。我一直在研究列表,我已经找了很长时间了!你知道为什么代表tidyverse
列表端的purrr
包从来没有实现过这么方便的功能吗?你的问题正是时候!我很抱歉关于实现一个通用的tidyselect::vec_select()
,它将用于列表和任何向量。
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:
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)
library(tidyverse)
l <- letters
names(l) <- letters
l
select.list <- function(x, ...) {
vars <- rlang::quos(...) %>% map(quo_text) %>% unlist()
x[vars]
}
select.list(l, a, b)
a b
"a" "b"
select2 <- function(.x, ...) {
vars <- rlang::names2(.x)
vars <- tidyselect::vars_select(vars, ...)
.x[vars]
}
x <- list(a = 1, b = 2)
select2(x, dplyr::starts_with("a"))