【发布时间】:2021-01-11 17:45:20
【问题描述】:
我在自己的函数中使用 tibbles,通常接受变量名作为参数。所以基本上,而不是做
tibble %>% do_something(foo)
我做了很多
function(bar){
tibble %>% do_something(bar)
}
我对定义列名的不同方式感到困惑,具体取决于上下文:尽管它通过反复试验而起作用,而且我开始理解为什么,但我会重视清晰的总结 + 解释。有些函数需要一个带有列名的字符向量(它们是最简单的使用),我认为有些函数需要符号(如果我错了,请纠正我),有时两者都不起作用,有时两者都起作用,有时不同的方法起作用但是给出不同的结果:
bar
get(bar)
!!!rlang:::sym(bar)
all_of(bar)
让我们探索一下:
ds <- tibble(aa=c(1,2,3),bb=c(4,5,6))
myvar <- "aa"
myvars <- c("aa","bb")
1) 首先,我们的函数似乎可以使用字符向量:
参数被明确描述为 char:
ds %>% left_join(ds,by=myvar)
参数被描述为 tidy-select:
ds %>% select(all_of(myvars)) # Ok
ds %>% select(myvars)
# NOT ds %>% select(get(myvar))
ds %>% select(!!!rlang::syms(myvars))
好的,所以我已经不明白了。 select() 接受一个或多个字符串向量或符号。但为什么它不接受 get(myvar) ? myvar的值是字符串“aa”,为什么不等于ds %>% select("aa")?
ds %>% summarise(across( all_of(myvars), max ))
ds %>% summarise(across( myvars, max ))
# NOT ds %>% summarise(across(get(myvars),max))
# NOT ds %>% summarise(across( !!!rlang::syms(myvars) , max ))
尽管across() 声称接受 tidy-select 语法,但这似乎仅在有限的意义上是正确的(它接受字符但不接受符号,不像 select 消化两者)。
2) 然后,我们的函数似乎可以处理符号:
Arg 是“分组依据的变量或计算”= 一个符号?
ds %>% group_by(!!!rlang:::syms(myvar) )
ds %>% group_by(get(myvar))
ds %>% group_by(all_of(myvar))
# But NOT ds %>% group_by(myvar)
所有三个工作,但给出不同的结果......
Arg 是数据屏蔽
ds %>% count(get(myvar))
ds %>% count(!!!rlang::syms(myvar))
# But:
ds %>% count(all_of(myvar))# Works, but NOT the same result !
ds %>% filter(get(myvar)==1)
ds %>% filter(.data[[myvar]] == 1)
# NOT ds %>% filter(!!!rlang:::syms(myvar)==1)
ds %>% mutate(cc=myvar) # Works, but fills cc with the string "aa"
ds %>% mutate(cc=get(myvar))
ds %>% mutate(cc=.data[[myvar]])
# NOT ds %>% mutate(cc=!!!rlang::syms(myvar))
ds %>% mutate(myvar=11) # Works, by creating a column called "myvar"
ds %>% mutate(.data[[myvar]] * 0 +11) # Works similarly
# NOT ds %>% mutate(get(myvar)=11)
# NOT ds %>% mutate(!!!rlang::syms(myvar)=11)
终于...
我们在这里引入一种全新的语法!
ds %>% mutate("{myvar}" := 11)
Arg 是“要扩展的列的规范”
ds %>% complete(!!!rlang::syms(myvars))
# NOT ds %>% complete(get(myvars))
# Error: Join columns must be present in data.
# x Problem with `get(myvars)`.
存在一个已知问题
# NOT ds %>% complete(myvars)
# NOT ds %>% complete(all_of(myvars))
原则上,应该可以使用 tidy-select 语法 (all_of) 传递列的名称,但是从 2021 年初开始,这不起作用 (https://github.com/tidyverse/tidyr/issues/1033)
所以,简而言之:有人可以解释我何时(以及为什么)使用以下内容吗?
bar
get(bar)
!!!rlang:::sym(bar)
all_of(bar)
"{myvar}"
【问题讨论】: