for循环中的多个图忽略par

Posted

技术标签:

【中文标题】for循环中的多个图忽略par【英文标题】:Multiple plots in for loop ignoring par 【发布时间】:2018-11-28 11:21:02 【问题描述】:

我正在尝试生成 10 对图,每页图有几对,并且正在使用 for 循环来构建这些对。但是,绘图会作为单独的绘图而不是页面发送到设备。

下面的 MWE 具有基本图形和 ggplot 版本的相同结构,但基本图形有效,ggplot 无效。在第二个版本中,我需要做什么才能使分页正确?

library(ggplot2)
attach(mtcars)

# correct configuration
par(mfrow=c(2,2))
for (ii in 1:3)
  vars <- c("wt", "disp", "wt")
  plot(get(vars[ii]), mpg)
  hist(get(vars[ii]))


# places each on separate plot
par(mfrow=c(2,2))
for (ii in 1:3)
  vars <- c("wt", "disp", "wt")
  p <- ggplot(mtcars, aes(get(vars[ii]), mpg)) + geom_point(size=4)
  plot(p)
  p <- ggplot(mtcars, aes(get(vars[ii]))) + geom_histogram()
  plot(p)


detach(mtcars)

【问题讨论】:

par 不能在 ggplot 图形上运行,只能在基数 R 上运行。您是否想要对图进行刻面? 构面的潜在替代方案是gridExtra::grid.arrange;参见例如this post. 很高兴知道par 不可用。这不是facet 问题-不同的情节。我将不得不看看我是否可以使gridExtra::grid.arrangecowplot::plot_grid 足够灵活,以处理不命名个人地块的问题。 您可以尝试将您的图存储在一个列表中,以便使用您提到的包/功能。 【参考方案1】:

这是使用cowplot::plot_grid 的一种方法。 plot_duo 函数在ggplot2 v3.0.0 中使用tidyeval 方法

# install.packages("ggplot2", dependencies = TRUE)

library(rlang)
library(dplyr)
library(ggplot2)
library(cowplot)

plot_duo <- function(df, plot_var_x, plot_var_y) 

  if (is.character(plot_var_x)) 
    print('character column names supplied, use ensym()')
    plot_var_x <- ensym(plot_var_x)
   else 
    print('bare column names supplied, use enquo()')
    plot_var_x <- enquo(plot_var_x)
  

  if (is.character(plot_var_y)) 
    plot_var_y <- ensym(plot_var_y)
   else 
    plot_var_y <- enquo(plot_var_y)
  

  pts_plt <- ggplot(df, aes(x = !! plot_var_x, y = !! plot_var_y)) + geom_point(size = 4)
  his_plt <- ggplot(df, aes(x = !! plot_var_x)) + geom_histogram()

  duo_plot <- plot_grid(pts_plt, his_plt, ncol = 2)


### use character column names
plot_vars1 <- c("wt", "disp", "wt")
plt1 <- plot_vars1 %>% purrr::map(., ~ plot_duo(mtcars, .x, "mpg"))
#> [1] "character column names supplied, use ensym()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> [1] "character column names supplied, use ensym()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> [1] "character column names supplied, use ensym()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

plot_grid(plotlist = plt1, nrow = 3)

### use bare column names
plot_vars2 <- alist(wt, disp, wt)
plt2 <- plot_vars2 %>% purrr::map(., ~ plot_duo(mtcars, .x, "mpg"))
#> [1] "bare column names supplied, use enquo()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> [1] "bare column names supplied, use enquo()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> [1] "bare column names supplied, use enquo()"
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

plot_grid(plotlist = plt2, nrow = 3)

要将绘图分成多个页面,我们可以使用gridExtra::marrangeGrob

ml1 <- marrangeGrob(plt, nrow = 2, ncol = 1)

# Interactive use
ml1

# Non-interactive use, multipage pdf
ggsave("multipage.pdf", ml1)

【讨论】:

谢谢。这几乎可以工作。在我的 MWE 中,您可以看到我正在生成 6 个图,第一个“页面”为 2x2,第二个“页面”为 2x1。我已经根据我的真实数据调整了您的代码,但是do.call 将所有图表放在一个页面上。有没有办法强制 2x2 限制,以便为每 4 个子图创建一个单独的图?

以上是关于for循环中的多个图忽略par的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB R2014b 中的 MATLAB Coder 和 parfor

具有并行工具箱的 Matlab 独立应用程序(已部署应用程序中的 parfor 循环)

为啥'continue'语句忽略'while'循环中的循环计数器增量,而不是'for'循环?

为啥它会忽略我在 for 循环中的继续? [关闭]

为什么递归循环中的局部变量被忽略? For循环中的Java递归循环

在 R 中使用 for 循环绘制多个图