【问题标题】:How to splice a tidyselect-style list of column names into a call of my function如何将 tidyselect 样式的列名列表拼接到我的函数的调用中
【发布时间】:2020-09-14 13:49:44
【问题描述】:

我正在尝试编写一个对我的分组数据框进行重复数据删除的函数。它断言每个组中的值都相同,然后只保留该组的第一行。我试图给它提供类似于pivot_longer() 中所见的类似tidyselect 的语义,因为我只需要将列名转发到summary(a = n_distinct(...)) 调用中。

举个例子

test <- tribble(
  ~G,  ~F, ~v1, ~v2,
  "A", "a",  1,   2,
  "A", "b",  1,   2, 
  "B", "a",  3,   3,
  "B", "b",  3,   3) %>%
  group_by(G)

我希望调用 remove_duplicates(test, c(v1, v2))(使用 tidyselect 助手 c() 返回

G   F  v1  v2
A   a   1   2
B   a   1   2

但我明白了

Error: `arg` must be a symbol

我尝试使用新的"embrace" 语法来解决这个问题(参见下面的函数代码),但失败并显示如上所示的消息。

# Assert that values in each group are identical and keep the first row of each
# group
# tab: A grouped tibble
# vars: <tidy-select> Columns expected to be constant throughout the group
remove_duplicates <- function(tab, vars){
  # Assert identical results for identical models and keep only the first per group.
  tab %>%
    summarise(a = n_distinct({{{vars}}}) == 1, .groups = "drop") %>%
    {stopifnot(all(.$a))}
  # Remove duplicates
  tab <- tab %>%
    slice(1) %>%
    ungroup() 
  return(tab)
}

我认为我需要以某种方式指定表达式vars 的评估上下文必须更改为tab 的子数据帧,该子数据帧目前正在由substitute 评估。 所以像

tab %>%
  summarise(a = do.call(n_distinct, TIDYSELECT_TO_LIST_OF_VECTORS(vars, context = CURRENT_GROUP))))

但我对技术细节的了解不足以真正完成这项工作......

【问题讨论】:

    标签: r tidyverse tidyselect


    【解决方案1】:

    如果您首先 enquos 您的 vars 然后在结果上使用 curly-curly 运算符,这将按预期工作:

    remove_duplicates <- function(tab, vars){
      
      vars <- enquos(vars)
    
      tab %>%
        summarise(a = n_distinct({{vars}}) == 1, .groups = "drop") %>%
        {stopifnot(all(.$a))}
    
      tab %>% slice(1) %>% ungroup()
    }
    

    那么现在

    remove_duplicates(test, c(v1, v2))
    #> # A tibble: 2 x 4
    #>   G     F        v1    v2
    #>   <chr> <chr> <dbl> <dbl>
    #> 1 A     a         1     2
    #> 2 B     a         3     3
    

    【讨论】:

    • 太棒了,谢谢!但是,我不明白为什么会有新的{{ 运算符。因为如果我写 !!vars 而不是 {{vars}} 它也可以。那么{{有什么好处呢?
    • @akraf 这似乎是 n_distinct 的问题,而不是您使用 curly-curly 运算符的方式。不知道是不是因为summarisen_distinct在内部都使用enquos
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 2021-09-09
    • 2017-04-17
    • 1970-01-01
    相关资源
    最近更新 更多