rlang 和 enquo 在括号内不起作用
rlang and enquo does not work inside brackets
我正在尝试编写一个在 data.frame 上运行的函数,并将接受 dplyr 样式的参数,即未使用 dplyr 的代名词(或我们称之为的任何东西)引用的列名。
但是我在括号表达式中使用 !!
时遇到了问题(见下面的示例)。
示例:
先一个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
时进行分组,
从括号内寻找 quosure 是行不通的。
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
有点晚了,但是您实施 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)) {
您的所有四个测试用例都将按预期工作。
我正在尝试编写一个在 data.frame 上运行的函数,并将接受 dplyr 样式的参数,即未使用 dplyr 的代名词(或我们称之为的任何东西)引用的列名。
但是我在括号表达式中使用 !!
时遇到了问题(见下面的示例)。
示例:
先一个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
时进行分组,
从括号内寻找 quosure 是行不通的。
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
有点晚了,但是您实施 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)) {
您的所有四个测试用例都将按预期工作。