Подтвердить что ты не робот

Knitr - исключить куски из `purl (...)`?

Когда я изнашиваю/замаскиваю документ, чтобы извлечь R-фрагменты в script, есть ли способ:

  • исключить произвольный фрагмент (по имени сказать)?
  • если нет, исключите фрагмент 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 the function I've been explaining:
```{r function}
plus <- function (a, b) a + b
```

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

Сплетенный script выглядит следующим образом:

## @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 в моем выпуске script (это было хорошо в Rmd для документации, но я хочу иметь возможность связать Rmd, а затем просто source('myfile.r'), если я хочу использовать plus, не беспокоясь о выполнении этих дополнительных примеров. В настоящее время я запутываю Rmd, а затем вручную отредактирую куски, которые я не хочу из script, что кажется против принципа простого написания одного Rmd который будет обеспечивать как документацию, так и script без дополнительных усилий.)

4b9b3361

Ответ 1

Так как knitr 1.3 есть новая опция chunk purl = TRUE/FALSE, которая позволяет включать/исключать определенные фрагменты кода для purl().

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

Ответ 2

Блок обработки пакетов в настоящее время не расширяет параметры, но мы можем сделать так...

# 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 the function I've been explaining:
```{r function}
plus <- function (a, b) a + b
```

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

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

Ответ 3

Хотя это скорее трюк, чем решение, вы все равно можете изменить script в результате пула с некоторыми регулярными выражениями.

Например, со следующей функцией (может быть, существует более простое решение для регулярного выражения):

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

Вы можете сделать это, чтобы удалить кусок с именем "функция" или "пример" (и на самом деле он удалит любой фрагмент, содержащий эти слова, но это можно изменить, изменив регулярное выражение):

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