【问题标题】:Tidy evaluation programming and ggplot2整洁的评估编程和ggplot2
【发布时间】:2017-11-16 20:16:25
【问题描述】:

试图编写一个相对简单的包装器来生成一些图,但不知道如何指定对指定为... 的分组变量的整洁评估,这是一个对变量进行分面但不通过分组进行区分的示例函数...

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

现在我读了好几遍Programming with dplyr 之后,我看不到或想不出哪里出错了。

谁能指出我的错误/给我指路?

【问题讨论】:

  • 在你的第二个函数中,为什么你有两行 ggplot(aes(etc.))
  • 如果您使用quo(...) 而不是quos(...),那么aes_aes_(~value, color = quo_group) 中一切正常。但也许你需要一个分组变量列表来做别的事情?
  • 哦,我明白了,quos 返回一个列表。因此,如果您只想使用从 quos(...) 获取的 1 元素列表的第一个元素,则需要在 aes_ 中使用 color = quo_group[[1]]
  • @FlorianGD 转录两个版本时出错,现已更正。
  • @aosmith quo_group[[1]] 可以解决问题,但似乎与 Programming with dplyr : capturing multiple variables 文档不一致。

标签: r ggplot2 dplyr rlang tidyeval


【解决方案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)

reprex package (v0.2.0.9000) 于 2018 年 9 月 12 日创建。

【讨论】:

  • 谢谢,我认为 ggplot2 v3.0.0 解决了很多这些问题,对我来说唯一的缺点是我换了工作,因此不得不开始使用 Python :-/
  • 现在您知道PythonR。那不是很棒吗?恭喜!
  • 我不会说我知道 Python,但我已经到了 ;-) 理解设计模式和 SOLID 原则也是一个并行的学习曲线!
【解决方案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 变量,并为每个堆叠重复color 变量。它还使用aes_string,因为aes(x=value, color=color)color=NULL 时失败。

【讨论】:

    猜你喜欢
    • 2019-04-12
    • 2018-06-10
    • 2018-06-09
    • 2020-04-28
    • 1970-01-01
    • 2020-11-29
    • 2021-12-01
    • 1970-01-01
    • 2023-01-24
    相关资源
    最近更新 更多