通过表达式生成时如何在ggplot2中对齐标题和副标题

How to align title and subtitle in ggplot2 when generated via expression

我正在使用下面的代码在 ggplot2 中生成一个简单的箱线图:

# Libs data
data("mtcars"); require(ggplot2); require(ggthemes)
# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle("WT by AM") +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"))

生成的图表相当简单:

任务

我想在我的图表中添加一个副标题,并且可以控制它的呈现方式。我正在关注 this discussion 并使用代码:

# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle(expression(atop("WT by AM", 
                          atop(italic("Some crucial note that has to be here"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"))

我得到以下图表:


这看起来很糟糕,我想改变一些东西:

  1. 制作副标题标题left-justified
  2. 减少两条线之间的白色space
  3. 保持字体粗体

尝试次数

我尝试了不同的东西,例如下面的代码:

ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle(expression(atop("WT by AM", 
                          atop(italic("Stupid note"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"),
        plot.title = element_text(size = 16, colour = "black", hjust = -1))

但它完全隐藏了标题:

在 "it's stupid but it works" 文件中,您可以在中心右侧添加空格以强制左对齐。可以使用数学确定正确的空格数,但我看不出如何将字符串变量传回 atop

# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)), fill = "gray87") +
  xlab("AM") + ylab("WT") + theme_gdocs() +
  ggtitle(expression(atop("WT by AM                            ", 
                          atop(italic("Some crucial note that has to be here"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid", size = 0.5),
        panel.grid = element_line(colour = "gray"))

Github 目前有一个新版本的 ggplot2 (2.1.0.9000+) 可以解决您的问题。有关详细信息,请参阅 Bob Rudis' vignette.

devtools::install_github("hadley/ggplot2")  # Until the new version is available on CRAN
library(ggplot2)
library(ggthemes)  # Only necessary because the OP used theme_gdocs()

ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)), fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle("WT by AM", subtitle = "pearl of wisdom") +  # subtitle is a new argument. Both are now left-justified by default
  theme(plot.title=element_text(margin=margin(b=0), size = 20), plot.subtitle=element_text(margin=margin(t=5, b = 10)))  # Changing the size and margins of the title and subtitles to give the OP some options.

是否必须使用"expression"命令?我在 ggplot2 中这样做,但我想这对 ggplot 有用,因为它们都使用 plotmath。

您可以使用 bquote 和 atop 来根据字符串的不同长度添加空格。您可以通过 bquote 的粘贴中的 .() 从环境中获取内容。

bquote(atop(
       paste("WT by AM", .(paste0(replicate(nchar("Some Crucial Note that Has to Be Here") - nchar("WT by AM"), " "), collapse = ""), 
       paste("Some Crucial Note that Has to Be Here")
            ) 
       )

至于调整不同大小的空格(由于字体大小),我只是将复制中的长度表达式乘以一个数字(如果得到分数,则使用 floor 或 ceiling)。

编辑:但是,字符“”和 "a" 在绘制时具有不同的长度,因此即使将空格数作为字符串长度的差异也不完美。