整洁评估编程和ggplot2

12

我试图编写一个相对简单的包装器来生成一些图形,但是无法弄清如何指定作为 ... 指定的分组变量的整洁评估,例如对变量进行细分但不区分分组的示例函数...

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进行编程多次,但我仍然看不清楚或无法解决我的错误。

有人能指出我的错误/向我指明正确的方向吗?


在你的第二个函数中,为什么有两行带有 ggplot(aes(etc.)) 的代码? - FlorianGD
如果您在aes_中使用quo(...)而不是quos(...),那么事情会正常工作,例如aes_(~value, color = quo_group)。但也许您需要一些其他的分组变量列表? - aosmith
1
哦,我明白了,quos返回一个列表。因此,如果您只想使用从quos(...)获得的1个元素列表中的第一个元素,则需要在aes_中使用color = quo_group[[1]] - aosmith
@FlorianGD 有一个转录两个版本的错误,现在已经纠正。 - slackline
请看这里,我的朋友:https://dev59.com/_FcO5IYBdhLWcg3wbBA8 - ℕʘʘḆḽḘ
显示剩余3条评论
2个回答

3
新发布的 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包(v0.2.0.9000)于2018年9月12日创建的。


1
谢谢,我已经注意到ggplot2 v3.0.0解决了很多这些问题,唯一的缺点是我换了工作,因此不得不开始使用Python :-/ - slackline
现在你知道了PythonR,是不是很棒?恭喜你! - Tung
1
我不会说我已经精通Python,但我正在接近 ;-)了解设计模式和SOLID原则也是一条并发的学习曲线! - slackline

1

我不确定我理解这个问题。这是否满足要求?

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,因为当color=NULL时,aes(x=value, color=color)会失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接