【发布时间】:2018-10-04 16:12:49
【问题描述】:
试图排除
-
多个列在对
tidyr::gather()的调用中 - 通过 字符向量 参数(
shiny::selectInput的输出)而不是通过...作为我的函数的输入 - 以程序化方式
如何使用整洁的评估功能来做到这一点?
由于我通过单个函数参数传递多个列名,我认为我需要使用!!!(取消引用拼接)而不是!!,如Programming with dplyr 中所述。但这似乎与tidyselect::vars_select() 并不能很好地配合,而且似乎是- 造成了麻烦。
这是我想做的基本事情:
library(magrittr)
gather_data_1 <- function(dat, ...) {
dat %>% tidyr::gather("key", "value", ...)
}
mtcars %>% gather_data_1(-mpg, -cyl) %>% head()
#> mpg cyl key value
#> 1 21.0 6 disp 160
#> 2 21.0 6 disp 160
#> 3 22.8 4 disp 108
#> 4 21.4 6 disp 258
#> 5 18.7 8 disp 360
#> 6 18.1 6 disp 225
但是我想通过 single 参数传递列名(就像在闪亮的应用程序中一样,它也将通过 input$<select_input_id> 提供服务):
gather_data_2 <- function(dat, exclude) {
exclude <- rlang::syms(exclude)
dat %>% tidyr::gather("key", "value", -!!!exclude)
}
mtcars %>% gather_data_2(exclude = c("mpg", "cyl"))
#> Error: Can't use `!!!` at top level
然后我试着看看-是不是问题:
gather_data_3 <- function(dat, exclude) {
exclude <- rlang::syms(exclude)
dat %>% tidyr::gather("key", "value", !!!exclude)
}
mtcars %>% gather_data_3(exclude = c("mpg", "cyl")) %>% head()
#> disp hp drat wt qsec vs am gear carb key value
#> 1 160 110 3.90 2.620 16.46 0 1 4 4 mpg 21.0
#> 2 160 110 3.90 2.875 17.02 0 1 4 4 mpg 21.0
#> 3 108 93 3.85 2.320 18.61 1 1 4 1 mpg 22.8
#> 4 258 110 3.08 3.215 19.44 1 0 3 1 mpg 21.4
#> 5 360 175 3.15 3.440 17.02 0 0 3 2 mpg 18.7
#> 6 225 105 2.76 3.460 20.22 1 0 3 1 mpg 18.1
这似乎行得通。
然后我尝试将 - 放入实际的符号名称中,但这不起作用(至少我尝试过的方式是 ;-)):
gather_data_4 <- function(dat, exclude) {
exclude <- rlang::syms(sprintf("-%s", exclude))
dat %>% tidyr::gather("key", "value", !!!exclude)
}
mtcars %>% gather_data_4(exclude = c("mpg", "cyl"))
#> Error in .f(.x[[i]], ...): object '-mpg' not found
[1]: https://dplyr.tidyverse.org/articles/programming.html#unquote-splicing
编辑
在 Lionel 的帮助下,我得以拼凑起来:
gather_data_6 <- function(dat, exclude) {
dat %>% tidyr::gather("key", "value", -c(rlang::UQS(exclude)))
}
mtcars %>% gather_data_6(exclude = c("mpg", "cyl")) %>% head()
#> mpg cyl key value
#> 1 21.0 6 disp 160
#> 2 21.0 6 disp 160
#> 3 22.8 4 disp 108
#> 4 21.4 6 disp 258
#> 5 18.7 8 disp 360
#> 6 18.1 6 disp 225
甚至简化:
gather_data_7 <- function(dat, exclude) {
dat %>% tidyr::gather("key", "value", -c(!!!exclude))
}
mtcars %>% gather_data_7(exclude = c("mpg", "cyl")) %>% head()
#> mpg cyl key value
#> 1 21.0 6 disp 160
#> 2 21.0 6 disp 160
#> 3 22.8 4 disp 108
#> 4 21.4 6 disp 258
#> 5 18.7 8 disp 360
#> 6 18.1 6 disp 225
由reprex package (v0.2.0) 于 2018 年 4 月 26 日创建。
【问题讨论】:
-
这在stackoverflow.com/questions/46828296/… 中得到了回答请注意
sym()用于创建符号(例如列名)而不是调用(对列的操作) -
@lionel:非常感谢您的指点!
-
哎呀,请不要使用带有
UQS()的命名空间,这将被弃用。一般来说,最好使用!!!,我们对UQS()语法感到遗憾。 -
@lionel 指出。但是使用
!!!您指出的解决方案不再起作用,还是我做错了什么?使用-c(!!!exclude)会引发错误 -
@lionel:别介意我之前的评论,只需使用
-c(!!!exclude)对我有用
标签: r tidyr tidyeval tidyselect