如何使用 knitr/rmarkdown 自定义图形 LaTeX
How to Customize figure LaTeX with knitr/rmarkdown
我想在通过 LaTeX 生成 .pdf 文件的 rmarkdown 文档中使用 ggplot2 创建的图形在浮动中创建一个页脚。
我的问题:rmarkdown/knitr 是否有办法在 figure 环境中添加更多 LaTeX 命令?
具体来说,我想找到一种使用 floatrow
或 caption*
宏插入自定义 LaTeX 的方法,如 https://tex.stackexchange.com/questions/56529/note-below-figure 中所述,在 figure 环境中。
当我查看块选项 (https://yihui.org/knitr/options/#plots) 时,out.extra
之类的东西似乎接近我想要的,但它被用作 \includegraphics
的额外选项,而我想要在图形环境中放置额外的 LaTeX,在任何其他 LaTeX 命令之外。
您的问题的解决方案可能与 非常相似。但是,我相信你的更笼统一些,所以我也会尝试更笼统一些...
据我所知,没有简单的解决方案可以在 figure 环境中添加额外的 LaTeX 代码。您可以做的是更新 knit (or output) hook(即图形块生成的 LaTeX 代码输出)。
可以找到 LaTeX 图形输出钩子的源代码 here (hook_plot_tex
). The output generated can be found starting at line 159。在这里我们可以看到输出的结构,我们可以在它到达乳胶引擎之前对其进行修改。
但是,我们只想修改相关的图形块,而不是全部。这是 的地方。我们可以创建一个新的块选项,允许控制它何时被激活。作为启用 caption*
和 floatrow
的示例,我们可以定义以下 knit hook
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 环境中。
您可能会说,天空是您在图形环境中所能做到的极限 add/replace。只需确保将其添加到环境中并位于适当的位置即可。请参阅下面的示例,了解块选项如何用于启用 floatfoot
和 caption*
。 (您也可以通过简单地划分 !is.null(options$customplot)
条件,将 customplot
选项拆分为例如 starcaption
和 floatfoot
。这应该允许更好的控制)
工作示例:
---
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
选项。应该很容易修复,但我没有时间研究它。
@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.
我想在通过 LaTeX 生成 .pdf 文件的 rmarkdown 文档中使用 ggplot2 创建的图形在浮动中创建一个页脚。
我的问题:rmarkdown/knitr 是否有办法在 figure 环境中添加更多 LaTeX 命令?
具体来说,我想找到一种使用 floatrow
或 caption*
宏插入自定义 LaTeX 的方法,如 https://tex.stackexchange.com/questions/56529/note-below-figure 中所述,在 figure 环境中。
当我查看块选项 (https://yihui.org/knitr/options/#plots) 时,out.extra
之类的东西似乎接近我想要的,但它被用作 \includegraphics
的额外选项,而我想要在图形环境中放置额外的 LaTeX,在任何其他 LaTeX 命令之外。
您的问题的解决方案可能与
据我所知,没有简单的解决方案可以在 figure 环境中添加额外的 LaTeX 代码。您可以做的是更新 knit (or output) hook(即图形块生成的 LaTeX 代码输出)。
可以找到 LaTeX 图形输出钩子的源代码 here (hook_plot_tex
). The output generated can be found starting at line 159。在这里我们可以看到输出的结构,我们可以在它到达乳胶引擎之前对其进行修改。
但是,我们只想修改相关的图形块,而不是全部。这是 caption*
和 floatrow
的示例,我们可以定义以下 knit hook
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 环境中。
您可能会说,天空是您在图形环境中所能做到的极限 add/replace。只需确保将其添加到环境中并位于适当的位置即可。请参阅下面的示例,了解块选项如何用于启用 floatfoot
和 caption*
。 (您也可以通过简单地划分 !is.null(options$customplot)
条件,将 customplot
选项拆分为例如 starcaption
和 floatfoot
。这应该允许更好的控制)
工作示例:
---
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
选项。应该很容易修复,但我没有时间研究它。
@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.