R lazyeval: передать параметры в dplyr::filter

Я думаю, что этот вопрос имеет несколько других вариантов (например: здесь, здесь и, возможно, здесь) - возможно, даже где-то ответ.

Как предоставить параметры для функции фильтра.

library(dplyr)
library(lazyeval)
set.seed(10)
data <- data.frame(a=sample(1:10, 100, T))

Если мне нужно подсчитать количество вхождений встречающихся чисел от 1 до 10 и показать подсчет, скажем, 1, 2 и 3, я бы сделал это:

data %>% 
  group_by(a) %>% 
  summarise(n = n()) %>% 
  filter(a < 4)

дает:

# A tibble: 3 × 2
      a     n
  <int> <int>
1     1    11
2     2     8
3     3    16

Теперь, как я могу поместить это в функцию? Вот grp это группировка вар.

   fun <- function(d, grp, no){
      d %>% 
        group_by_(grp) %>% 
        summarise_(n = interp(~ n() )) %>%
        filter_( grp < no)
        # This final line instead also does not work:  
        # filter_(interp( grp < no), grp = as.name(grp))
    }

Сейчас,

fun(data, 'a', 4)

дает:

# A tibble: 0 × 2
# ... with 2 variables: a <int>, n <int>

1 ответ

Решение

Мы можем использовать подход с использованием quosures из версии devel dplyr (скоро выйдет 0.6.0)

fun <- function(d, grp, no){
   grp <- enquo(grp)

   d %>% 
      group_by(UQ(grp)) %>% 
      summarise(n = n() )%>%
       filter(UQ(grp) < no)

}

fun(data, a, 4)
# A tibble: 3 x 2
#      a     n
#  <int> <int>
#1     1    11
#2     2     8
#3     3    16

Мы используем enquo взять входной аргумент и преобразовать его в quosureв пределах group_by/summarise/mutate, оценка оценивается без кавычек (UQ или же !!)


Вышеприведенная функция также может быть изменена, чтобы принимать как кавычки, так и кавычки

fun <- function(d, grp, no){
   lst <- as.list(match.call())
   grp <- if(is.character(lst$grp)) {
              rlang::parse_quosure(grp)
            } else enquo(grp)


   d %>% 
      group_by(UQ(grp)) %>% 
      summarise(n = n() )%>%
       filter(UQ(grp) < no)

}




fun(data, a, 4)
# A tibble: 3 x 2
#      a     n
#  <int> <int>
#1     1    11
#2     2     8
#3     3    16

 fun(data, 'a', 4)
# A tibble: 3 x 2
#      a     n
#  <int> <int>
#1     1    11
#2     2     8
#3     3    16
Другие вопросы по тегам