【问题标题】:Subfigures or Subcaptions with knitr?knitr 的子图或子标题?
【发布时间】:2012-09-14 19:27:49
【问题描述】:

是否可以使用 knitr 生成子图(带有关联的子标题)?这是一个最小的工作示例:

\documentclass{article}

\begin{document}

<<echo = FALSE, fig.cap = c("Some numbers.", "Some more numbers."), out.width = "0.5\\textwidth", fig.align = "center">>=

plot(1:10)
plot(30:100)

@

\end{document}

这会产生两个标记为图 1 和图 2 的图,并带有定义的标题(分别)。但我希望它们被标记为“图 1a”和“图 1b”,就像您可以使用 subcaption LaTeX 包一样。

我知道有一个 knitr 选项“fig.env”,但这并不能解决它(至少不使用,例如,“fig.env = 'subfigure'”)。这里有一篇关于 Sweave 的类似帖子,但解决方案是不优雅的 hack:http://texblog.org/2011/12/01/sweave-subfig-controlling-figure-size-and-placement/

【问题讨论】:

标签: r latex knitr subfigure


【解决方案1】:

knitr (>= v1.5) 支持subfigures。您可以使用块选项fig.subcap。这是一个最小的例子。

\documentclass{article}
\usepackage{subfig}
\begin{document}

<<fig-sub, fig.cap='two plots', fig.subcap=c('one plot', 'the other one'), out.width='.49\\linewidth'>>=
plot(1:10)
plot(rnorm(10), pch=19)
@

\end{document}

【讨论】:

  • 太棒了!这肯定会让我的源代码更干净。谢谢一辉。
  • 感谢您制作这个!使许多事情变得容易得多。但是,我真的很难想象一个允许在情节之间换行的钩子(“智能地”或按用户规范)。例如:如何让plot.lm 的结果以 2x2 配置显示,其中每个绘图都是一个子图? (即不使用par(mfrow=c(2,2)),而是在情节2和情节3之间使用`\\`。我应该在GitHub上提出功能请求吗?还是有一个简单的解决方案?谢谢!
  • @Yihui 有没有办法让这些数字也集中在页面上?
  • \usepackage{subfig} 部分很重要 =) ;我也可以确认这个功能现在在 mainline knitr 中。
  • @Yihui,这太棒了。我不知道使用subcaption 而不是这个会有多困难。它可能也允许我们使用子表。
【解决方案2】:

更新一辉的答案,以反映过去几年Rmarkdown的变化,以及从Rnw文件的转变。

正如 knitr chunk options 中列出的那样,子图需要在块头中设置一些额外的设置:

  • fig.subcap 是子图的标题列表
  • fig.ncol: 子图的列数
  • out.width:图形的输出宽度。您通常会设置此 100% 除以子列数。

子图还需要 LaTeX 包 subfig。因此,\usepackage{subfig} 行必须包含在 YAML 中,或者如果您使用的是外部 tex 模板,则可以将其添加到该文件中。

这是一个基本模板:

---
output: pdf_document
header-includes:
   - \usepackage{subfig}
---  

```{r fig-sub, fig.cap='two plots', fig.subcap=c('one plot', 'the other one'), out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}
plot(1:10)
plot(rnorm(10), pch=19)
```

与 ggplot2 一起使用

如果您正在绘制包含多个 ggplot 图的子图,可能会很混乱,因为它们不会在图之间排列。您可能想在这里查看这篇文章,了解如何使用 cowplot 强制 ggplots 具有相同的尺寸。

This stackoverflow post 将帮助您确保所有地块都对齐,如下图所示:

为子图提供列表

只是分享这个作为子图的可能扩展。我喜欢用它们做的事情是给他们提供一个数字列表。也许您已经生成了一个需要在四个不同的试验组或四个不同的位置运行的函数。例如,以下是英国四个城市的列表:

```{r}
locations <- c("Southampton, UK", "London, UK", "Bristol, UK", "Birmingham, 
```

然后可以在fig.sublapply 中使用此列表来生成子图列表。如果你需要运行

```{r fig-sub-2, fig.cap='A collection of maps', fig.subcap= locations, out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}
library(ggmap)
lapply(locations, function(x) 
  ggmap(get_map(x))
  )
```

这使得子图非常健壮。如果我需要在额外的几个城市中运行我的模型,我需要做的就是在location 列表中添加额外的值,并且子图的长度将相同。

【讨论】:

  • 很好的解决方案@Michael Harper。但是,当我有更多的数字然后适合一页(对于pdf文档)时,我遇到了这个问题。当我说 10 个数字时,剩余的数字在将文档编织成 pdf 后就会被截断。你知道如何解决这个问题吗?我也为它创建了一个问题here
【解决方案3】:

你可以使用 Latex 的subcaption 包。

\documentclass{article}
\usepackage{subcaption}

\begin{document}

\begin{figure}
\centering
\begin{subfigure}[b]{0.3\textwidth}
\centering
<<echo = FALSE, out.width = "0.5\\textwidth", fig.align = "center">>=
  plot(1:10)
@
\caption{text for first figure}
\label{fig:gull}
\end{subfigure}%

\begin{subfigure}[b]{0.3\textwidth}
\centering
<<echo = FALSE, out.width = "0.5\\textwidth", fig.align = "center">>=
  plot(30:100)
@
\caption{text for second figure}
\label{fig:tiger}
\end{subfigure}
\caption{Figure caption}
\end{figure}

\end{document}

【讨论】:

  • 不错的解决方案 - 它可以显式保存制作图形 pdf 然后插入它。但这仍然是一个黑客攻击。期待在 knitr 中正确实现这一点!
猜你喜欢
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 2017-12-25
相关资源
最近更新 更多