【问题标题】:Tibbles and data-defined column namesTibbles 和数据定义的列名
【发布时间】: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 %&gt;% 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}"

【问题讨论】:

    标签: r dplyr tibble


    【解决方案1】:

    一些问题在group_by,它会在across

    ds %>%
         group_by(across(all_of(myvar)))
    # A tibble: 3 x 2
    # Groups:   aa [3]
    #     aa    bb
    #  <dbl> <dbl>
    #1     1     4
    #2     2     5
    #3     3     6
    

    count

    ds %>% 
       count(across(all_of(myvar)))
    

    同样

     ds %>% 
         mutate(!! myvar := 11)  
    # A tibble: 3 x 2
    #     aa    bb
    #  <dbl> <dbl>
    #1    11     4
    #2    11     5
    #3    11     6
    

    complete 步骤有效

    ds %>% 
        complete(!!!rlang::syms(myvars))
    # A tibble: 9 x 2
    #     aa    bb
    #  <dbl> <dbl>
    #1     1     4
    #2     1     5
    #3     1     6
    #4     2     4
    #5     2     5
    #6     2     6
    #7     3     4
    #8     3     5
    #9     3     6
    

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 2020-07-10
      • 2020-02-24
      • 2021-06-13
      • 1970-01-01
      • 2016-07-14
      • 2010-11-20
      • 1970-01-01
      • 2013-08-25
      相关资源
      最近更新 更多