【问题标题】:How to Customize figure LaTeX with knitr/rmarkdown如何使用 knitr/rmarkdown 自定义图形 LaTeX
【发布时间】:2021-08-21 20:12:38
【问题描述】:

我想在浮动中为使用 ggplot2 在通过 LaTeX 生成 .pdf 文件的 rmarkdown 文档中创建的图形创建页脚。

我的问题:rmarkdown/knitr 中有没有办法在图形环境中添加更多 LaTeX 命令?

具体来说,我想找到一种方法来使用图形环境中https://tex.stackexchange.com/questions/56529/note-below-figure 中所述的floatrowcaption* 宏插入自定义LaTeX。

当我查看块选项 (https://yihui.org/knitr/options/#plots) 时,out.extra 之类的东西似乎与我想要的很接近,但它被用作\includegraphics 的额外选项,而我想访问以将额外的 LaTeX 放入图形环境,在任何其他 LaTeX 命令之外。

【问题讨论】:

    标签: r r-markdown knitr


    【解决方案1】:

    您的问题的解决方案可能与this one 非常相似。不过,我相信你的比较笼统,所以我也会尽量笼统一点……

    据我所知,没有简单的解决方案可以在图形环境中添加额外的 LaTeX 代码。您可以做的是更新knit (or output) hook(即图形块生成的LaTeX代码输出)。

    LaTeX 图形输出钩子的源代码可以在here (hook_plot_tex) 找到。可以从line 159 开始找到生成的输出。在这里我们可以看到输出的结构,我们可以在它到达乳胶引擎之前对其进行修改。

    但是,我们只想为相关的图形块修改它,而不是全部。这就是Martin Schmelzer's answer comes in handy。我们可以创建一个新的块选项,允许控制它何时被激活。作为启用caption*floatrow 的示例,我们可以定义以下编织钩

    defOut <- knitr::knit_hooks$get("plot")  
    knitr::knit_hooks$set(plot = function(x, options) {  
      #reuse the default knit_hook which will be updated further down
      x <- defOut(x, options) 
      #Make sure the modifications only take place when we enable the customplot option
      if(!is.null(options$customplot)) {  
       
        x  <- gsub("caption", "caption*", x) #(1)
        inter <- sprintf("\\floatfoot{%s}\\end{figure}", options$customplot[1]) #(2)
        x  <- gsub("\\end{figure}", inter, x, fixed=T)  #(3)
      }
      return(x)
    })
    

    我们在这里所做的是 (1) 将 \caption 命令替换为 \caption*,(2) 定义自定义 floatfoot 文本输入,(3) 将 \end{figure} 替换为 \floatfoot{custom text here}\end{figure},这样 floatfoot在 figure 环境中。

    正如您可能知道的那样,在 figure 环境中可以添加/替换的内容是无限的。只需确保将其添加到环境中并位于适当的位置即可。请参阅下面的示例,如何使用块选项启用 floatfootcaption*。 (您还可以将customplot 选项拆分为例如starcaptionfloatfoot,只需将!is.null(options$customplot) 条件分开即可。这应该可以更好地控制)

    工作示例:

    ---
    header-includes:
      - \usepackage[capposition=top]{floatrow}
      - \usepackage{caption}
    output: pdf_document
    ---
    
    
    ```{r, echo = F}
    library(ggplot2)
    
    defOut <- knitr::knit_hooks$get("plot")  
    knitr::knit_hooks$set(plot = function(x, options) {  
      x <- defOut(x, options) 
      if(!is.null(options$customplot)) {  
       
        x  <- gsub("caption", "caption*", x)
        inter <- sprintf("\\floatfoot{%s}\\end{figure}", options$customplot[1])
        x  <- gsub("\\end{figure}", inter, x, fixed=T)  
      }
      return(x)
    })
    ```
    
    ```{r echo = F, fig.cap = "Custom LaTeX hook chunk figure", fig.align="center", customplot = list("This is float text using floatfoot and floatrow")}
    ggplot(data = iris, aes(x=Sepal.Length, y=Sepal.Width))+
      geom_point()
    ```
    

    PS

    上面的示例需要启用fig.align 选项。应该很容易修复,但我没有时间研究它。

    【讨论】:

    • 这太好了,谢谢!它的局限性在于它会将相同的文本放在一个块中的每个图中,但就我今天的目的而言,这很好。
    【解决方案2】:

    @henrik_ibsen 给出了让我来到这里的答案。我对最终使用的代码进行了一些修改,以使其工作更简单:

    hook_plot_tex_footer <- function(x, options) {  
      x_out <- knitr:::hook_plot_tex(x, options) 
      if(!is.null(options$fig.footer)) {
        inter <- sprintf("\\floatfoot{%s}\n\\end{figure}", options$fig.footer[1])
        x_out <- gsub(x=x_out, pattern="\n\\end{figure}", replacement=inter, fixed=TRUE)
      }
      x_out
    }
    
    knitr::knit_hooks$set(plot=hook_plot_tex_footer)
    

    总的来说,这做同样的事情。但是,它使用knitr:::hook_plot_tex() 而不是defOut(),因此如果在同一个会话中重新运行,它仍然可以工作。而且,由于它专门进入\floatfoot,我将选项命名为fig.footer。但是,这些变化很小,答案肯定要归功于@henrik_ibsen。

    【讨论】:

      猜你喜欢
      • 2016-12-16
      • 2016-11-22
      • 2019-03-03
      • 2013-02-06
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多