【问题标题】:How to add a ggplot2 subtitle with different size and colour?如何添加不同大小和颜色的ggplot2字幕?
【发布时间】:2012-07-30 15:13:13
【问题描述】:

我正在使用 ggplot2 来改进降水条形图。

这是我想要实现的可重现示例:

library(ggplot2)
library(gridExtra)
secu <- seq(1, 16, by=2)
melt.d <- data.frame(y=secu, x=LETTERS[1:8])
m <- ggplot(melt.d, aes(x=x, y=y)) +
  geom_bar(fill="darkblue") + 
  labs(x="Weather    stations", y="Accumulated Rainfall [mm]") +
  opts(axis.text.x=theme_text(angle=-45, hjust=0, vjust=1),
       title=expression("Rainfall"), plot.margin = unit(c(1.5, 1, 1, 1), "cm"),
       plot.title = theme_text(size = 25, face = "bold", colour = "black", vjust = 5))
z <- arrangeGrob(m, sub = textGrob("Location", x = 0, hjust = -3.5, vjust = -33, gp = gpar(fontsize = 18, col = "gray40"))) #Or guessing x and y with just option
z

我不知道如何避免在 ggplot2 上的 hjust 和 vjust 上使用猜测数字?有没有更好的方式放字幕(不只是使用\n,而是使用不同文字颜色和大小的字幕)?

我需要能够与 ggsave 一起使用才能拥有一个 pdf 文件。

这里有两个相关的问题:

Add a footnote citation outside of plot area in R?

How can I add a subtitle and change the font size of ggplot plots in R?

感谢您的帮助。

【问题讨论】:

  • vjust=-33 在 Linux 上为我工作。我知道 sub 是为了低于情节,但这是我得到我想要的东西的唯一方法。
  • 由于某种原因,这使我的情节非常小,并在图表下方创建了一个巨大的空间
  • @hrbrmstr 的回答似乎是当今的必经之路

标签: r ggplot2 subtitle


【解决方案1】:

最新的 ggplot2 版本(即 2.1.0.9000 或更高版本)具有字幕和情节下方字幕作为内置功能。这意味着您可以这样做:

library(ggplot2) # 2.1.0.9000+ 

secu <- seq(1, 16, by=2)
melt.d <- data.frame(y=secu, x=LETTERS[1:8])

m <-  ggplot(melt.d, aes(x=x, y=y))
m <- m + geom_bar(fill="darkblue", stat="identity")
m <- m + labs(x="Weather    stations", 
              y="Accumulated Rainfall [mm]",
              title="Rainfall",
              subtitle="Location")
m <- m + theme(axis.text.x=element_text(angle=-45, hjust=0, vjust=1)) 
m <- m + theme(plot.title=element_text(size=25, hjust=0.5, face="bold", colour="maroon", vjust=-1))
m <- m + theme(plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="black"))
m

【讨论】:

  • (函数(el,elname)中的错误:“plot.subtitle”不是有效的主题元素名称。
  • 请阅读答案:" 最新的 ggplot2 版本(即 2.1.0.9000 或更新版本)"
【解决方案2】:

忽略此答案 ggplot2 2.2.0 版具有标题和副标题功能。请参阅@hrbrmstr 的答案below


您可以在expression 中使用嵌套的atop 函数来获得不同的大小。

编辑更新了 ggplot2 0.9.3 的代码

m <-  ggplot(melt.d, aes(x=x, y=y)) + 
     geom_bar(fill="darkblue", stat = "identity") + 
     labs(x="Weather    stations", y="Accumulated Rainfall [mm]") + 
     ggtitle(expression(atop("Rainfall", atop(italic("Location"), "")))) +
     theme(axis.text.x = element_text(angle=-45, hjust=0, vjust=1), 
     #plot.margin = unit(c(1.5, 1, 1, 1), "cm"), 
     plot.title = element_text(size = 25, face = "bold", colour = "black", vjust = -1))

【讨论】:

  • 嗨,这是一个了不起的解决方案。我想使用它,但不是atop(italic("Location"),而是我想要一个对象:atop(italic(my_string_vector)。我试过了,但后来字幕评估为 (my_string_vector)。如何强制此表达式使用字符串值而不按字面意思对待提供的文本?
  • 如果您在使用变量时遇到问题,您应该使用bquote 而不是expression,请参阅here
  • @Konrad 要使用对象,请将 expression 替换为 bquote 并使用 .() 包装对象,如下所示,用于存储在名为“main.title”的对象中的主标题和存储在名为“sub.title”的对象中的字幕:ggtitle(bquote(atop(.(main.title), atop(italic(.(sub.title)), "")))) 归功于 Didzis Elferts 的回答:stackoverflow.com/questions/19957536/…
【解决方案3】:

从 ggplot 2 0.9.1 开始,opts 似乎已被弃用并且不再起作用。这对我来说适用于今天的最新版本:+ ggtitle(expression(atop("Top line", atop(italic("2nd line"), ""))))

【讨论】:

  • 这也适用于没有最终的, "" - 那部分是干什么用的?
  • 击败我。我可能复制了我在其他地方看到的示例。
  • 可能来自@SandyMuspratt 上面的回答:P - 我现在明白了,atop() 有点像没有条的分数。因此,将第二个 atop() 放在第一个中会给您一个小分数,其中文本按比例缩小。 "" 是子分数的底部。不过,这似乎是不必要的 - 也许atop() 的第二个参数有一个默认的空字符串,或者其他什么。
  • 看来@SandyMuspratt 的答案已修改之后 我发布了我的答案以反映与我的代码相似的代码。 :-)
【解决方案4】:

将 grobs 添加到 gtable 并以这种方式制作精美的标题并不难,

library(ggplot2)
library(grid)
library(gridExtra)
library(magrittr)
library(gtable)

p <- ggplot() + 
  theme(plot.margin = unit(c(0.5, 1, 1, 1), "cm"))

lg <- list(textGrob("Rainfall", x=0, hjust=0, 
                    gp = gpar(fontsize=24, fontfamily="Skia", face=2, col="turquoise4")),
               textGrob("location", x=0, hjust=0, 
                        gp = gpar(fontsize=14, fontfamily="Zapfino", fontface=3, col="violetred1")),
           pointsGrob(pch=21, gp=gpar(col=NA, cex=0.5,fill="steelblue")))

margin <- unit(0.2, "line")
tg <- arrangeGrob(grobs=lg, layout_matrix=matrix(c(1,2,3,3), ncol=2),
                  widths = unit.c(grobWidth(lg[[1]]), unit(1,"null")),
                  heights = do.call(unit.c, lapply(lg[c(1,2)], grobHeight)) + margin)

grid.newpage()
ggplotGrob(p) %>%
  gtable_add_rows(sum(tg$heights), 0) %>%
  gtable_add_grob(grobs=tg, t = 1, l = 4)  %>%
  grid.draw()

【讨论】:

    【解决方案5】:

    此版本使用gtable 函数。它允许标题中有两行文本。每行的文本、大小、颜色和字体可以相互独立设置。但是,该函数将仅使用单个绘图面板修改绘图。

    小修改:更新到 ggplot2 v2.0.0

    # The original plot
    library(ggplot2)
    
    secu <- seq(1, 16, by = 2)
    melt.d <- data.frame(y = secu, x = LETTERS[1:8])
    
    m <- ggplot(melt.d, aes(x = x, y = y)) + 
         geom_bar(fill="darkblue", stat = "identity") + 
         labs(x = "Weather    stations", y = "Accumulated Rainfall [mm]") + 
         theme(axis.text.x = element_text(angle = -45, hjust = 0, vjust = 1))
    
    
    # The function to set text, size, colour, and face
    plot.title = function(plot = NULL, text.1 = NULL, text.2 = NULL, 
       size.1 = 12,  size.2 = 12,
       col.1 = "black", col.2 = "black", 
       face.1 = "plain",  face.2 = "plain") {
    
    library(gtable)
    library(grid)
    
    gt = ggplotGrob(plot)
    
    text.grob1 = textGrob(text.1, y = unit(.45, "npc"), 
       gp = gpar(fontsize = size.1, col = col.1, fontface = face.1))
    text.grob2 = textGrob(text.2,  y = unit(.65, "npc"), 
       gp = gpar(fontsize = size.2, col = col.2, fontface = face.2))
    
    text = matrix(list(text.grob1, text.grob2), nrow = 2)
    text = gtable_matrix(name = "title", grobs = text, 
       widths = unit(1, "null"), 
       heights = unit.c(unit(1.1, "grobheight", text.grob1) + unit(0.5, "lines"), unit(1.1,  "grobheight", text.grob2) + unit(0.5, "lines")))
    
    gt = gtable_add_grob(gt, text, t = 2, l = 4)
    gt$heights[2] = sum(text$heights)
    
    class(gt) =  c("Title", class(gt))
    
    gt
    }
    
    # A print method for the plot
    print.Title <- function(x) {
       grid.newpage()   
       grid.draw(x)
    }
    
    
    # Try it out - modify the original plot
    p = plot.title(m, "Rainfall", "Location", 
       size.1 = 20, size.2 = 15, 
       col.1 = "red", col.2 = "blue", 
       face.2 = "italic")
    
    p
    

    【讨论】:

      【解决方案6】:

      您可以在 grid.arrange 中使用包装图并传递自定义的基于网格的标题,

      library(ggplot2)
      library(gridExtra)
      
      p <- ggplot() + 
        theme(plot.margin = unit(c(0.5, 1, 1, 1), "cm"))
      
      tg <- grobTree(textGrob("Rainfall", y=1, vjust=1, gp = gpar(fontsize=25, face=2, col="black")),
                     textGrob("location", y=0, vjust=0, gp = gpar(fontsize=12, face=3, col="grey50")),
                     cl="titlegrob")
      heightDetails.titlegrob <- function(x) do.call(sum,lapply(x$children, grobHeight))
      
      grid.arrange(p, top = tg)
      

      【讨论】:

      • 当前版本的 ggplot 分别使用 theme 和 element_text 而不是 opts 和 theme_text。此外,ggplotGrob 方法似乎在当前版本的 gridExtra (gridExtra_0.8.1) 和 ggplot2 (ggplot2_0.9.3.1) 中失败
      【解决方案7】:

      您可能已经注意到,Sandy 的代码不会为“Rainfall”生成粗体标题 - 使这个粗体的指令应该出现在 atop() 函数中,而不是 theme() 函数中。

      ggplot(melt.d, aes(x=x, y=y)) + 
       geom_bar(fill="darkblue", stat = "identity") + 
       labs(x="Weather    stations", y="Accumulated Rainfall [mm]") + 
       ggtitle(expression(atop(bold("Rainfall"), atop(italic("Location"), "")))) +
       theme(axis.text.x = element_text(angle=-45, hjust=0, vjust=1),
       plot.title = element_text(size = 25, colour = "black", vjust = -1))
      

      【讨论】:

        猜你喜欢
        • 2020-01-10
        • 1970-01-01
        • 2014-04-10
        • 2018-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-20
        • 1970-01-01
        相关资源
        最近更新 更多