首页 > 解决方案 > 让 quosures 在地图调用中工作

问题描述

我正在努力让 quosures 在map通话中工作。

一些玩具数据:

library(tidyverse)

df <- tibble(
   g1 = letters[1:2] %>% 
     rep(each = 3),
   g2 = letters[3:5] %>% 
     rep(times = 2),
   y = runif(6)
  )

我可以让这个函数工作,在enquo我将它传递给之前我是一个变量group_by

sum1 <- function(df, g){

 g <- enquo(g)

 df %>% 
   group_by(!! g) %>% 
   summarize(
     mu = y %>% 
       mean
     )
  }

调用这个函数

 sum1(df, g2)

让我得到预期的结果。但是如果我想map超过多个分组变量,(即g1& g2

 str_c("g", 1:2) %>% 
   map(
    function(i)
      sum1(df, i)
   )

返回错误

  Error in grouped_df_impl(data, unname(vars), drop) : 
   Column `i` is unknown 

如何quosuresmap通话中进行设置?

标签: rdplyrrlangtidyeval

解决方案


我们可以使用group_by_at它可以将字符串作为参数

library(tidyverse)
sum1 <- function(df, grps){

 map(grps, ~ 
           df %>%
              group_by_at(.x) %>%
              summarise(mu = mean(y))
              )

              }

sum1(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
#  g1       mu
#  <chr> <dbl>
#1 a     0.440
#2 b     0.469

#[[2]]
# A tibble: 3 x 2
#  g2       mu
#  <chr> <dbl>
#1 c     0.528
#2 d     0.592
#3 e     0.243

关于函数中带quosure的参数的使用,不清楚是单参数还是多参数

如果我们将字符串作为参数,请将其转换为符号 ( sym),然后计算 ( !!)

sum2 <- function(df, grps){


 map(grps, ~ 
           df %>%
              group_by(!! rlang::sym(.x)) %>%
              summarise(mu = mean(y))
              )

              }

sum2(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
#  g1       mu
#  <chr> <dbl>
#1 a     0.440
#2 b     0.469

#[[2]]
# A tibble: 3 x 2
#  g2       mu
#  <chr> <dbl>
#1 c     0.528
#2 d     0.592
#3 e     0.243

另一个可以通过多个组的方法是

sum3 <- function(df, ...){

   gs <- enquos(...)
   map(gs, ~ 
         df %>%
            group_by(!! .x) %>%
            summarise(mu = mean(y)))


              }
sum3(df, g1, g2)
#[[1]]
# A tibble: 2 x 2
#  g1       mu
#  <chr> <dbl>
#1 a     0.440
#2 b     0.469

#[[2]]
# A tibble: 3 x 2
#  g2       mu
#  <chr> <dbl>
#1 c     0.528
#2 d     0.592
#3 e     0.243

推荐阅读