Чистое оценочное программирование и 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, где я ' м иду не так.

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


person slackline    schedule 14.06.2017    source источник
comment
Почему во второй функции у вас есть две строки с ggplot(aes(etc.))?   -  person FlorianGD    schedule 14.06.2017
comment
Если вы используете quo(...) вместо quos(...), тогда все работает нормально в aes_ а-ля aes_(~value, color = quo_group). Но, может быть, вам нужен список группирующих переменных для чего-то еще?   -  person aosmith    schedule 14.06.2017
comment
О, понятно, quos возвращает список. Поэтому, если вы хотите использовать только первый элемент списка 1 элемента, полученного из quos(...), вам понадобится color = quo_group[[1]] в aes_.   -  person aosmith    schedule 14.06.2017
comment
@FlorianGD - ошибка при расшифровке двух версий, теперь исправленная.   -  person slackline    schedule 14.06.2017
comment
@aosmith quo_group[[1]] делает свое дело, но, похоже, противоречит Программирование с dplyr : захват нескольких переменных документации.   -  person slackline    schedule 14.06.2017
comment
@slackline Я согласен, но я не уверен, как захват нескольких переменных сочетается с отображением отдельных переменных в эстетике. Похоже, что для сопоставления переменных вам нужно захватить только одну переменную, и у вас будет конкретный аргумент для этого в вашей функции. Я думаю, может быть, мы увидим, как только ggplot2 будет перенесен в аккуратную платформу оценки!   -  person aosmith    schedule 14.06.2017
comment
@aosmith да, мне придется перенастроить параметры для моей функции. С нетерпением жду полных подробностей тидевала в ggplot2.   -  person slackline    schedule 14.06.2017
comment
см. здесь мой человек stackoverflow.com/questions/45824409/   -  person ℕʘʘḆḽḘ    schedule 24.08.2017


Ответы (2)


Новый выпущенный 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)

Создано 12 сентября 2018 г. пакетом REPEX (v0.2.0.9000).

person Tung    schedule 12.09.2018
comment
Спасибо, я заметил, что ggplot2 v3.0.0 решает многие из этих проблем, единственным недостатком для меня является то, что я сменил работу, и, как следствие, мне пришлось начать использовать Python: - / - person slackline; 12.09.2018
comment
Теперь вы знаете и Python, и R. Разве это не здорово? Поздравляю! - person Tung; 12.09.2018
comment
Я бы еще не сказал, что знаю Python, но я уже добился этого ;-) Понимание шаблонов проектирования и принципов SOLID также требует одновременного обучения! - person slackline; 12.09.2018

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

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 переменных, при этом переменная (и) color повторяется для каждого стека. Он также использует aes_string, поскольку aes(x=value, color=color) не работает, когда color=NULL.

person dnlbrky    schedule 08.02.2018