我正在尝试编写一个在data.frame上运行的函数,该函数将接受dplyr样式的参数,即使用dplyr的pronous(或我们称为它的东西)未引用的列名。
但是在带括号的表达式中使用!!
时遇到了一个问题(请参见下面的示例)。
示例:
首先是一个data.frame:
df <- data.frame(gah=c('a','a','a','a','b','b','b','b'),
fruit=c('apple','apple','apple','banana','banana','banana','dog','dog'),
val=1:8,
sss=-7:0,
mean=0)
第一个函数,它对固定列(val
)和参数指定的列取平均值。它不会修改分组:
a_func <- function(df, value=val) {
value_ = enquo(value)
df %>% summarise(mean=mean(!!value_), mean_val=mean(val), n=n())
}
a_func(df, sss)
df %>% group_by(gah) %>% a_func()
df %>% group_by(gah) %>% a_func(sss)
df %>% group_by(gah, fruit) %>% a_func
这按预期工作。
下一个函数在使用summarise
之前添加分组变量:
c_func <- function(df, gr) {
gr_ = enquo(gr)
df %>% group_by(!!gr_) %>% summarise(n=n())
}
c_func(df, gah)
c_func(df, gr=gah)
c_func(df, fruit)
这也按预期工作。
接下来,我将两者结合起来。那应该可行-实际上是!赞美圣小猫!
b_func <- function(df, value=val, gr=NA) {
value_ = enquo(value)
gr_ = enquo(gr)
df %>% group_by(!!gr_, add=TRUE) %>%
summarise(mean=mean(!!value_), mean_val=mean(val))
}
b_func(df, sss)
df %>% group_by(gah) %>% b_func(gr=fruit)
b_func(df, gr=fruit)
df %>% group_by(gah) %>% b_func(sss, fruit)
显然,它与可选参数gr
一样可以正常工作,我只想在gr
不是 NA
时添加分组变量。
这是中断吗?
添加条件以仅在gr
不是NA
时进行分组,
在支架内寻找担保不起作用。
d_func <- function(df, value=val, gr=NA) {
value_ = enquo(value)
gr_ = enquo(gr)
if (!is.na(gr)) {
df <- df %>% group_by(!!gr_)
}
df %>%
summarise(mean=mean(!!value_), mean_val=mean(val))
}
d_func(df, sss) # works
df %>% group_by(gah) %>% d_func(gr=fruit)
# Error in d_func(., gr = fruit) : object 'fruit' not found
d_func(df, gr=fruit)
# Error in d_func(df, gr = fruit) : object 'fruit' not found
df %>% group_by(gah) %>% d_func(sss, fruit)
# Error in d_func(., sss, fruit) : object 'fruit' not found
显然是由于!!gr_
在附加括号的范围内被称为;删除if和它的方括号,d_func
等效于b_func
,并且两个组都由列NA
组成。
我不明白为什么会这样或如何解决。
已使用sessionInfo更新
R version 3.4.4 (2018-03-15)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=Danish_Denmark.1252 LC_CTYPE=Danish_Denmark.1252 LC_MONETARY=Danish_Denmark.1252
[4] LC_NUMERIC=C LC_TIME=Danish_Denmark.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] rlang_0.2.0 bindrcpp_0.2.2 lemon_0.4.0 tidyr_0.8.0 magrittr_1.5
[6] dplyr_0.7.4 odbc_1.1.5 RevoUtils_10.0.9 RevoUtilsMath_10.0.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.16 pillar_1.2.1 compiler_3.4.4 plyr_1.8.4 bindr_0.1.1 tools_3.4.4
[7] bit_1.1-12 tibble_1.4.2 gtable_0.2.0 lattice_0.20-35 pkgconfig_2.0.1 openxlsx_4.0.17
[13] cli_1.0.0 rstudioapi_0.7 DBI_0.8 yaml_2.1.18 gridExtra_2.3 knitr_1.20
[19] hms_0.4.2 bit64_0.9-7 grid_3.4.4 tidyselect_0.2.4 glue_1.2.0 R6_2.2.2
[25] ggplot2_2.2.1.9000 purrr_0.2.4 blob_1.1.1 scales_0.5.0 assertthat_0.2.0 colorspace_1.3-2
[31] utf8_1.1.3 lazyeval_0.2.1 munsell_0.4.3 crayon_1.3.4
答案 0 :(得分:1)
一个较晚的答案,但是实现d_func
的问题在于,您正在混合使用同一变量的标准和非标准评估。您正在使用enquo
捕获调用环境中给gr
的表达式(非标准评估),同时测试变量gr
所保存的值是否为NA
(标准评估)。
在进行标准求值的情况下(如!is.na(gr)
),gr
将求值到变量fruit
所保存的值,而不是表达式fruit
。在您的情况下,从未定义变量fruit
。在akrun的情况下-library(tidyverse)
可能是谁-fruit
得出的预定义字符串向量来自stringr::fruit
,其中包含各种水果名称。
在任何一种情况下,这种行为都是不希望的。您的目标是仅在指定gr
的情况下执行特定的操作。 R提供了可用于此目的的原始函数missing()
。如果您更换
if (!is.na(gr)) {
与
if (!missing(gr)) {
所有四个测试用例都能按预期工作。