4

我想编写一个函数,它将 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 附加到-。但在我的工作中,以 - 的形式创建这个 quosure 并不容易,quos(-mpg, -cyl, -disp)那么我该如何修改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

这里有一个类似的问题,但没有答案,似乎没有处理quos()而不是的问题quo()

4

2 回答 2

3

我们可以做的

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
于 2017-10-29T16:47:59.887 回答
2

我可以提供“回答问题而不是问题”类型的答案。您实际上需要一种方法来指定收集的列,其中包含有关未使用列的信息。这是我的方式:

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
于 2017-10-29T16:38:27.253 回答