在多个 ggplot 的 {patchwork} 中添加纯文本部分的最佳方法?

Pau*_*idt 8 r ggplot2 patchwork ggtext

当使用{patchwork}将单独的 ggplots 组合成同一个图形时,我有时想添加一个或多个根本不是绘图的部分,但基本上是一个文本框。

据我所知,拼凑文档中唯一一次解决这个问题是在这里使用wrap_elements(grid::textGrob('Text on left side')). 然而,这是行不通的,因为我想使用{ggtext}主要是为了(i)自动换行和(ii)混合常规、斜体、粗体和彩色文本(参见例如此处)。

到目前为止,我已经找到了两种不同的方法来实现这项工作,它们在下面的 reprex 中进行了演示。两种方法的共同点是它们基本上隐藏了 ggplot 中不是所需文本的所有部分。

  • 第一种方法(灵感来自此处:绘图相关代码)将文本添加为ggtext::geom_textbox()​​ 。
  • 第二种方法(灵感来自这里:绘图相关代码)将文本添加为subtitle​​ with theme(plot.subtitle = ggtext::element_markdown())

问题

然而,我的问题是,是否有更好/更简单的方法来实现这一点。主要是因为正如您在下面的 reprex 中看到的那样,在文本正确排列之前需要进行一些margin()操作。plot_layout()

我可以想到对于此文本我想要两种不同的垂直对齐方式:

  1. 这样它就从与左图标题相同的高度开始。p2与此接近,但需要手动扭转。此外,它目前为左侧图的标题和副标题添加了不必要的垂直空间。
  2. 这样它就从与左图的绘图区域相同的高度开始。p1与此接近,但需要手动扭转

代表

# setup -------------------------------------------------------------------
library(ggtext)
library(glue)
library(patchwork)
library(tidyverse)

cols <- c(ctrl = "red", trt1 = "blue", trt2 = "purple")

string <- glue("<i style='color:{cols}'>{names(cols)}</i>") %>%
  paste(collapse = ", ") %>%
  paste("There are three treatments", .,
        "and here are some interesting facts about them.") %>%
  rep(5) %>% paste(collapse = " ")

plot <- ggplot(PlantGrowth) +
  aes(x = group, y = weight, color = group) +
  geom_point() +
  scale_color_manual(values = cols, guide = "none") +
  labs(title = "Title",
       subtitle = "Subtitle",
       caption = "Caption") 


# 1st approach: geom_textbox() --------------------------------------------
text1 <- ggplot(data = tibble(x = 0, y = 1, label = string)) +
  aes(x = x, y = y, label = label) +
  geom_textbox(
    box.color = NA,
    fill = NA,
    width = unit(10, "cm"),
    hjust = 0,
    vjust = 1
  ) +
  scale_x_continuous(limits = c(0, 1), expand = c(0, 0)) +
  scale_y_continuous(limits = c(0, 1), expand = c(0, 0)) +
  theme_void() +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )


p1_left  <- plot
p1_right <- text1 / plot + plot_layout(heights = c(1, 1))
p1 <- p1_left | p1_right

ggsave("p1.png", p1, width = 9, height = 6)
cowplot::ggdraw() + cowplot::draw_image(png::readPNG("p1.png"))
Run Code Online (Sandbox Code Playgroud)

# 2nd approach: subtitle --------------------------------------------------
text2 <- ggplot(data = data.frame(x = 1:2, y = 1:10)) +
  labs(subtitle = string) +
  theme_void() +
  theme(
    plot.subtitle = ggtext::element_textbox_simple(
      hjust = 0,
      halign = 0,
      margin = margin(20, 0, 0, 0)
    ),
    plot.margin = margin(0, 0, 0, 0)
  )

p2_left  <- plot
p2_right <- text2 / plot + plot_layout(heights = c(1, 6))
p2 <- p2_left | p2_right

ggsave("p2.png", p2, width = 9, height = 6)
cowplot::ggdraw() + cowplot::draw_image(png::readPNG("p2.png"))
Run Code Online (Sandbox Code Playgroud)

创建于 2022-08-24,使用reprex v2.0.2

编辑1

根据昆滕的回答,我更新了

  1. 代表。正确地指出,通过 {reprex} 创建的 ggplots 在尺寸上是任意的。这与 RStudio 中的绘图预览窗口类似。但是,我不希望这是这个问题的焦点,因为 ggplots 将始终以某些给定的维度导出。因此,我添加了两行,通过 导出具有给定尺寸的 ggplot ggsave(...),然后通过 显示实际的 png cowplot::draw_image(png::readPNG(".png"))
  2. 的问题。现在我想要的更加精确。

编辑2

相关推文:https://twitter.com/CedScherer/status/1579066626741178368

Qui*_*ten 0

plot_layout您可以做的是首先使用with argument更改右图和文本之间的高度布局height。检查 Rstudio 中的“缩放”选项后,绘图的显示方式并更改宽度和高度,直到您喜欢为止。当您右键单击“检查元素”时,您可以看到高度和宽度是多少。这是一个例子:

在此输入图像描述

在本例中,宽度 = 1259,高度 = 827。您可以使用这些值来ggsave指定宽高比的宽度和高度,这会产生以下结果:

p <- plot | (text2 / plot + plot_layout(heights = c(1, 7))) 

# aspect ration 1259:827
ratio = 827/1259
width = 10
height = ratio * width
ggsave(p, filename = "your_plot.png",  width = width, height = height)
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

正如您所看到的,它更好地对齐了。