Как объединить ggplot и dplyr в функцию?

Рассмотрим этот простой пример

library(dplyr)
library(ggplot2)

dataframe <- data_frame(id = c(1,2,3,4),
                        group = c('a','b','c','c'),
                        value = c(200,400,120,300))

# A tibble: 4 x 3
     id group value
  <dbl> <chr> <dbl>
1     1     a   200
2     2     b   400
3     3     c   120
4     4     c   300

Здесь я хочу написать функцию, которая принимает в качестве входных данных фрейм данных и переменную группировки. В идеале, после группировки и агрегации я хотел бы распечатать диаграмму ggpplot.

Это работает:

get_charts2 <- function(data, mygroup){

  quo_var <- enquo(mygroup)

  df_agg <- data %>% 
    group_by(!!quo_var) %>% 
    summarize(mean = mean(value, na.rm = TRUE),
              count = n()) %>% 
    ungroup()

  df_agg
}



> get_charts2(dataframe, group)
# A tibble: 3 x 3
  group  mean count
  <chr> <dbl> <int>
1     a   200     1
2     b   400     1
3     c   210     2

К сожалению, добавив ggplot в функцию выше FAILS

 get_charts1 <- function(data, mygroup){

  quo_var <- enquo(mygroup)

  df_agg <- data %>% 
    group_by(!!quo_var) %>% 
    summarize(mean = mean(value, na.rm = TRUE),
              count = n()) %>% 
  ungroup()

  ggplot(df_agg, aes(x = count, y = mean, color = !!quo_var, group = !!quo_var)) + 
    geom_point() +
    geom_line() 
}


> get_charts1(dataframe, group)
Error in !quo_var : invalid argument type

Я не понимаю, что здесь не так. Есть идеи? Спасибо!

EDIT: интересное продолжение здесь как создать фактор-переменные из quosures в функциях с помощью ggplot и dplyr?

Ответ 1

ggplot пока не поддерживает tidy eval синтаксис (вы не можете использовать !!). Вам необходимо использовать более традиционные стандартные оценочные вызовы. Вы можете использовать aes_q в ggplot, чтобы помочь с этим.

get_charts1 <- function(data, mygroup){

  quo_var <- enquo(mygroup)

  df_agg <- data %>% 
    group_by(!!quo_var) %>% 
    summarize(mean = mean(value, na.rm = TRUE),
              count = n()) %>% 
    ungroup()

  ggplot(df_agg, aes_q(x = quote(count), y = quote(mean), color = quo_var, group = quo_var)) + 
    geom_point() +
    geom_line() 
}


get_charts1(dataframe, group)

Ответ 2

ggplot2 v3.0.0, выпущенный в июле 2018 года, поддерживает !! (bang bang), !!! и :=. aes_()/aes_q() и aes_string() мягко устарели.

OP оригинальный код должен работать

library(tidyverse)

get_charts1 <- function(data, mygroup){

  quo_var <- enquo(mygroup)

  df_agg <- data %>% 
    group_by(!!quo_var) %>% 
    summarize(mean = mean(value, na.rm = TRUE),
              count = n()) %>% 
    ungroup()

  ggplot(df_agg, aes(x = count, y = mean, 
                color = !!quo_var, group = !!quo_var)) + 
    geom_point() +
    geom_line() 
}

get_charts1(dataframe, group)

Редактировать: использование местоимения аккуратной оценки .data[] для вырезания выбранной переменной из фрейма данных также работает

get_charts2 <- function(data, mygroup){

  df_agg <- data %>% 
    group_by(.data[[mygroup]]) %>% 
    summarize(mean = mean(value, na.rm = TRUE),
              count = n()) %>% 
    ungroup()

  ggplot(df_agg, aes(x = count, y = mean, 
                     color = .data[[mygroup]], group = .data[[mygroup]])) + 
    geom_point() +
    geom_line() 
}

get_charts2(dataframe, "group")

Created on 2018-04-04 by the reprex package (v0.2.0).