【问题标题】:Multicolored title with R带有 R 的多彩多姿的标题
【发布时间】:2016-09-04 21:04:11
【问题描述】:

我想为图表标题中的某些字词添加颜色。我已经能够find some precedent here。具体来说,我希望用撇号(在下面的输出中)包裹的文本与它们各自条形图的颜色相对应。

这是我在将 PDF 导出到 Adob​​e Illustrator 或其他程序之前在 R 中使用标题的程度。

name <- c("Peter", "Gabriel", "Rachel", "Bradley")
age <- c(34, 13, 28, 0.9)
fake_graph <- family[order(family$age, decreasing = F), ]
fake_graph <- within(fake_graph, {
    bar_color = ifelse(fake_graph$name == "Rachel", "blue", "gray")
})

# Plot creation
library(ggplot2)
fake_bar_charts <- ggplot() +
  geom_bar(
    data = fake_graph,
    position = "identity",
    stat = "identity",
    width = 0.75,
    fill = fake_graph$bar_color,
    aes(x = name, y = age)
    ) +
  scale_x_discrete(limits = fake_graph$name) +
  scale_y_continuous(expand = c(0, 0)) +
  coord_flip() +
  theme_minimal()
family <- data.frame(name, age)

# Add title
library(grid)
library(gridExtra)
grid_title <- textGrob(
  label = "I spend more time with 'Rachel' than\nwith 'other family members.'",
  x = unit(0.2, "lines"),
  y = unit(0.1, "lines"),
  hjust = 0, vjust = 0,
  gp = gpar(fontsize = 14, fontface = "bold")
)
gg <- arrangeGrob(fake_bar_charts, top = grid_title)
grid.arrange(gg)

输出:

此示例使用ggplot2 创建条形图以及gridgridExtra 用于标题功能,但我愿意使用任何解决方案(最好使用ggplot2 来创建图表本身) 可以为我提供引号中的文本以匹配它们各自的条形图颜色。

本网站上的任何其他解决方案都无法解决这个难题,但我很想在 R 中找到解决方案。

感谢您的帮助!

【问题讨论】:

标签: r ggplot2 gridextra r-grid


【解决方案1】:

我写的标签太诚实了。第一个grob 的宽度决定了第二个grob 的x,以此类推。我使用grobTree() 将它们分组。因为gTree 没有自己的大小信息,所以我给arrangeGrob() 一个参数padding 以保留gTree 的空间。

library(grid); library(gridExtra); library(ggplot2)

df <- data.frame(name = c("Rachel", "Peter", "Gabriel","Bradley"), age = c(23, 35, 12, 3))
fake_bar_charts <- ggplot(df, aes(x=name, y=age)) + 
  geom_bar(stat="identity", fill = c(rep("gray50",3), "red")) + coord_flip()

grobs <- grobTree(
  gp = gpar(fontsize = 14, fontface = "bold"), 
  textGrob(label = "I spend more time with '", name = "title1",
           x = unit(0.2, "lines"), y = unit(1.4, "lines"), 
           hjust = 0, vjust = 0),
  textGrob(label = "Rachel", name = "title2",
           x = grobWidth("title1") + unit(0.2, "lines"), y = unit(1.4, "lines"),
           hjust = 0, vjust = 0, gp = gpar(col = "red")),
  textGrob(label = "' than", name = "title3",
           x = grobWidth("title1") + grobWidth("title2") + unit(0.2, "lines"), y = unit(1.4, "lines"),
           hjust = 0, vjust = 0),
  textGrob(label = "with '", name = "title4",
           x = unit(0.2, "lines"), y = unit(0.1, "lines"),
           hjust = 0, vjust = 0),
  textGrob(label = "other family members", name = "title5",
           x = grobWidth("title4") + unit(0.2, "lines"), y = unit(0.1, "lines"),
           hjust = 0, vjust = 0, gp = gpar(col = "gray50")),
  textGrob(label = "'.", name = "title6",
           x = grobWidth("title4") + grobWidth("title5") + unit(0.2, "lines"), y = unit(0.1, "lines"),
           hjust = 0, vjust = 0)
)

gg <- arrangeGrob(fake_bar_charts, top=grobs, padding = unit(2.6, "line"))
grid.newpage()
grid.draw(gg)

【讨论】:

  • 顺便说一句,不是arrangeGrob不喜欢gTrees,只是gTrees不知道它们的大小(heightDetails方法不计算任何东西)。解决这个问题的常用方法是定义一个包含有意义的 heightDetails 方法的自定义类。
  • @cuttlefish44 @baptiste 非常优雅的解决方案!我仍然熟悉网格图形 - 有没有办法通过这种方法减少像 hjustvjust 这样的冗余代码条目?
【解决方案2】:

一个非常简单的方法是使用ggtext

这是通过

实现的
library(ggtext) #remotes::install_github("wilkelab/ggtext")

ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) +
  geom_point(size = 3) +
  scale_color_manual(
    name = NULL,
    values = c(setosa = "#0072B2", virginica = "#009E73", versicolor = "#D55E00"),
    labels = c(
      setosa = "<i style='color:#0072B2'>I. setosa</i>",
      virginica = "<i style='color:#009E73'>I. virginica</i>",
      versicolor = "<i style='color:#D55E00'>I. versicolor</i>")
  ) +
  labs(
    title = "**Fisher's *Iris* dataset**  
    <span style='font-size:11pt'>Sepal width vs. sepal length for 
    <span style='color:#0072B2;'>setosa</span>, 
    <span style='color:#D55E00;'>versicolor</span>, and
    <span style='color:#009E73;'>virginica</span>
    </span>",
    x = "Sepal length (cm)", y = "Sepal width (cm)"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_markdown(lineheight = 1.1),
    legend.text = element_markdown(size = 11)
  )

【讨论】:

  • 很好的解决方案,比手动构建文本 Grobs 更乏味,theme 中的 element_markdown 规范可以轻松保留不需要降价的默认 ggplot 行为。
【解决方案3】:

这是利用有关how to insert annotations outside of the plot area 的答案的第一次尝试。基本思想是使用不同颜色的自定义文本几何分层。我觉得这个答案不是很令人满意,因为(i)字符的边缘是锯齿状的(多次将文本覆盖在自身上的结果),并且(ii)需要手动指定标题的位置,但是这是一个开始:

library(ggplot2)
library(grid)

# Convenience function to make text    
tt <- function(text, colour, x, y) {
  annotation_custom(
    grob = textGrob(
      label = text, hjust = 0, gp = gpar(col = colour)),
      xmin = x, xmax = x,
      ymin = y, ymax = y
  )   
}

p <- ggplot(mpg, aes(x = class, fill = ifelse(class == "pickup", "a", "b"))) +
  geom_bar() +
  scale_fill_manual(guide = FALSE, values = c("blue", "grey")) + 
  coord_flip() +
  theme(plot.margin = unit(c(4, 3, 3, 2), units = "lines"))
p <- p +
  tt("I spend more time with 'pickup' than\nwith 'other family members.'",
       "grey", 8.5, 0) +
  tt("I spend more time with 'pickup' than\nwith",
       "black", 8.5, 0) +
  tt("I spend more time with 'pickup'\n",
       "blue", 8.5, 0) +
  tt("I spend more time with\n",
       "black", 8.5, 0)
# Code to override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

【讨论】:

  • 我是便利功能的忠实粉丝。如果您将其设置为返回 textGrob 作为 grobTree 的一部分,那么它肯定会减少混乱和文本。
【解决方案4】:

使用ggchartsmdthemes 这可以很容易地实现。

name <- c("Peter", "Gabriel", "Rachel", "Bradley")
age <- c(34, 13, 28, 0.9)
family <- data.frame(name, age, stringsAsFactors = FALSE)

title <- paste(
  "**I spend more time with '<span style=color:'#1F77B4'>Rachel</span>' than",
  "with '<span style=color:'lightgray'>other family members</span>'**",
  sep = "<br>"
)

ggcharts::bar_chart(family, name, age, highlight = "Rachel", bar_color = "#1F77B4") +
  ggtitle(title) +
  mdthemes::md_theme_minimal()

ggcharts 中的 bar_chart() 函数默认创建一个水平排序的条形图。使用highlight 参数内置突出显示。

mdthemes 包提供了将文本呈现为 markdown/HTML 的主题。请注意标题周围的** 使其粗体 和带有CSS 的&lt;span&gt; 标记来为单词着色。

【讨论】:

  • 我不熟悉 mdthemes 包,我喜欢这种方法。谢谢!
  • @DanKalleward,它是全新的!我大约两周前才创建它。
  • 我是ggcharts 包的忠实粉丝。我并不总是有时间输入 45 行 ggplot2 代码来分析一些数据。这个包填补了一个空白,我一定会把它传递下去。
猜你喜欢
  • 2021-07-11
  • 1970-01-01
  • 2013-04-28
  • 2014-01-07
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
相关资源
最近更新 更多