Упрощение программирования программирования и ggplot2

Попытка написать относительно простую оболочку для создания некоторых графиков, но не может решить, как указать аккуратную оценку группирующих переменных, указанную как ... примерную функцию, которая граничит с переменными, но не различает их группировкой...

my_plot <- function(df = starwars,
                    select = c(height, mass),
                    ...){
    results <- list()
    ## Tidyeval arguments
    quo_select <- enquo(select)
    quo_group  <- quos(...)
    ## Filter, reshape and plot
    results$df <- df %>%
                  dplyr::filter(!is.na(!!!quo_group)) %>%
                  dplyr::select(!!quo_select, !!!quo_group) %>%
                  gather(key = variable, value = value, !!!quo_select) %>% 
                  ## Specify what to plot
                  ggplot(aes(value)) +
                  geom_histogram(stat = 'count')  +
                  facet_wrap(~variable, scales = 'free', strip.position = 'bottom')
    return(results)
}
## Plot height and mass as facets but colour histograms by hair_color
my_plot(df = starwars, select = c(height, mass), hair_color)

Отлично, но как отличить разные hair_color? Обычно это делается в aes(), но поскольку это использует результаты quos() (т.е. quo_group), я должен (я думаю) использовать aes_() вместо

my_plot <- function(df = starwars,
                    select = c(height, mass),
                    ...){
    results <- list()
    ## Tidyeval arguments
    quo_select <- enquo(select)
    quo_group  <- quos(...)
    ## Filter, reshape and plot
    results$df <- df %>%
                  dplyr::filter(!is.na(!!!quo_group)) %>%
                  dplyr::select(!!quo_select, !!!quo_group) %>%
                  gather(key = variable, value = value, !!!quo_select) %>% 
                  ## Specify what to plot, including colouring by the supplied ... groupings
                  ggplot(aes_(~value, colour = !!!quo_group)) + 
                  geom_histogram(stat = 'count')  +
                  facet_wrap(~variable, scales = 'free', strip.position = 'bottom')
    return(results)
}
## Plot height and mass as facets but colour histograms by hair_color
my_plot(df = starwars, select = c(height, mass), hair_color)
Error in !quo_group : invalid argument type

Я не вижу или не читаю Программирование с dplyr несколько раз, когда я ошибаюсь.

Может ли кто-нибудь указать мою ошибку/показать мне путь?

Ответ 1

Новый выпущенный ggplot2 v3.0.0 поддерживает !! внутри aes(). С некоторыми незначительными изменениями ваша функция теперь работает

library(tidyverse)

my_plot <- function(df = starwars,
                    select = c(height, mass),
                    ...){
  results <- list()

  ## Tidyeval arguments
  quo_select <- enquo(select)

  # only need quo here, if quos is used then we need to 'unlist' to 
  # convert its output from list to vector
  quo_group  <- quo(...) 

  ## Filter, reshape and plot
  results$df <- df %>%
    dplyr::filter(!is.na(!!!quo_group)) %>%
    dplyr::select(!!quo_select, !!!quo_group) %>%
    gather(key = variable, value = value, !!!quo_select) %>% 
    ## Specify what to plot, including coloring by the supplied dots '...' 
    ggplot(aes(value, color = !!quo_group, fill = !!quo_group)) +  # unquote inside aes
    geom_histogram(stat = 'count')  +
    facet_wrap(vars(variable), scales = 'free', strip.position = 'bottom')
  return(results)
}

## Plot height and mass as facets but color histograms by hair_color
my_plot(df = starwars, select = c(height, mass), hair_color)

Создано 2018-09-12 пакетом представлением (v0.2.0.9000).

Ответ 2

Я не уверен, что понимаю этот вопрос. Соответствует ли это требованиям?

library(ggplot2)
library(data.table)

your_plot <- function(df, select, color=NULL) {

  df <- as.data.table(df)[, mget(na.omit(c(select, color)))]

  ggplot(melt(df, color, select), aes_string(x=quote(value), color=color)) +
    geom_histogram(stat="count") +
    facet_wrap(~variable, scales="free", strip.position="bottom")

}

your_plot(dplyr::starwars, c("height", "mass"), "hair_color")

Используется melt для стека переменных select с переменной (t23) color, повторяемой для каждого стека. Он также использует aes_string, поскольку aes(x=value, color=color) терпит неудачу, если color=NULL.