在 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.
是的。通常,当您将向量传递给图形相关的块选项时,i
th 元素用于 i
th情节。这适用于 "figure specific" 的选项,例如fig.cap
、fig.scap
、out.width
和 out.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
的结果是 i
th 元素被用于 i
th plot,将向量传递给 "device specific" 选项的结果是 i
th 元素用于 i
th 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"
.
我希望能够在 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.
是的。通常,当您将向量传递给图形相关的块选项时,i
th 元素用于 i
th情节。这适用于 "figure specific" 的选项,例如fig.cap
、fig.scap
、out.width
和 out.height
.
但是,其他图形选项是"device specific"。要理解这一点,重要的是看一下 option dev
:
dev
: the function name which will be used as a graphical device to record plots […] the optionsdev
,fig.ext
,fig.width
,fig.height
anddpi
can be vectors (shorter ones will be recycled), e.g.<<foo, dev=c('pdf', 'png')>>=
creates two files for the same plot:foo.pdf
andfoo.png
虽然将向量传递给 "figure specific" 选项 out.height
的结果是 i
th 元素被用于 i
th plot,将向量传递给 "device specific" 选项的结果是 i
th 元素用于 i
th 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"
.