knitr - exclude chunks from `purl(…)`?

后端 未结 3 1295
死守一世寂寞
死守一世寂寞 2021-01-01 14:27

When I purl/tangle a document to extract the R chunks into a script, is there any way to:

  • exclude an arbitrary chunk (by name say)?
  • if not, exclude a
相关标签:
3条回答
  • 2021-01-01 14:53

    The tangle processing block doesn't currently expand params, but we can make it do so...

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

    Then purl() exclusion can be controlled using option arguments...

    ```{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)
    ```
    
    0 讨论(0)
  • 2021-01-01 14:53

    Although this is more a trick than a solution, you can still modify the script resulting from purl with some regular expressions.

    For example with the following function (maybe there is a simpler solution for the regex) :

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

    You can then do this to remove all code chunk containing eval=F :

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

    You can do this to remove the chunk named "function" or "example" (and in fact it will remove any chunk that contains these words somewhere but this could be changed by changing the regex):

    purl("test.Rmd")
    dropchunks("test.R", c("function", "example"))
    
    0 讨论(0)
  • 2021-01-01 14:58

    Since knitr 1.3, there is a new chunk option purl = TRUE/FALSE that allows one to include/exclude certain code chunks for purl().

    ```{r test, purl=FALSE}
    library(MASS)
    ```
    
    0 讨论(0)
提交回复
热议问题