Rmarkdown中的循环:如何制作文本中的图形参考?配图?

时间:2016-12-23 23:37:47

标签: r loops knitr r-markdown reproducible-research

{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&#39;

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))
```

1 个答案:

答案 0 :(得分:1)

  1. 使用knit_expand()
  2. 使用captioner代替kfigr
  3. 这会在文字和报告末尾对您的数字(或表格)进行编号。
  4. 此脚本向您展示如何在for循环中创建markdown段落,这些循环具有对图形的文本引用。
  5. 它还向您展示了如何在保留数字顺序的同时在for循环中创建自定义图形标题。
  6. 如果你使用brew展示如何做#4和#5,我会给你所有的SO点。
  7. library(knitr) library(dplyr) library(png) library(grid) library(pander) library(ggplot2) library(devtools) library(captioner)

    使用fig_nums()包创建captioner函数 (https://github.com/adletaw/captioner/blob/master/vignettes/using_captioner.Rmd

    fig_nums <- captioner(prefix = "Figure")
    

    数据

    每年我们都有不同数量的阶层,因此需要循环。

    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循环之前应该出现在列表中的数字按strata

    创建部分
    first_plot <- ggplot(df, aes(x, fill=strata)) + geom_histogram()
    fig_nums("first_plot", display = FALSE)
    

    last_plot:for循环后应该出现在列表中的数字按层次创建部分

    last_plot <- ggplot(df, aes(x = strata, y = z)) + geom_boxplot()
    

    图代

    一旦你想要了解你想要的东西,请注释这一部分。如果您在R中执行大量映射,则此步骤不会感到复杂,不自然,次优,不必要或者是一个非常糟糕的主意。

    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&#39;

    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 fig_nums("first_plot", display="cite")

    将在文本中引用的结果和图像文件名:

    ```{r echo = FALSE, warnings=FALSE, message=FALSE, results = "asis"}
    
        results <- df %>% 
          group_by(strata) %>% 
          dplyr::summarise_each(funs(mean)) %>% 
          mutate(fig1 = paste0("fig1_", strata),
                 fig2 = paste0("fig2_", strata))
    
    ```
    
    ```{r run-numeric-md, warning=FALSE, include=FALSE}
    
    #The text for the markdown sections in for loop... the knit_expand() is the work-horse here.
    
    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]))}}', '({{fig_nums(results$fig1[results$strata==i],display="cite")}}).',
                                      '\n'
      )))
    }
    
    ```
    

    为每个阶层

    创建部分
    `r paste(knit(text = out), collapse = '\n')`
    

    结论

    报告中的一些讨论文字和图r fig_nums("last_plot",display="cite")

    数字清单

    `r fig_nums("first_plot",caption="Here is the caption for the first figure.")`
    
    ```{r 'first_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6}
    suppressMessages(print(first_plot))
    ```
    
    ```{r figcaps, include=FALSE}
    caps = NULL
    
    for (i in as.character(unique(results$strata))) {
      caps = c(caps, knit_expand(  
        text=c({{fig_nums(results$fig1[results$strata==i], caption="Caption text for strata *{{i}}* goes here.")}},
               '``` {r {{results$fig1[results$strata==i]}}, echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6}',
               {{paste0('grid.raster(',results$fig1[results$strata==i],')')}},
                                        '```',
               '\n')))
    }
    
    #DON'T FORGET TO UNLIST!
    src <- unlist(caps)
    ```
    
    `r paste(knit(text = src),sep='\n')`
    
    `r fig_nums("last_plot", caption="The caption for the last figure.")`
    
    ```{r 'last_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6}
    suppressMessages(print(last_plot))
    ```