在 knitr 中打印动态大小图的列表

Print a list of dynamically-sized plots in knitr

我希望能够在 knitr 中打印出非预定的地块列表。我 能够做到这一点,但还有一些问题需要解决。即:

1) 如何在每个情节之前的每个页面上抑制列表索引(如 [[2]])?使用 echo=FALSE 不会做任何事情。

2) 是否可以在渲染时设置 每个图 的大小?我试过在块之外设置一个大小变量,但这只允许我使用一个值而不是每个图的不同值。

我把这个问题作为一个问题来问,因为他们似乎讲的是同一个课程,即生成一系列情节。

一些示例代码:

\documentclass{article}
\usepackage[margin=.5in, landscape]{geometry}
\begin{document}

<<diamond_plots, echo = FALSE, results = 'hide'>>==
library(ggplot2)

diamond_plot = function(data, cut_type){
  ggplot(data, aes(color, fill=cut)) + 
    geom_bar() +
    ggtitle(paste("Cut:", cut_type, sep = ""))
}

cuts = unique(diamonds$cut)
plots = list()
for(i in 1:length(cuts)){
    data = subset(diamonds, cut == cuts[i])
    plots[[i]] = diamond_plot(data, cuts[i])
}
height = 3
@

<<print_plots, results='asis', echo=FALSE,  fig.width=10, fig.height=height>>=
plots
@
\end{document}

绘图的 PDF 格式如下:

您需要访问各个列表元素,否则 print 将始终打印出索引。

不确定这是否是最简洁的答案,但您可以循环打印它们。

> print(plots)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

> for(x in plots){print(x)}

但我没有在 tex 中尝试过,只是在控制台中尝试过。

1) How do you suppress the list indices (like [[2]]) on each page that precede each plot? Using echo=FALSE doesn't do anything.

分别绘制列表中的每个元素 (lapply) 并隐藏 lapply 的输出 (invisible):

invisible(lapply(plots, print))

2) Is it possible to set the size for each plot as they are rendered? I've tried setting a size variable outside of the chunk, but that only let's me use one value and not a different value per plot.

是的。通常,当您将向量传递给图形相关的块选项时,ith 元素用于 ith情节。这适用于 "figure specific" 的选项,例如fig.capfig.scapout.widthout.height.

但是,其他图形选项是"device specific"。要理解这一点,重要的是看一下 option dev:

dev: the function name which will be used as a graphical device to record plots […] the options dev, fig.ext, fig.width, fig.height and dpi can be vectors (shorter ones will be recycled), e.g. <<foo, dev=c('pdf', 'png')>>= creates two files for the same plot: foo.pdf and foo.png

虽然将向量传递给 "figure specific" 选项 out.height 的结果是 ith 元素被用于 ith plot,将向量传递给 "device specific" 选项的结果是 ith 元素用于 ith device.

因此,生成动态大小的图需要对块进行一些修改,因为 one 块无法生成具有不同 fig.height 设置的图。以下解决方案基于 knitr 示例 `075-knit-expand.Rnw and this post on r-bloggers.com (which explains this answer on SO).

解决方案的想法是使用块模板并使用适当的表达式扩展模板值以生成块,这些块反过来会生成具有正确 fig.height 设置的图。扩展模板传递给 knit 以评估块:

\documentclass{article}
\begin{document}

<<diamond_plots, echo = FALSE, results = "asis">>==
library(ggplot2)
library(knitr)

diamond_plot = function(data, cut_type){
  ggplot(data, aes(color, fill=cut)) +
    geom_bar() +
    ggtitle(paste("Cut:", cut_type, sep = ""))
}

cuts = unique(diamonds$cut)

template <- "<<plot-cut-{{i}}, fig.height = {{height}}, echo = FALSE>>=
    data = subset(diamonds, cut == cuts[i])
    plot(diamond_plot(data, cuts[i]))
@"

for (i in seq_along(cuts)) {
  cat(knit(text = knit_expand(text = template, i = i, height = 2 * i), quiet = TRUE))
}

@

\end{document}

使用 knit_expand 扩展模板,用相应的值替换 {{}} 中的表达式。

对于knit调用,使用quite = TRUE很重要。否则,knit 会用日志信息污染主文档。

使用 cat 很重要,可以避免隐含的 print 否则会损坏输出。出于同样的原因,"outer" 块 (diamond_plots) 使用 results = "asis".