- 使用非标准评估收集的操作员
- operator with gather using non standard evaluation
我想编写一个函数,将一个 quosure 作为参数,将 -
附加到 quosure,并将其传递给 gather
,如下所示:
library(tidyverse)
my_gather <- function(d, not.columns) {
dg <- tidyr::gather(d, key = k, value = v, .dots = -!!!not.columns)
dg
}
de <- my_gather(mtcars, not.columns = quos(mpg, cyl, disp))
> Error in `-`(~mpg, ~cyl, ~disp) : operator needs one or two arguments
这显然是因为我需要用 -
附加 quosure 的每个元素,而不是用 -
附加整个 quosure。但是在我的工作中,以 quos(-mpg, -cyl, -disp)
的形式创建这个 quosure 并不容易 - 那么我如何修改 quos(mpg, cyl, disp)
以添加 -
?
我希望看到与 gather(mtcars, key = k, value = v, -mpg, -cyl, -disp)
相同的结果,前 3 行是
mpg cyl disp k v
1 21.0 6 160 hp 110
2 21.0 6 160 hp 110
3 22.8 4 108 hp 93
有一个类似的问题 here,但没有人回答并且似乎没有处理 quos()
而不是 quo()
的问题。
我可以提供 "Answer the problem not the question" 类型的答案。您实际上需要一种方法来指定收集的列,其中包含有关未使用列的信息。这是我的方法:
library(tidyverse)
negate_columns <- function(.tbl, not.columns) {
not_columns <- colnames(select(.tbl, !!!not.columns))
setdiff(colnames(.tbl), not_columns)
}
my_gather <- function(d, not.columns) {
columns <- negate_columns(d, not.columns)
tidyr::gather(d, key = k, value = v, !!!syms(columns))
}
这样它会按预期工作:
my_gather(mtcars, not.columns = quos(mpg, cyl, disp)) %>%
head(3)
#> mpg cyl disp k v
#> 1 21.0 6 160 hp 110
#> 2 21.0 6 160 hp 110
#> 3 22.8 4 108 hp 93
我们可以做到
my_gather <- function(d, not.columns) {
tidyr::gather(d, key = k, value = v, .dots = -c(UQS(not.columns)))
#or use !!! instead of UQS
#tidyr::gather(d, key = k, value = v, .dots = -c(!!!(not.columns)))
}
de <- my_gather(mtcars, not.columns = quos(mpg, cyl, disp))
head(de, 3)
# mpg cyl disp k v
#1 21.0 6 160 hp 110
#2 21.0 6 160 hp 110
#3 22.8 4 108 hp 93
检查没有函数的输出
de1 <- gather(mtcars, key = k, value = v, -mpg, -cyl, -disp)
identical(de, de1)
#[1] TRUE
我想编写一个函数,将一个 quosure 作为参数,将 -
附加到 quosure,并将其传递给 gather
,如下所示:
library(tidyverse)
my_gather <- function(d, not.columns) {
dg <- tidyr::gather(d, key = k, value = v, .dots = -!!!not.columns)
dg
}
de <- my_gather(mtcars, not.columns = quos(mpg, cyl, disp))
> Error in `-`(~mpg, ~cyl, ~disp) : operator needs one or two arguments
这显然是因为我需要用 -
附加 quosure 的每个元素,而不是用 -
附加整个 quosure。但是在我的工作中,以 quos(-mpg, -cyl, -disp)
的形式创建这个 quosure 并不容易 - 那么我如何修改 quos(mpg, cyl, disp)
以添加 -
?
我希望看到与 gather(mtcars, key = k, value = v, -mpg, -cyl, -disp)
相同的结果,前 3 行是
mpg cyl disp k v
1 21.0 6 160 hp 110
2 21.0 6 160 hp 110
3 22.8 4 108 hp 93
有一个类似的问题 here,但没有人回答并且似乎没有处理 quos()
而不是 quo()
的问题。
我可以提供 "Answer the problem not the question" 类型的答案。您实际上需要一种方法来指定收集的列,其中包含有关未使用列的信息。这是我的方法:
library(tidyverse)
negate_columns <- function(.tbl, not.columns) {
not_columns <- colnames(select(.tbl, !!!not.columns))
setdiff(colnames(.tbl), not_columns)
}
my_gather <- function(d, not.columns) {
columns <- negate_columns(d, not.columns)
tidyr::gather(d, key = k, value = v, !!!syms(columns))
}
这样它会按预期工作:
my_gather(mtcars, not.columns = quos(mpg, cyl, disp)) %>%
head(3)
#> mpg cyl disp k v
#> 1 21.0 6 160 hp 110
#> 2 21.0 6 160 hp 110
#> 3 22.8 4 108 hp 93
我们可以做到
my_gather <- function(d, not.columns) {
tidyr::gather(d, key = k, value = v, .dots = -c(UQS(not.columns)))
#or use !!! instead of UQS
#tidyr::gather(d, key = k, value = v, .dots = -c(!!!(not.columns)))
}
de <- my_gather(mtcars, not.columns = quos(mpg, cyl, disp))
head(de, 3)
# mpg cyl disp k v
#1 21.0 6 160 hp 110
#2 21.0 6 160 hp 110
#3 22.8 4 108 hp 93
检查没有函数的输出
de1 <- gather(mtcars, key = k, value = v, -mpg, -cyl, -disp)
identical(de, de1)
#[1] TRUE