【问题标题】:Figure caption scientific names + symbols in textGrob gtable图标题 学名 + textGrob gtable 中的符号
【发布时间】:2016-03-11 09:21:30
【问题描述】:

首先,我要感谢巴蒂斯特爵士帮助我改进了我的 R 脚本,他使用 gtable/textGrob 在组合图的左下角添加了一个标题,如下所示:

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

p1 <- p2 <- ggplot()

g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)

g <- rbind(g1, g2)
caption <- textGrob("Figure 1. This is a caption", hjust=0, x=0)
g <- gtable::gtable_add_rows(g, unit(2,"mm") + grobHeight(caption), -1)
g <- gtable::gtable_add_grob(g, caption, nrow(g), l = 4, r = ncol(g))
grid.newpage()
grid.draw(g)

不过,我还想补充两点:

(1) 在标题中插入一个学名,并用斜体书写。 - 例如,根据上面提到的标题,我想只用斜体字“is”,其余的都是纯文本。

(2) 我还会在标题中添加符号,例如点形状=c(1,22);颜色=c(“黑色”,“红色”);填充=c("红色", "黑色")。

我将如何做这些?我是 R 程序的新手,因此非常感谢您的帮助。谢谢。

更新:

我已经在@Docconcoct、@user20650 和@baptiste 的帮助下使用此脚本解决了问题 1:

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

g1 <- ggplotGrob(pl)
g2 <- ggplotGrob(pl1)

g <- rbind(g1, g2)
caption <- textGrob(expression(paste("Figure 1. This",  italic(" is"), " a caption")), hjust=0, x=0)
g <- gtable::gtable_add_rows(g, unit(2,"mm") + grobHeight(caption), -1)
g <- gtable::gtable_add_grob(g, caption, nrow(g), l = 4, r = ncol(g))
grid.newpage()
grid.draw(g)

对于查询 2,正如 @baptiste 爵士所说,在我给他的原始电子邮件中,我已经有了关于组合图的图例。但是,在图形标题中,我需要说明图例中的那些符号是什么意思,以及情节的其他一些细节。根据巴蒂斯特爵士给出的示例,我需要在标题中包含 supp 的含义以及 OJ(黑圈)和 VC(黑三角)的符号。

再次,非常感谢!

【问题讨论】:

  • 以下内容应为斜体,如所述:caption &lt;- textGrob(expression(atop("Figure 1. This ", atop(italic("is ")), "a caption", hjust=0, x=0))) 我建议您使用 dput() 创建可重现的数据并将其添加到您的问题中。目前还不清楚你的输出应该是什么样子,我也不清楚你想要数字 2 是什么。
  • 我可能应该提一下,您要做的事情并非微不足道,所以除非有人自愿为您完成所有编码,并使用所有繁琐的小细节来获得您想要的情节,您将不得不花一些时间学习低级 gtable 和网格函数。或者,您可以考虑使用其他方法来制作图形标题,例如使用 LaTeX 或某些文本编辑器。一次性项目可能更容易。
  • 附带说明,大多数情况下,图形标题是指带有纯文本描述的符号,而不是图片(但我确实看到了这种方法的潜在价值)。您的标题通常会显示为“图 1。红点对应于 1984 年的数据集,而空心方块来自 John 等人 [37]。”
  • this latex question 也可能是相关的

标签: r ggplot2 caption gtable


【解决方案1】:

基于 cmets,我建议以下策略:创建一个虚拟图,将您的图形标题(文本)作为图例标题,提取其图例,并将其放在 gtable 的底部。

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

p1 <- ggplot()
p2 <- ggplot(ToothGrowth, aes(len, dose, shape=supp)) + geom_point() +
  theme(legend.position="bottom", 
        legend.background=element_rect(colour="black")) 

title <- expression("Figure 1. This "*italic(is)*" now a legendary caption")
dummy <- ggplotGrob(p2 + guides(shape = guide_legend(title = title)))

g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
caption <- gtable_filter(dummy,"guide")[["grobs"]][[1]]
caption$widths <- grid:::unit.list(caption$widths)
caption$widths <- unit.c(unit(0,"mm"), caption$widths[2], unit(1,"null"))

g <- rbind(g1, g2)
g <- gtable::gtable_add_rows(g, unit(2,"mm") + grobHeight(caption), -1)
g <- gtable::gtable_add_grob(g, caption, nrow(g), l = 4, r = ncol(g))
grid.newpage()
grid.draw(legend)
grid.draw(g)

【讨论】:

  • 感谢@Docconcoct 和 user20650 的帮助。正如上面巴蒂斯特爵士提出的那样,我将您的两个建议都纳入了查询 1 中以获得我想要的输出。对于我真正想在问题 2 上实现的目标的困惑,我也深表歉意。正如巴蒂斯特爵士所说,在我给他的原始电子邮件中,我已经有了关于组合情节的传说。但是,在图形标题中,我需要再次说明图例中的那些符号是什么意思。根据上面巴蒂斯特爵士给出的例子,我需要在标题中包含 OJ(黑圈)和 VC(黑三角)的符号。谢谢!
  • 请更新您的问题,而不是在 cmets 中澄清它。
【解决方案2】:

我认为一个好的解决方案将依赖于 LaTeX 或类似的文本渲染,特别是换行的棘手问题,但可以在 R 级别设计一些东西以促进包含与给定图形相对应的绘图符号。类似的东西,

gl = extract_legend_grobs(p)
caption = caption_plot("Figure 1. We are referring to the points {{gl$points[supp == OG'']}}. 
 The theoretical model is shown as {{gl$lines[type == 'theory']}}.", gl)

print(caption, output="latex")
## "Figure 1. We are referring to the points \includegraphics{gl_p_1.png}. 
## The theoretical model is shown as \includegraphics{gl_l_1.png}."

有趣的想法,但可能需要做很多工作才能让它正确。

也可以设计一个快速而简单的 R 图形输出,但不常见的是希望标题成为图形的一部分(而且 R 图形对文本不是特别好)。

这是一个将符号和文本混合在一起的标题的弱尝试。理想情况下,首先将文本拆分为单个单词(为换行提供更多选项),但绘图表达式使其不方便。

下一步是添加一些方便的包装器来生成通用符号,并交错两个 grobs 列表。

library(grid)
library(gridExtra)

inwidth <- function(x, margin=unit(1,"mm")) {
  if(inherits(x, "text"))
    convertWidth(grobWidth(x)+margin, "in", valueOnly = TRUE) else
      convertWidth(unit(1,"line")+margin, "in", valueOnly = TRUE)
}

captionGrob <- function(..., width = unit(4, "in"), debug = FALSE){

  maxw <- convertWidth(width, "in", valueOnly = TRUE)
  lg <- list(...)
  lw <- lapply(lg, inwidth)
  stopifnot(all(lw < maxw))

  # find breaks
  cw <- cumsum(lw)
  bks <- which(c(0, diff(cw %% maxw))  < 0 )
  # list of lines
  tg <- list()
  starts <- c(1, bks)
  ends <- c(bks -1, length(lg))

  for(line in seq_along(starts)){
    ids <- seq(starts[line], ends[line])
    sumw <- do.call(sum,lw[ids])
    neww <- maxw - sumw # missing width to fill
    filler <- rectGrob(gp=gpar(col=NA, fill=NA), 
                             width=unit(neww, "in"), 
                             height=unit(1, "line"))
    grobs <- c(lg[ids], list(filler))

    # store current line
    tg[[line]] <- arrangeGrob(grobs=grobs, nrow = 1, 
                              widths = unit(c(lw[ids], neww), "in"))

  }

  # arrange all lines in one column
  grid.arrange(grobs=tg, ncol=1,
               heights = unit(rep(1, length(tg)), "line"))

  if(debug)  grid.rect(width=width, gp=gpar(fill=NA, lty=2))
}

tg <- lapply(c(expression(bold(Figure~1.)~italic(Those)~points), 
               "are important, ", "nonetheless", "and", "have value too."), 
             textGrob)
pGrob <- function(fill, size=1, ...){
  rectGrob(..., width=unit(size,"line"), height=unit(size,"line"), gp=gpar(fill=fill))
}
pg <- mapply(pGrob, fill=1:5, size=0.5, SIMPLIFY = FALSE)
grid.newpage()
captionGrob(tg[[1]], pg[[1]], pg[[2]], pg[[3]], tg[[2]], tg[[3]], pg[[4]], tg[[4]], pg[[5]], tg[[5]])

【讨论】:

  • 感谢巴蒂斯特爵士的建议。我将尝试检查其中哪些对我有用。正如我所提到的,我将尝试学习和理解每个元素,我对 R 程序很陌生。我真的很感谢你所有的时间和努力来帮助我。等我搞清楚后我会回来的。再次,请接受我真诚的感谢。
  • 如果有人有兴趣追求这个想法,我已经勾勒出一些想法in this github repo
  • 这个比上一个更直接。但我不确定如何将其插入到我以前的脚本中。谢谢巴蒂斯特爵士! :)
猜你喜欢
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 2020-08-13
  • 2014-08-23
相关资源
最近更新 更多