首页 文章

如何添加不同大小和颜色的ggplot2字幕?

提问于
浏览
74

我正在使用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

我不知道如何避免在gjplot2上的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?

谢谢你的帮助 .

7 回答

  • 6

    最新的ggplot2版本(即2.1.0.9000或更新版本)具有字幕和低于 Headers 的字幕作为内置功能 . 这意味着你可以这样做:

    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
    
  • 7

    Ignore this answer ggplot2 2.2.0版具有 Headers 和副 Headers 功能 . 请参阅@ hrbrmstr的回答below .


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

    EDIT 更新了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))
    

    enter image description here

  • 1

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

  • 80

    将gbs添加到gtable并以这种方式制作一个花哨的 Headers 并不太难,

    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()
    

    enter image description here

  • 73

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

    Minor edit: Updating to 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
    

    enter image description here

  • 7

    你可以使用在grid.arrange中包装图并传递一个自定义的基于网格的 Headers ,

    enter image description here

    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)
    
  • 2

    你可能已经注意到Sandy的代码没有为“Rainfall”生成一个粗体 Headers - 使这个粗体的指令应该出现在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))
    

    enter image description here

相关问题