如何使用knitr/rmarkdown自定义LaTeX图表

5
我想在使用ggplot2创建的图形浮动体内创建页脚,并将其嵌入到通过LaTeX生成PDF格式的rmarkdown文档中。
我的问题是:在rmarkdown / knitr中是否有一种方法可以在图形环境中添加更多的LaTeX命令?
具体而言,我希望找到一种方法,在图形环境中使用floatrow或caption*宏插入自定义LaTeX,如https://tex.stackexchange.com/questions/56529/note-below-figure所描述的。
当我查看代码块选项(https://yihui.org/knitr/options/#plots)时,像out.extra似乎接近我想要的,但它用作\includegraphics的额外选项,而我想要访问将额外的LaTeX放入图形环境中,超出任何其他LaTeX命令之外。
2个回答

2
你的问题解决方案可能与这个问题非常相似。然而,我认为你的问题更加普遍,所以我会尽量提供更一般化的解决方案...
据我所知,在图形环境中添加额外的LaTeX代码并没有简单的解决方案。你可以更新钩子(即图形块生成的LaTeX代码)knit(或输出)钩子
LaTeX图形输出钩子的源代码可以在这里(hook_plot_tex找到。生成的输出从第159行开始。在这里,我们可以看到输出的结构,并且在它到达LaTeX引擎之前修改它。
然而,我们只想为相关的图形块修改它,而不是所有图形块。这就是Martin Schmelzer的答案有用的地方。我们可以创建一个新的块选项,允许控制何时激活它。例如,启用使用caption*floatrow,我们可以定义以下knit钩子。
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) 用 \floatfoot{custom text here}\end{figure} 替换 \end{figure},使 floatfoot 在 figure 环境中。
正如您可能已经注意到的那样,在 figure 环境中,您可以添加/替换的内容不限。只需确保它被添加到环境中并位于适当位置即可。请参见下面的示例,了解如何使用 chunk 选项启用 floatfootcaption*。(您还可以通过将 !is.null(options$customplot) 条件分割来将 customplot 选项拆分为例如 starcaptionfloatfoot。这应该允许更好的控制)
工作示例:
---
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选项。应该很容易解决,但我没有时间去研究它。


1
这太棒了,谢谢!它的限制是在一个块中放置相同的文本,但对于我今天的目的来说,这是可以接受的。 - Bill Denney

1

@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。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接