Create sections through a loop with knitr

2019-04-14 04:33发布

问题:

See this reproducible example :

---
title: "test"
output: html_document
---

## foo

```{r}
plot(1:3)
```

## bar

```{r}
plot(4:7)
```

## baz

```{r}
plot(8:12)
```

I want to be able to automate the creation of these sections as I can't know how many they will be before going further in my analysis.

My input to get this would be :

my_list   <- list(foo = 1:3, bar = 4:7, baz = 8:12)
my_fun    <- plot
my_depth  <- 2

And the ideal answer (though I'm welcoming any improvement) would help me build a mdapply function so that I could just run:

```{r}
mdapply(X = my_list, FUN = my_fun, title_depth = my_depth)
```

And get the same output.

回答1:

It seems like I found a way!

The whole idea is to pass what would be typed by hand as a string inside of knit(text=the_string) used in inline code.

So the function basically pastes a bunch of strings together, with a bit of substitute magic to have a function that feels like it's part of the apply family.

  • Parameter depth decides how many # you want.

  • Parameter options contains the chunk options, as a vector.

A vector shouldn't be able to contain logical and characters together but here it doesn't matter as it will all be coerced to character anyway, so c(echo= FALSE, results="hide") is fine.

I expect that it's easy to break but seems to work fine when treated gently.

---
title: "test"
output: html_document
---

```{r setup, include = FALSE}
library(knitr)    
mdapply <- function(X, FUN, depth, options=""){
  FUN       <- as.character(substitute(FUN))
  list_name <- as.character(substitute(X))
  if(options != "")
    options <- paste(",",names(options),"=",options,collapse="")
  build_chunk <- function(nm)
  {
    paste0(
      paste0(rep("#",depth), collapse=""),
      " ",
      nm,
      "\n\n```{r", options, "}\n",
      FUN,
      "(", list_name, "[['", nm, "']])\n```")
  }      
  parts <- sapply(names(X), build_chunk)
  whole <- paste(parts, collapse="\n\n")
  knit(text=whole)
  }
```

```{r code}
my_list   <- list(foo = 1:3, bar = 4:7, baz = 8:12)
```

`r mdapply(my_list, plot, 2, c(echo=FALSE))`