3

我正在构建一个自定义 ggplot 主题来标准化我生成的图形的外观和感觉。目标比这个最小的例子更复杂,所以我正在寻找一个通用的解决方案。我有几个关键目标:

  • 我希望所有图表都以相同的大小(3000 像素宽,1500 像素高)导出。
  • 我想控制绘图面板本身的纵横比。
  • 我想使用 textGrob 来包含数字。
  • 我希望图像左对齐

我面临的挑战是,当结合这两个约束时,保存的图像在窗口中居中 ggplot 图,这在默认情况下是有意义的,但在这种情况下看起来很糟糕。

我希望在导出时有一个通用的解决方案来左对齐 ggplot 面板。理想情况下,这也适用于多面图。

似乎使用 gridExtra、gtable、cowplot 和 egg 包中的一个或某种组合应该可以实现某些事情,但是在试验了几个小时之后,我有点不知所措。有谁知道我怎么能做到这一点?我的代码包含在下面。

这是生成的图像。如您所见,标题在底部左对齐,但 ggplot 本身是水平居中的。我也希望 ggplot 图左对齐。

图表输出:https ://i.stack.imgur.com/5EM2c.png

library(ggplot2)

# Generate dummy data
x <- paste0("var", seq(1,10))
y <- LETTERS[1:10]
data <- expand.grid(X=x, Y=y)
data$Z <- runif(100, -2, 2)

# Generate heatmap with fixed aspect ratio
p1 <- ggplot(data, aes(X, Y, fill= Z)) + 
    geom_tile() +
    labs(title = 'A Heatmap Graph') +
    theme(aspect.ratio = 1)


# A text grob for the footer
figure_number_grob <- grid::textGrob('Figure 10',
                                     x = 0.004,
                                     hjust = 0,
                                     gp = grid::gpar(fontsize = 10,
                                                     col = '#01A184'))

plot_grid <- ggpubr::ggarrange(p1,
                               figure_number_grob,
                               ncol = 1,
                               nrow = 2,
                               heights = c(1,
                                           0.05))

# save it
png(filename = '~/test.png', width = 3000, height = 1500, res = 300, type = 'cairo')
print(plot_grid)
dev.off()
4

1 回答 1

0

我能够找到一个适合我需要的解决方案,尽管它确实感觉有点老套。

这是核心思想:

  • 生成没有固定纵横比的绘图。
  • 将图例从图中拆分为自己的组件
  • 使用 GridExtra 的arrangeGrob 将绘图、一个分隔符、图例和另一个分隔符水平组合
  • 将绘图的宽度设置为 npc(正常父坐标)的一部分,在本例中为 0.5。这意味着绘图将占用输出文件水平空间的 50%。
    • 请注意,这与为绘图设置固定纵横比并不完全相同。如果您知道输出文件的大小,它几乎是一样的,但是轴文本和轴标题的大小会影响面板本身的输出纵横比,所以虽然它让您接近,但如果您需要,它并不理想真正固定的纵横比
  • 将垫片的宽度设置为 npc 的剩余部分(在本例中,再次为 0.5),减去图例的宽度,以使图例在剩余空间中水平居中。

这是我的代码:

library(ggplot2)

# Generate dummy data
x <- paste0("var", seq(1,10))
y <- LETTERS[1:10]
data <- expand.grid(X=x, Y=y)
data$Z <- runif(100, -2, 2)

# Generate heatmap WITHOUT fixed aspect ratio. I address this below
p1 <- ggplot(data, aes(X, Y, fill= Z)) + 
    geom_tile() +
    labs(title = 'A Heatmap Graph')

# Extract the legend from our plot
legend = gtable::gtable_filter(ggplotGrob(p1), "guide-box")


plot_output <- gridExtra::arrangeGrob(
    p1 + theme(legend.position="none"),                           # Remove legend from base plot
    grid::rectGrob(gp=grid::gpar(col=NA)),                        # Add a spacer
    legend,                                                       # Add the legend back
    grid::rectGrob(gp=grid::gpar(col=NA)),                        # Add a spacer
    nrow=1,                                                       # Format plots in 1 row
    widths=grid::unit.c(unit(0.5, "npc"),                         # Plot takes up half of width
                        (unit(0.5, "npc") - legend$width) * 0.5,  # Spacer width
                        legend$width,                             # Legend width
                        (unit(0.5, "npc") - legend$width) * 0.5)) # Spacer width

# A text grob for the footer
figure_number_grob <- grid::textGrob('Figure 10',
                                     x = 0.004,
                                     hjust = 0,
                                     gp = grid::gpar(fontsize = 10,
                                                     col = '#01A184'))

plot_grid <- ggpubr::ggarrange(plot_output,
                               figure_number_grob,
                               ncol = 1,
                               nrow = 2,
                               heights = c(1,
                                           0.05))

# save it
png(filename = '~/test.png', width = 3000, height = 1500, res = 300, type = 'cairo')
print(plot_grid)
dev.off()

这是输出图像:https ://i.stack.imgur.com/rgzFy.png

于 2020-04-17T13:43:33.747 回答