dplyr group_by и резюмируем с нестандартной оценкой - PullRequest
3 голосов
/ 29 мая 2020

Предположим, у меня есть этот код:

> df<-data.frame(a=c(1,1,1,2,2,2), b=c(T,T,F,F,F,T))
> df %>% group_by(a) %>% summarize(trues=sum(b), falses=sum(!b))
# A tibble: 2 x 3
      a trues falses
  <dbl> <int>  <int>
1     1     2      1
2     2     1      2

, и я хочу использовать строковую переменную, чтобы получить b (например, для l oop). Это в точности похоже на этот вопрос Я думаю, но я не могу заставить его работать.

Некоторые неудачные попытки:

var <- 'b'

df %>% group_by(a) %>% summarize_(trues=sum(var), falses=sum(!var))
df %>% group_by(a) %>% summarize(trues=sum({{var}}), falses=sum(!{{var}}))
df %>% group_by(a) %>% summarize_(trues=sum({{var}}), falses=sum(!{{var}}))
foo1 <- function(df, var) {
  df %>% group_by(a) %>% summarize(trues=sum({{var}}), falses=sum(!{{var}}))
}
foo1(df, 'b')
foo2 <- function(df, var) {
  var <- enquo(var)
  df %>% group_by(a) %>% summarize(trues=sum(!!var), falses=sum(! !!var))
}
foo2(df, 'b')

Возможно, я мог бы использовать lazyeval в другом вопросе, но я бы предпочел знать, как это сделать, используя только тидиверс.

1 Ответ

3 голосов
/ 29 мая 2020

В этом случае лучше использовать ensym, поскольку мы передаем строку. Кроме того, ensym работает и с аргументом без кавычек

foo2 <- function(df, var) {
   var <- ensym(var)
   df %>% 
         group_by(a) %>%
         summarize(trues=sum(!!var), 
                   falses=sum(! (!!var)))
  }
foo2(df, 'b')
# A tibble: 2 x 3
#      a trues falses
#* <dbl> <int>  <int>
#1     1     2      1
#2     2     1      2


foo2(df, b)
# A tibble: 2 x 3
#      a trues falses
#* <dbl> <int>  <int>
#1     1     2      1
#2     2     1      2

Если переданный аргумент является объектом, оцените (!!) при передаче в функцию, чтобы избежать буквального вычисления

foo2(df, !!var)
# A tibble: 2 x 3
#      a trues falses
#* <dbl> <int>  <int>
#1     1     2      1
#2     2     1      2
...