21

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

  • 排除任意块(按名称说)?
  • 如果不是,排除一个块 if eval=F(或者我可以定义一个块挂钩/选项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)

我的想法是,由于我不想评估特定的块,它们至少不应该出现在输出中(在上面的示例中,第二setup块)。

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

4

3 回答 3

26

knitr1.3 开始,有一个新的块选项purl = TRUE/FALSE允许包含/排除purl().

```{r test, purl=FALSE}
library(MASS)
```
于 2013-06-22T00:15:05.937 回答
7

缠结处理块目前不扩展参数,但我们可以让它这样做......

# 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)
```
于 2013-06-17T04:57:18.990 回答
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"))
于 2013-06-17T21:48:53.863 回答