【问题标题】:Preserve panel size across differing numbers of panels in ggplot在 ggplot 中保留不同数量面板的面板大小
【发布时间】:2019-11-06 17:20:37
【问题描述】:

我想绘制来自不同数据帧的两个图,然后将它们组合成一个图(最终图更复杂)。每个图显示了两个分类变量(例如“性别”和“圆形”)的数据子集。绘制的数据在两个图中都是相同的类型。每个数据集在这些分类变量的级别数上有所不同。

例如,这里是绘制在 3 x 2 网格中的模拟数据:

require(ggplot2)
set.seed(10)

# Mock data
N <- 10
rounds <- c("A", "B", "C")
NROUNDS <- length(rounds)

df1 <- data.frame(
    Age = 1:N, 
    Response = rnorm(N*2*NROUNDS), 
    Sex = rep(c("M", "F"), each = N), 
    Round = rep(rounds, each = N*2)
)

# Dimension parameters
panel_width <- 2.5
panel_height <- 1.5
ylims <- c(-4, 4)
units <- "in"
panel_spacing <- 0.1
plot_mar <- 0.25

total_x_margin <- panel_spacing + plot_mar*2
total_y_margin <- panel_spacing*(NROUNDS-1) + plot_mar*2

# Plot the figure
six_panel_plot <- ggplot(df1, aes(x = Age, y = Response)) + 
    geom_line(lwd = 2, color = "#CC79A7") + 
    facet_grid(rows = vars(Round), cols = vars(Sex)) + 
    ylim(ylims) + 
    theme(
        panel.spacing.x = unit(panel_spacing, units),
        panel.spacing.y = unit(panel_spacing, units),
        plot.margin = margin(plot_mar, plot_mar, plot_mar, plot_mar, units)
    ) + theme_bw()

# Save the figure
ggsave("six_panel_plot.png", six_panel_plot, 
    width = total_x_margin + panel_width*2, 
    height = total_y_margin + panel_height*NROUNDS)

我尝试根据每个维度中的面板数量和边距大小来调整图形大小。但是,如果在 4 x 2 网格上创建类似的图形,则各个面板的尺寸与上一个图形并不完全相同。

# Mock data
N <- 10
rounds <- c("A", "B", "C", "D")
NROUNDS <- length(rounds)

df2 <- data.frame(
    Age = 1:N, 
    Response = rnorm(N*2*NROUNDS), 
    Sex = rep(c("M", "F"), each = N), 
    Round = rep(rounds, each = N*2)
)


# Dimension parameters
panel_width <- 2.5
panel_height <- 1.5
ylims <- c(-4, 4)
units <- "in"
panel_spacing <- 0.1
plot_mar <- 0.25

total_x_margin <- panel_spacing + plot_mar*2
total_y_margin <- panel_spacing*(NROUNDS-1) + plot_mar*2


eight_panel_plot <- ggplot(df2, aes(x = Age, y = Response)) + 
    geom_line(lwd = 2, color = "#CC79A7") + 
    facet_grid(rows = vars(Round), cols = vars(Sex)) + 
    ylim(ylims) + 
    theme(
        panel.spacing.x = unit(panel_spacing, units),
        panel.spacing.y = unit(panel_spacing, units),
        plot.margin = margin(plot_mar, plot_mar, plot_mar, plot_mar, units)
    ) + theme_bw()

ggsave("eight_panel_plot.png", eight_panel_plot, 
    width = total_x_margin + panel_width*2, 
    height = total_y_margin + panel_height*NROUNDS)

如果我在其他软件(Inkscape、Illustrator 等)中对齐这些图形,则面板的尺寸不同。

我如何保持各个面板 的大小(而不是简单地强制第一个图有四行)?我想避免使用额外的包,这可能只用 ggplot2 吗?

【问题讨论】:

    标签: r ggplot2 visualization


    【解决方案1】:

    我没有 ggplot-only 解决方案,但我将使用 ggplot 本身所依赖的一些包(grid & gtable),因此无需额外下载。我假设所需的单位是以英寸为单位定义的,但它很容易更改。

    library(grid)
    
    # As per your post
    panel_width <- 2.5
    panel_height <- 1.5
    
    # Convert plot to gtables
    plots <- list(p8 = ggplotGrob(eight_panel_plot), 
                  p6 = ggplotGrob(six_panel_plot))
    
    plots <- lapply(plots, function(gt) {
      # Find the positions of panels
      panel_x <- unique(panel_cols(gt)$l)
      panel_y <- unique(panel_rows(gt)$t)
      # Change the sizes of these positions
      gt$widths[panel_x] <- unit(panel_width, "inch")
      gt$heights[panel_y] <- unit(panel_height, "inch")
      gt
    })
    
    ggsave("test1.png", plot = plots[[1]])
    ggsave("test2.png", plot = plots[[2]])
    

    test1.png:

    test2.png:

    【讨论】:

      【解决方案2】:

      你可以试试 egg::set_panel_size()

      【讨论】:

      • 请用示例添加答案。避免写单行答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 1970-01-01
      • 2015-12-31
      • 2018-10-11
      • 1970-01-01
      相关资源
      最近更新 更多