代码之家  ›  专栏  ›  技术社区  ›  camille

ggplot2:创建主题标题,带cowlot的副标题

  •  2
  • camille  · 技术社区  · 6 年前

    我有一个数据帧列表,用来列出 ggplot s,然后组合成一个具有 cowplot . 然后我需要附加一个共享的标题、副标题和标题。我希望这样做的方式是,这些标签将具有相同的主题元素(大小、字体等),就像它们是由 labs 而不是 cowplot::draw_label .

    在我的真实情况下,我有几张合唱,每个都有自己的单位和音阶,这就是为什么我不能只是刻面,而是需要建立彼此独立的情节。

    以下是数据的简化版本,以及我加载的包:

    library(tidyverse)
    library(cowplot)
    
    dfs <- list(
      adults_no_diploma = structure(list(
        tract = c("09003405100", "09003405200", "09003405300", "09003405401", "09003405402", "09003405500", "09003405600", "09003405700", "09003405800", "09003405900"), 
        value = c(0.08, 0.108, 0.095, 0.099, 0.105, 0.103, 0.161, 0.279, 0.056, 0.055)), 
        row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame")), 
      severe_cost_burden = structure(list(
        tract = c("09003405100", "09003405200", "09003405300", "09003405401", "09003405402", "09003405500", "09003405600", "09003405700", "09003405800", "09003405900"), 
        value = c(0.128, 0.147, 0.165, 0.1, 0.151, 0.11, 0.179, 0.184, 0.14, 0.038)), 
        row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))
    )
    

    我正在处理一个自定义主题(同样是一个简化版本):

    theme_georgia <- function(...) {
      theme_gray(base_family = "Georgia", ...) + 
        theme(plot.title = element_text(face = "bold"))
    }
    
    plots <- dfs %>%
      imap(~{
        ggplot(.x, aes(x = value)) + 
          geom_density() + 
          ggtitle(.y) +
          theme_georgia()
        })
    
    gridded <- plot_grid(plotlist = plots, nrow = 1)
    

    跟随 cowplot annotations vignette ,我可以用 ggdraw() + draw_label("Socio-economic measures") 手动设置字体大小之类的东西,但我更喜欢以某种方式定义那个标签。 作为 标题;也就是说,主题将应用于 plot.title 对它来说,同样也可以创建一个字幕和标题。

    我现在的解决办法是 格格图 具有 实验室 对于标题和字幕,对标题进行相同的操作,并将它们垂直地堆叠起来。 cowplot::plot_grid .

    title_gg <- ggplot() + 
      labs(title = "Socio-economic measures", subtitle = "By census tract, 2016") + 
      theme_georgia()
    plot_grid(title_gg, gridded, ncol = 1, rel_heights = c(0.15, 1))
    

    解决办法还可以,但我喜欢你的整洁和整齐 draw_label . 我可以逐个添加这些主题元素来模拟标题:

    title_theme <- ggdraw() +
      draw_label("Socio-economic measures", 
                 fontfamily = theme_georgia()$text$family, 
                 fontface = theme_georgia()$plot.title$face, x = 0.05, hjust = 0)
    plot_grid(title_theme, gridded, ncol = 1, rel_heights = c(0.2, 1))
    

    我的问题是,我有没有办法将这些方法结合起来,拉扯所有相关的主题元素,并把它们喂给 拖拉标签 很快,或者不知怎么说 拖拉标签 这件事是一个标题,应该得到标题主题元素,这另一件事是一个字幕,等等。我想象着这样的魔法:

    ggdraw() + 
      draw_label("Socio-economic measures", theme_georgia()$plot.title_elements)
    

    或:

    ggdraw() + 
      draw_label("Socio-economic measures", type = "title") + theme_georgia()
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   Claus Wilke    6 年前

    像这样吗?

    library(ggplot2)
    library(cowplot)
    
    theme_georgia <- function(...) {
      theme_gray(base_family = "Georgia", ...) + 
        theme(plot.title = element_text(face = "bold"))
    }
    
    
    title_theme <- calc_element("plot.title", theme_georgia())
    
    ggdraw() + 
      draw_label(
        "Socio-economic measures",
        fontfamily = title_theme$family,
        fontface = title_theme$face,
        size = title_theme$size
      )
    

    于2018年6月21日由 reprex package (v0.2.0)。

        2
  •  2
  •   camille    6 年前

    @claus wilke的解决方案完成了这项工作,但我受到启发,编写了一个包装函数 draw_label 以获得模仿主题元素所必需的样式。我在这里发布,以防对其他人有用,尽管这可能是一个奇怪的用例。

    此函数接受主题函数,或者如果 theme 如果忽略,则获取当前主题 theme_get . 它还接受主题元素的名称,例如 "plot.title" ,从中获得样式 calc_element . 所有必需的参数都传递给 cowplot::draw_label ,以及其他 ... x hjust .

    library(tidyverse)
    library(cowplot)
    
    draw_label_theme <- function(label, theme = NULL, element = "text", ...) {
      if (is.null(theme)) {
        theme <- ggplot2::theme_get()
      }
      if (!element %in% names(theme)) {
        stop("Element must be a valid ggplot theme element name")
      }
    
      elements <- ggplot2::calc_element(element, theme)
    
      cowplot::draw_label(label, 
                          fontfamily = elements$family,
                          fontface = elements$face,
                          colour = elements$color,
                          size = elements$size,
                          ...
      )
    }
    
    title <- ggdraw() +
      draw_label_theme("Socio-economic measures", 
                       theme = theme_georgia(), element = "plot.title",
                       x = 0.05, hjust = 0, vjust = 1)
    subtitle <- ggdraw() +
      draw_label_theme("By census tract, 2016",
                       theme = theme_georgia(), element = "plot.subtitle",
                       x = 0.05, hjust = 0, vjust = 1)
    

    现在唯一困难的是把东西整齐地排列在 rel_heights ,我可以在这里做更多的事情。可能会有定位信息从主题中提取出来并用于设置高度。

    plot_grid(title, subtitle, gridded, ncol = 1, rel_heights = c(0.1, 0.1, 1))