r语言 - quosure in case_when and/or ifelse



我正试图找出如何使用quosure(如果这是正确的工具)将变量名称传递给if_else(…)或case_when(…)内使用从函数传递的字符串参数的突变命令。一个快速可复制的例子,它分离了我的问题:

#create a simple 3x3 tibble
library(tidyverse)
lev<-c("a","b","c")
a=seq(1,3)
test<-tibble("index"=lev,"raw"=as.numeric(a),"x2"=a*2, x3 = a*3)

现在,假设我想替换"raw"在index=="a"的情况下为零。我可以使用原始代码:

test %>% 
mutate(raw=case_when(
(index=="a")~0,
TRUE~raw
)
)

,我得到输出:

# A tibble: 3 x 4
index   raw    x2    x3
<chr> <dbl> <dbl> <dbl>
1 a         0     2     3
2 b         2     4     6
3 c         3     6     9

完美。我可以用两种不同的方式在函数中做到这一点(if_else或case_when)。第一:

sending_test_cw<-function(data_sent)
{
data_sent %>% 
mutate(raw=case_when(
(index=="a")~0,
TRUE~raw)
)
}

的输出:

sending_test_cw(test)
R > sending_test_cw(test)
# A tibble: 3 x 4
index   raw    x2    x3
<chr> <dbl> <dbl> <dbl>
1 a         0     2     3
2 b         2     4     6
3 c         3     6     9

or, for case_when:

sending_test_ie<-function(data_sent)
{
data_sent %>% 
mutate(
raw=ifelse(index=="a",0,raw))
}
R > sending_test_ie(test)
# A tibble: 3 x 4
index   raw    x2    x3
<chr> <dbl> <dbl> <dbl>
1 a         0     2     3
2 b         2     4     6
3 c         3     6     9

,再次得到预期的输出。

现在,我想创建一个在发送名称时工作的函数保存索引的列的,像这样:

sending_test_qu<-function(data_sent,index_id="index")
{
index_quo<-enquo(index_id)
data_sent %>% 
#group_by(index)%>%
mutate(
raw=ifelse(!!index_quo=="a",0,raw),
raw_2=case_when(
(!!index_quo=="a")~0,
TRUE~raw)
)
}
sending_test_qu(test)

但是,我不能让那个工作工作。

sending_test_qu<-function(data_sent,index_id="index")
{
index_quo<-enquo(index_id)
data_sent %>% 
#group_by(index)%>%
mutate(
raw=ifelse(!!index_quo=="a",0,raw),
raw_2=case_when(
(!!index_quo=="a")~0,
TRUE~raw)
)
}
sending_test_qu(test)

生成如下输出:

R > sending_test_qu(test)
# A tibble: 3 x 5
index   raw    x2    x3 raw_2
<chr> <dbl> <dbl> <dbl> <dbl>
1 a         1     2     3     1
2 b         1     4     6     1
3 c         1     6     9     1

欢迎提出任何建议或引用。

转换为symbol,ensym作为输入字符串(也可以不加引号),如果输入不加引号,可以使用enquo!!,或者更直接使用{{}}

sending_test_qu<-function(data_sent,index_id="index")
{
index_sym<- rlang::ensym(index_id)
data_sent %>% 
#group_by(across(all_of(index_id)))%>%
mutate(
raw=ifelse(!!index_sym=="a",0,raw),
raw_2=case_when(
(!!index_sym=="a")~0,
TRUE~raw)
)
}

测试

# default argument value for index_id
> sending_test_qu(test)
A tibble: 3 × 5
index   raw    x2    x3 raw_2
<chr> <dbl> <dbl> <dbl> <dbl>
1 a         0     2     3     0
2 b         2     4     6     2
3 c         3     6     9     3
# pass as unquoted
> sending_test_qu(test, index)
# A tibble: 3 × 5
index   raw    x2    x3 raw_2
<chr> <dbl> <dbl> <dbl> <dbl>
1 a         0     2     3     0
2 b         2     4     6     2
3 c         3     6     9     3
# pass as string
> sending_test_qu(test, "index")
# A tibble: 3 × 5
index   raw    x2    x3 raw_2
<chr> <dbl> <dbl> <dbl> <dbl>
1 a         0     2     3     0
2 b         2     4     6     2
3 c         3     6     9     3

最新更新