【问题标题】:Does rmarkdown allow captions and references for code chunks?rmarkdown 是否允许代码块的标题和引用?
【发布时间】:2018-11-15 02:36:52
【问题描述】:

是否有在 rmarkdown 中添加字幕和引用一小段代码的技巧(不是运行代码的结果)?比如如何引用这段代码:

```{r blah}
blah <- "blah"
```

我知道我可以使用 \@ref(fig:theFig) 或 \@ref(tab:theTable) 来获取 fig.cap 或标题(使用 kable),但我看不到标题和参考的方法代码本身。

【问题讨论】:

    标签: r latex r-markdown knitr


    【解决方案1】:

    这将是一个很棒的功能。而且我认为它还没有集成。这是一种适用于 PDF 文档并允许您生成标题和标签以进行交叉引用的方法:

    1. header.tex 中包含以下内容

    \usepackage{caption}
    \usepackage{floatrow}
    
    \DeclareNewFloatType{chunk}{placement=H, fileext=chk, name=}
    \captionsetup{options=chunk}
    \renewcommand{\thechunk}{Chunk~\thesection.\arabic{chunk}}
    \makeatletter
    \@addtoreset{chunk}{section}
    \makeatother
    

    由于用于块的环境不是浮动类型,我们声明了一个新的,命名为chunkname 选项留空,因为我们已经在下一行中重新定义了 \thechunk,方法是在 Chunk 前面加上单词(使用 name 选项看看会发生什么)。

    应该按节枚举块,因此我们告诉 tex 在每次新节开始时重置计数器。

    如果不使用节编号(通过设置 YAML 选项),则替换该行

    \renewcommand{\thechunk}{Chunk~\thesection.\arabic{chunk}}
    

    通过

    \renewcommand{\thechunk}{Chunk~\arabic{chunk}}
    
    1. 修改 rmarkdown 文档中的 knitr 源挂钩

    library(knitr)
    oldSource <- knit_hooks$get("source")
    knit_hooks$set(source = function(x, options) {
      x <- oldSource(x, options)
      x <- ifelse(!is.null(options$ref), paste0("\\label{", options$ref,"}", x), x)
      ifelse(!is.null(options$codecap), paste0("\\captionof{chunk}{", options$codecap,"}", x), x)
    })
    

    这里我们使用了两个新的块选项refcodecap。如果任一不是NULL,则使用命令\label\captionof 生成相应的标签或标题。

    MWE:

    ---
    title: "Cross-referencing Code Chunks"
    output: 
      pdf_document: 
        includes:
          in_header: header.tex
        number_sections: true
    ---
    
    ```{r, echo=FALSE}
    library(knitr)
    oldSource <- knit_hooks$get("source")
    knit_hooks$set(source = function(x, options) {
      x <- oldSource(x, options)
      x <- ifelse(!is.null(options$ref), paste0("\\label{", options$ref,"}", x), x)
      ifelse(!is.null(options$codecap), paste0("\\captionof{chunk}{", options$codecap,"}", x), x)
    })
    ```
    
    # Foo
    
    Jump to \ref{TheBarChunk}
    
    ```{r Foo, ref = "TheFooChunk", codecap = "My Chunk"}
    print("Foo!")
    ```
    
    \newpage
    
    # Bar
    
    ```{r Bar, ref = "TheBarChunk", codecap = "My second chunk"}
    print("Bar!")
    ```
    
    Head back to \ref{TheFooChunk}
    

    这是(两个页面的)输出:

    在代码块下方添加标题

    如果您希望在代码块下方添加标题,而不是上方,这可以通过将上述 knitr 钩子更改为读取来实现:

    oldSource <- knit_hooks$get("source")
    knit_hooks$set(source = function(x, options) {
      x <- oldSource(x, options)
      x <- ifelse(!is.null(options$codecap), paste0(x, "\\captionof{chunk}{", options$codecap,"}"), x)
      ifelse(!is.null(options$ref), paste0(x, "\\label{", options$ref,"}"), x)
    })
    

    评论:

    您可以通过检查所需的输出类型来改进代码,以便新的源挂钩仅用于 pdf 输出(由于是午餐时间而跳过)。

    【讨论】:

    • 感谢您提供出色的解决方案。是否有一个简单的修改可以在代码块下面而不是上面添加标题?我已经尝试过了,但无法让它工作。干杯。
    • 检查mirror.physik-pool.tu-berlin.de/pub/CTAN/macros/latex/contrib/…中的位置参数。这可能行得通。
    • 位置参数只改变标题周围的间距。从您链接的文档中:“请注意, position=bottom 并不意味着标题实际上位于底部......”。
    • 然而,我发现交换paste0 命令的参数顺序足以将标题定位在下面。 IE。 paste0(x, "\\label{", options$ref,"}")paste0(x, "\\captionof{chunk}{", options$codecap,"}").
    • 这也适用于bookdownheader.txtknitr 源钩子块不需要修改。 YAML 标头只需将pdf_document: 替换为bookdown::pdf_book:。无需在 YAML 标头中包含 number_sections: true,因为默认情况下是 bookdown numbers 部分。请注意,除非您包含 codecap 块选项,否则不会发生编号,即使您包含 ref
    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2021-01-30
    • 2019-09-02
    • 2021-11-29
    • 2011-07-13
    相关资源
    最近更新 更多