knitr - 从'purl(...)`中排除块?

时间:2013-05-08 01:13:27

标签: r knitr

当我对文档进行purl / tangle以将R块提取到脚本中时,有什么方法可以:

  • 排除任意一块(按名称说)?
  • 如果没有,如果eval=F(或者我可以定义一个chunk hook / option include=F),则排除一个块?

例如,假设我有以下Rmd:

```{r setup, echo=F}
library(MASS)
```
First, we perform the setup (assume for some reason I need to evaluate `setup`
silently before I wish to display the chunk to the user, hence the repetition)
```{r setup, eval=F}
```

Here's the function I've been explaining:
```{r function}
plus <- function (a, b) a + b
```

And here's an example of its use:
```{r example}
plus(1, 2)
```

纠结的脚本看起来像这样:

## @knitr setup, echo=F
library(MASS)   

## @knitr setup, eval=F
library(MASS)

## @knitr function
plus <- function (a, b) a + b

## @knitr example
plus(1, 2)

我有一个想法,因为我没有想要评估特定的块,它们至少不应该出现在输出中(在上面的例子中,第二个{{1} } chunk)。

另外,对于纠结的输出,将一些块标记为“不可见”会很好。我不想在输出脚本中使用setup块(为了文档的目的,它在Rmd中很好,但我希望能够纠缠Rmd然后只是example如果我希望使用source('myfile.r')函数,而不必担心这些额外的例子正在执行。目前我纠结Rmd然后手动编辑出我不想要的块,这似乎是反对只编写一个Rmd的原则,它将提供文档和脚本而无需额外的努力。)

3 个答案:

答案 0 :(得分:21)

knitr 1.3开始,有一个新的块选项purl = TRUE/FALSE,允许用户包含/排除purl()的某些代码块。

```{r test, purl=FALSE}
library(MASS)
```

答案 1 :(得分:7)

纠结处理块目前没有扩展params,但我们可以这样做......

# See `?trace` documentation for details.
bdy <- as.list( body( knitr:::process_tangle.block ) )
trace.at <- which( grepl(".*opts_chunk\\$merge.*",
                         as.list( body( knitr:::process_tangle.block ) ) ) )
tracer <- quote({
  # Code borrowed from normal chunk procesing.
  af = opts_knit$get('eval.after'); al = opts_knit$get('aliases')
  if (!is.null(al) && !is.null(af)) af = c(af, names(al[af %in% al]))
  for (o in setdiff(names(params), af)) params[o] = list(eval_lang(params[[o]]))
  # Omit this if using lastest knitr source from github.
  if( isFALSE( params$include ) ) {
    tmp <- knit_code$get();
    tmp[[params$label]] <- "";
    knit_code$restore(tmp)
  }
})

trace( knitr:::process_tangle.block, tracer=tracer, at=trace.at, print=FALSE )

然后可以使用选项参数来控制purl()排除...

```{r setup, echo=TRUE, results='hide'}
library(MASS)
````

First, we perform the setup (assume for some reason I need to evaluate `setup`
silently before I wish to display the chunk to the user, hence the repetition)
```{r setup2, ref.label="setup", echo=FALSE, results='markup'}
```

Here's the function I've been explaining:
```{r function}
plus <- function (a, b) a + b
```

And here's an example of its use:
```{r example, eval=!opts_knit$get("tangle") }
plus(1, 2)
```

And here's another example of its use:
```{r example2, include=!opts_knit$get("tangle") }
plus(3, 3)
```

答案 2 :(得分:3)

虽然这不仅仅是一个解决方案,但你仍然可以使用一些正则表达式修改purl产生的脚本。

例如,使用以下函数(可能有一个更简单的正则表达式解决方案):

dropchunks <- function(scriptname, what.to.drop){
    script <- readLines(scriptname)
    script <- do.call(paste, list(script, collapse = "\n") )
    subpattern = paste0("(", do.call(paste, list(what.to.drop, collapse="|")), ")")
    mainpattern <- paste('(?s)## @knitr ((?!## @knitr).)*?', subpattern, '.*?((?=## @knitr)|$)', sep="")
    script <- gsub(pattern = mainpattern, replacement = "", x = script, perl=TRUE)
    writeLines(text = script, con= scriptname)
}

然后,您可以执行此操作以删除包含eval = F的所有代码块:

library(knitr)
purl("test.Rmd")
dropchunks("test.R", "eval=F")

您可以执行此操作以删除名为“function”或“example”的块(实际上它将删除任何包含这些单词的块,但可以通过更改正则表达式来更改):

purl("test.Rmd")
dropchunks("test.R", c("function", "example"))