【发布时间】:2017-05-09 14:28:24
【问题描述】:
{r setup, include=FALSE, message=FALSE, results="hide"}
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
library(kfigr)
library(dplyr)
library(png)
library(grid)
library(pander)
library(ggplot2)
问题
rmarkdown 中的循环:文本中的图形参考?数字字幕?
目标
使用 for 循环创建包含文本、文本内结果和多个图形引用以及图形列表中相关图形标题的部分。数字参考/编号应该是无缝的,在这些新部分之前和之后编号的数字。
注意: for 循环中引用的图形是在文本的前面生成的,保存为 png,然后重新加载。出于本示例的目的,这可能看起来很笨重,但实际的无花果是地图并且生成速度很慢(我打算在我想要的方式生成这些数字后注释掉生成这些数字的循环)。
{r echo = FALSE, warnings=FALSE, message=FALSE, results="hide"}
数据:每年我们有不同数量的层,因此需要循环。
df <- rbind(
data.frame(strata = rep("A", 10), x = rnorm(10, mean= 10), y = rnorm(10, mean = 15),z = rnorm(10, mean = 20)),
data.frame(strata = rep("B", 10), x = rnorm(10, mean= 5), y = rnorm(10, mean = 10), z = rnorm(10, mean = 15)),
data.frame(strata = rep("C", 10), x = rnorm(10, mean= 15), y = rnorm(10, mean = 20), z = rnorm(10, mean = 10)))
first_plot: for 循环之前应该出现在列表中的图形按层创建部分
first_plot <- ggplot(df, aes(x, fill=strata)) + geom_histogram()
last_plot:for 循环按层创建部分后应出现在列表中的图形
last_plot <- ggplot(df, aes(x = strata, y = z)) + geom_boxplot()
图形生成(这是我的版本稍后将在我拥有所需的地图后注释掉的部分)
strat <- unique(df$strata)
for (i in seq_along(strat)) {
sub <- df %>% filter(strata %in% strat[i])
fig1 <- ggplot(sub, aes(x = x, y = y)) + geom_point()
ggsave(fig1, file=paste0("fig1_", strat[i], ".png"))
fig2 <- ggplot(sub, aes(x = x, y = z)) + geom_point()
ggsave(fig2, file=paste0("fig2_", strat[i], ".png"))
}
加载 png 的
df_figs <- list.files(pattern = "\\.png$")
for (i in df_figs){
name <- gsub("-",".",i)
name <- gsub(".png","",name)
i <- paste(".\\",i,sep="")
assign(name,readPNG(i))
}
介绍部分
报告中的一些介绍性文字和一个图r figr('first_plot',TRUE, type='Figure')。
```{r echo = FALSE, warnings=FALSE, message=FALSE, results = "asis"}
# Summary of results and image file names that will be references in text
results <- df %>%
group_by(strata) %>%
dplyr::summarise_each(funs(mean)) %>%
mutate(fig1 = paste0("fig1_", strata),
fig2 = paste0("fig2_", strata))
#Text template (each strata will have its own section)
template <- "# The %s stratum
The mean of *x* in %s stratum was %1.1f. Relationships between *x* and *y* and *x* and *z* can be found in `r figr('%s', TRUE, type='Figure')` and `r figr('%s', TRUE, type='Figure')`.
"
#Create markdown sections in for loop
for(i in seq(nrow(results))) {
current <- results[i, ]
cat(sprintf(template,
current$strata, current$strata,
current$x,
current$fig1, current$fig2))
}
#Also doesn't work:
template <- "# The %s stratum
The mean in %s stratum was %1.0f. Results can be found in "
template2 <- " and "
template3 <- ".
"
`figr('%s', TRUE, type='Figure')` and `figr('%s', TRUE, type='Figure')`."
#For loop
for(i in seq(nrow(results))) {
current <- results[i, ]
cat(sprintf(template,
current$strata, current$strata,
current$mean,
current$fig_1, current$fig_2))
print(paste0("`r figr(",paste0("'", current$fig1,"'"), TRUE, type='Figure'))
cat(sprintf(template2))
print(paste0("`r figr(",paste0("'", current$fig2,"'"), "TRUE, type='Figure'),`"))
cat(sprintf(template3))
}
```
结论部分
报告中的一些讨论文字和图r figr('last_plot',TRUE, type='Figure')。
数字
*NOTE:* I don't know how to automate the looped portion of the list of figures here, so I've done it by hand.
```{r 'first_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="The caption for the first figure."}
suppressMessages(print(first_plot))
```
```{r 'fig1_A', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_A."}
grid.raster(fig1_A)
```
```{r 'fig2_A', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_A."}
grid.raster(fig2_A)
```
```{r 'fig1_B', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_B."}
grid.raster(fig1_B)
```
```{r 'fig2_B', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_B."}
grid.raster(fig2_B)
```
```{r 'fig1_C', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_C."}
grid.raster(fig1_C)
```
```{r 'fig2_C', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_C."}
grid.raster(fig2_C)
```
```{r 'last_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="The caption for the last figure."}
suppressMessages(print(last_plot))
```
【问题讨论】:
-
听起来你可以充分利用缓存和 knit_expand
-
@baptiste 我探索了 knit_expand,但我看不出它如何解决我的问题的
figr('plot',TRUE,type='Figure')部分。out = NULL for (i in as.character(unique(results$strata))) { out = c(out, knit_expand(text=c('#### The *{{i}}* strata', '\n', 'The mean of *x* is ', '{{paste(sprintf("%1.1f", results$x[results$strata==i]))}}', '{{figr(sprintf("%s", results$fig1[results$strata==i]),TRUE,type="Figure")}}' ))) } cat(out) -
好的!在职的。 ` '({{figr(sprintf("%s", results$fig1[results$strata==i]),TRUE,type="Figure")}}).', '\n' cat(out,sep ="\n")` 然后确保最后有你的无花果标题调用,大概你也可以把它放在一个循环中?
-
FWIW 对您的工作流程的描述听起来相当不自然,而且不必要地令人费解/脆弱。但是,鉴于您的问题设置方式,很难提供更精确的指导。通常使用
cat()、assign()、手动文件名等是一个明显的迹象,表明您在 knitr 中做的事情并不理想。实际上,您可能更愿意使用 brew 包来预处理您的 knitr 文件,但据我所知,您正在采取的几个步骤是不必要的,只会让您的生活更加艰难(保存 png 并重新加载它们 - 听起来对我来说这是一个非常糟糕的主意)。
标签: r loops knitr r-markdown reproducible-research