如何管道化ggplot对象?

时间:2016-11-16 16:18:26

标签: r ggplot2 pipe

我想使用带有magrittr管道的ggplot对象定义的自定义函数。但是,我无法将ggplot对象传递给此函数。

这是一个简单的例子:

library(ggplot2)
library(magrittr)

my_plot_function <- function(plot) {
    plot + geom_hline(yintercept = 3, linetype = 'dashed')
}

data(mtcars)
p <- mtcars %>%
    ggplot() +
    geom_point(aes(mpg, wt))
my_plot_function(p)

如果我可以在链中使用my_plot_function(),那将会很棒:

mtcars %>%
    ggplot() +
    geom_point(aes(mpg, wt)) %>%
    my_plot_function()

但是,它会产生错误,因为只有图层传递给my_plot_function()而不是图本身。我怎么能用管子传递图?

4 个答案:

答案 0 :(得分:3)

您可以尝试定义一个不期望绘图对象的函数,只需像foreach中那样添加它。

ggplot

答案 1 :(得分:2)

对于一个您建议的参数函数,可以通过定义-.gg使用以下技巧:

`-.gg` <- function(e1, e2) e2(e1)

my_plot_function <- function(plot) {
  plot + geom_hline(yintercept = 3, linetype = 'dashed')
}

mtcars %>%
  ggplot() +
  geom_point(aes(mpg, wt)) -
  my_plot_function

绘制图表


我经常使用此技巧来使用ggplotly

library(plotly)
mtcars %>%
  ggplot() +
  geom_point(aes(mpg, wt)) -
  ggplotly

绘制交互式图表


或绘制中间图表

mtcars %>%
  ggplot() +
  geom_point(aes(mpg, wt)) -
  plot +
  facet_wrap(~cyl)

绘制2张图表


对于多参数函数,可以使用purrr::partial

my_plot_function2 <- function(plot, msg) {
  print(msg)
  plot + geom_hline(yintercept = 3, linetype = 'dashed')
}

library(purrr)
mtcars %>%
  ggplot() +
  geom_point(aes(mpg, wt)) -
  partial(my_plot_function2, msg="hello")
# [1] "hello"

...并绘制图表


动态定义一个函数,在此示例中,编辑图的数据:

mtcars %>%
  ggplot() +
  geom_point(aes(mpg, wt)) -
  as_mapper(~{.$data <- head(.$data);.})

绘制6点图表


我认为这足以容纳在软件包中,因此I wrote one可以与devtools::install_github("moodymudskipper/ggfun")安装。

上面的示例可以工作,但是您必须使用+而不是-,我覆盖了+.gg并定义了-.gg才能将函数应用于对象的数据( README上有更多内容。

答案 2 :(得分:1)

您将需要根据建议将整个链包装在()中。这是一个接受的答案模板失败的示例:

library(ggplot2)
library(magrittr)

my_plot_function <- function() {
    geom_hline(yintercept = 3, linetype = 'dashed') +
    geom_vline(xintercept = 20, linetype = 'dotted')
}
my_plot_function2 <- function(plot) {
    plot + geom_hline(yintercept = 3, linetype = 'dashed') +
    geom_vline(xintercept = 20, linetype = 'dotted')
}
data(mtcars)

以下内容将引发错误:

mtcars %>%
    ggplot() +
    geom_point(aes(mpg, wt)) + my_plot_function()

以下将起作用:

(mtcars %>%
    ggplot() + geom_point(aes(mpg, wt))) %>%
    my_plot_function2()

如果要保持数据链分离,可以在ggplot()调用周围使用匿名函数:

mtcars %>%
    (function(dat) ggplot(dat) + geom_point(aes(mpg, wt))) %>%
    my_plot_function2()

答案 3 :(得分:0)

如果您确实需要一个必须有参数的函数,那么 wrapr 的点箭头管道 %.>% 可以完美地替代 +。然后您必须指定 . 作为您函数的输入。

Documentation


另一个可能更简单的选择是在函数中返回一个列表。示例:

foo <- function() {
  Out <- list(
    theme(
      panel.grid.major = element_blank(),
      panel.grid.minor = element_blank(),
      axis.line = element_line(colour="black"),
    expand_limits(x = 0, y = 0),
    scale_x_continuous(expand = c(0, 0)),
    scale_y_continuous(expand = c(0, 0))
  )

  return(Out)
}

后一种替代方案的用处在于标准化您的图形变得更加容易,例如使用定制的主题也需要对非主题功能进行一些更改(如上例所示)