使用knitr和pandoc将Markdown转换为PDF时的图像位置

55

我正在尝试使用knitr和pandoc将图形转换为PDF时控制其位置。我的.Rmd文件如下:

# My report

Some text some text some text some text some text some text some text some text some text


```{r myplot, echo=FALSE, fig.pos="placeHere", results='hide'}

library(ggplot2)

ggplot(mtcars, aes(mpg, drat)) + geom_point()

```

Some text some text some text some text some text some text some text some text some text

\usepackage{graphicx}
\begin{figure}[placeHere]
  \centering
    \includegraphics[width=0.5\textwidth]{placeHere}
\end{figure}

Some text some text some text some text some text some text some text some text some text

我正在使用这里提供的函数将内容转换为PDF:http://quantifyingmemory.blogspot.co.uk/2013/02/reproducible-research-with-r-knitr.html

如何将图形放置在第二和第三段文字之间?当前的LaTeX代码不起作用。

编辑:这是我现在尝试的内容。

# My report

   ```{r setup, include=FALSE}
# set global chunk options
opts_chunk$set(cache=FALSE)
library(ggplot2)
```

```{r, echo=FALSE, fig.height=3}

ggplot(mtcars, aes(disp, hp)) + geom_point()


```



Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 

Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 


Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 


Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 


```{r, echo=FALSE, fig.height=3}



ggplot(mtcars, aes(vs, am)) + geom_point()


```



Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 

Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 


Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 


```{r, echo=FALSE, fig.height=6}



ggplot(mtcars, aes(disp, cyl)) + geom_point()

```


```{r, echo=FALSE, fig.height=6}

ggplot(mtcars, aes(hp, qsec)) + geom_point()


```


Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 




```{r, echo=FALSE, fig.height=3}

ggplot(mtcars, aes(hp, wt)) + geom_point()

```



Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 



```{r, echo=FALSE, fig.height=5}

ggplot(mtcars, aes(mpg, drat)) + geom_point()

```




Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 

我可能说错了,但我认为你想要控制latex。你想要像这里所示的那样处理浮动位置:http://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions。 - Tyler Rinker
你是否混淆了knitr的Rnw和Rmd语法? - Tyler Rinker
我已经查看了维基页面,并尝试跟随代码。然而,仍然无法将图形放置在我想要的位置。帖子已更新,附上了我尝试过的代码。 - luciano
你为什么编辑了你的代码?这样做会让未来的访问者看不懂注释和其他内容。建议你添加代码而不是修改原有的代码。我已经根据这个建议编辑了你的问题。 - Tyler Rinker
如果其他解决方案不起作用,我已经发布了我的解决方案:https://dev59.com/YF0b5IYBdhLWcg3wA9PI#48920525 - Pablo Casas
显示剩余3条评论
8个回答

101

我提出了一种替代方案。不是事后在LaTeX文档中插入[H]符号,而是建议重新定义图形环境来忽略任何位置参数并使用[H]。

要做到这一点,请在与.Rmd文件相同的目录中创建一个.tex文件,该文件重新定义图形环境,并在.Rmd的YAML标头中更新文件以在编译期间包含它。

以下是.tex文件的示例:

\usepackage{float}
\let\origfigure\figure
\let\endorigfigure\endfigure
\renewenvironment{figure}[1][2] {
    \expandafter\origfigure\expandafter[H]
} {
    \endorigfigure
}

这里是包含它的.Rmd示例(假设您将.tex文件命名为“preamble-latex.tex”):

---
title: "example"
author: "you"
date: "`r format(Sys.time(), '%d %B %Y')`"
output:
  rmarkdown::pdf_document:
    fig_caption: yes        
    includes:  
      in_header: preamble-latex.tex
---

```{r, fig.cap='Markdownvellous!'}
plot(1:10, 1:10)
```

8
这个方法很好,我认为比被接受的答案要好得多。不过你可以简化一下,因为这里与图示等参考资料无关。 - bjw
2
完美的解决方案。我已经寻找它一段时间了。 - Farid Cheraghi
3
我完全同意这个答案比我的(五年前发布的)更优雅,我鼓励发帖人接受这个答案。 - Yihui Xie
这个答案似乎也适用于普通的rmarkdown包含图像,例如![图](fig.png),很好! - Matifou
2
如果像我一样,您同时遇到了表格漂浮到 PDF 页面底部的问题,那么这里有一个解决方案:https://dev59.com/wVcP5IYBdhLWcg3wHmxU - puslet88
显示剩余2条评论

30

对于将Markdown文档转换为LaTeX时,我不知道pandoc是否有设置浮动选项的选项。如果您选择Markdown是因为它的简单性,那么即使使用像pandoc这样强大的工具,也不应该期望太多功能。总之:Markdown不是LaTeX。它是为HTML而设计的,而不是LaTeX。

有两种方法可供选择:

  1. 使用Rnw语法(R + LaTeX)代替Rmd(R Markdown)(示例);在此情况下,您可以在导言中添加\usepackage{float},然后使用代码块选项fig.pos='H',从而完全掌控LaTeX操作,而无需使用pandoc。

  2. 修改pandoc生成的LaTeX文档,例如:

    library(knitr)
    knit('foo.Rmd')  # gives foo.md
    pandoc('foo.md', format='latex')  # gives foo.tex
    x = readLines('foo.tex')
    # insert the float package
    x = sub('(\\\\begin\\{document\\})', '\\\\usepackage{float}\n\\1', x)
    # add the H option for all figures
    x = gsub('(\\\\begin\\{figure\\})', '\\1[H]', x)
    # write the processed tex file back
    writeLines(x, 'foo.tex')
    # compile to pdf
    tools::texi2pdf('foo.tex')  # gives foo.pdf
    
    如果您不喜欢这些解决方案,可以考虑在 Github 上向 Pandoc 提出新功能的请求,然后坐下来等待。

如果您不喜欢这些解决方案,可以考虑 在 Github 上请求新功能 给Pandoc,然后坐下来等待。


2
因为我花了20分钟才找到它,所以在这里评论一下,@yihui和他的团队在bookdown中包含了一个特殊选项来实现这个功能:https://bookdown.org/yihui/rmarkdown-cookbook/figure-placement.html#fn10 - Julien Colomb

18

我正在使用RStudio中的KnitR和Markdown,对于我的情况,解决方案是在导言中添加\usepackage{float}

    ---
title: "Proyect 2"
author: "FV"
date: "2016-12-3"
output:
  pdf_document:
    fig_caption: yes
    fig_crop: no
    fig_height: 2
    fig_width: 3
    highlight: haddock
    keep_tex: yes
    number_sections: yes
    toc: yes
    toc_depth: 2
  html_document:
    fig_caption: yes
    theme: journal
    toc: yes
    toc_depth: 2
header-includes: 
- \usepackage{graphicx}
- \usepackage{float}
---

然后在最前面添加这行代码(fig.pos='H'):

```{r echo=FALSE,warning=FALSE}
 library(knitr)
  opts_chunk$set(fig.path='figure/graphics-', 
                 cache.path='cache/graphics-', 
                 fig.align='center',
                 external=TRUE,
                 echo=TRUE,
                 warning=FALSE,
                 fig.pos='H'
                )
  a4width<- 8.3
  a4height<- 11.7
```

我刚刚发现,如果它不起作用,请将fig.pos='H'更改为fig.pos="H",使用双引号。 - Ferran VilBer
我不能否认你的经验,但一般情况下这并不重要。在R中,单引号和双引号之间没有解释上的区别。https://dev59.com/N2Ij5IYBdhLWcg3wJCF-#20572492 - dfrankow

11
如果您只想手动控制图形的位置,请使用此网页: http://www.rci.rutgers.edu/~ag978/litdata/figs/,我发现如果在绘图命令后添加一个反斜杠“\”,则图形将不会浮动,而是在其当前位置打印。
如果您只想显示某些图形,则可以为每个图形修改该选项。
在您的示例中:
# My report

```{r setup, include=FALSE}
# set global chunk options
knitr::opts_chunk$set(cache=FALSE)

library(ggplot2)
```

Some text Some text Some text Some text Some text Some text Some text Some       text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 

```{r, echo=FALSE, fig.height=3}
ggplot(mtcars, aes(disp, hp)) + geom_point()
```
\

Some text Some text Some text Some text Some text Some text Some text Some       text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some text Some textSome text Some text Some text 

(etc)


1
对我来说,这会破坏图题和图的对齐。 - jsta
这是第一个对我有用的建议!这也适用于在代码块之外的Markdown文本中包含来自文件的图像。非常感谢! - emudrak

9

我有一些项目需要将.Rmd文件转换为.pdf文件(主要是beamer幻灯片演示),但我不想让图像浮动(浮动的图片在幻灯片演示中确实效果不佳)。

我使用的方法是在.md文件中的行末添加一个转义空格。这意味着图像位于一个段落内,而不是作为一个段落存在。这意味着pandoc不会将其包装在figure环境中(也就意味着我不能在图像上使用标题),从而使它恰好处于那个位置。

我使用Makefile来完成所有转换工作,因此在运行R和knitr后,它会自动运行Perl脚本(虽然也可以使用R或其他工具)来查找插入图像的位置并在行末添加转义空格。


7
这个答案解决了我的问题。对于那些不知道什么是转义空格的人,你可以使用反斜杠进行转义,就像这样:![SourceTree 提交信息](images/sourcetree-commit-message.png)\ - pwaring

6

使用knitr钩子

我偶然发现了这个问题,并想添加另一种方法。在这里,我利用了knitr钩子提供的强大灵活性。我只需将绘图钩子更改为使用knitr函数hook_plot_tex()。之后,我可以像在Rnw文档中一样使用块选项fig.pos来定位figure环境(必须设置fig.cap以调用figure环境)。

这在OP提供的示例中有效。我猜它们也适用于(某种程度上)更复杂的示例。为什么可以如此轻松地完成这项工作并且不是Rmd文档的默认设置,我不确定。也许Yihui可以澄清一下。

以下是代码:

---
title: "Example"
author: "Martin"
output: pdf_document
---

```{r}
knitr::knit_hooks$set(plot = function(x, options)  {
  hook_plot_tex(x, options)
})
```


```{r myplot, echo=FALSE, results='hide', fig.cap='Test', fig.pos='h'}
library(ggplot2)
ggplot(mtcars, aes(mpg, drat)) + geom_point()
```

如果没有fig.pos='h',这个图通常会跳到第二页。


如果 pandoc 抛出错误,请确保添加 fig.pos = 'h'。 - cibr

0

这是你想要的吗:

```{r setup, include=FALSE}
# set global chunk options
opts_chunk$set(cache=FALSE)
library(ggplot2)
```

# My report

Some text some text some text some text some text some text some text some text some text

Some text some text some text some text some text some text some text some text some text

```{r myplot, echo=FALSE}

ggplot(mtcars, aes(mpg, drat)) + geom_point()

```

Some text some text some text some text some text some text some text some text some text

如果在每个图中保持图高度相同,那似乎是有效的。但如果图高度不同,则无法正常工作。我已经编辑了帖子,更接近于我的实际文档外观。如果您尝试我的代码,您会发现PDF中的图形顺序与.Rmd文件中的顺序不同。 - luciano
你看过knitr的文档了吗?out.height='380px'请花些时间阅读文档。Yihui花费了大量时间制作了非常好的文档和最小化的示例。 - Tyler Rinker
在花更多时间研究之后,我意识到问题出现在将由knitr输出的.md文件转换为.pdf文件(通过Pandoc)。在.md文件中的html代码后添加反斜杠可以控制图形的放置位置,就像这样:![plot of chunk unnamed-chunk-1](figure/unnamed-chunk-1.png)\。然而,这引入了一个新问题:图形说明消失了。问题继续......! - luciano

0

解决方案并不是太直接,也许有人能够简化它。

基本步骤。(Windows 7)

  1. 您可以向knitr选项中添加参数fig.pos="H",可以全局设置或为每个代码块设置。注意要大写H。这将指示latex在Rmd文件中调用图片的位置。确切地放置图片浮动。

  2. 但是,这需要使用latex包,您可以在pandoc用于构建pdf文件的模板中指定。方法是在模板中添加以下行:\usepackage{float}

  3. 但是,您首先需要找到要修改的当前模板文件。我无法在任何地方找到它,但您可以使用此命令让pandoc将模板内容打印到控制台:pandoc -D latex

  4. 将该模板代码剪切并粘贴到空文本文件中。

  5. 添加以下行:\usepackage{float}

  6. 将其另存为文件名"default.latex",保存在一个目录中,例如 C:\Users\YOURNAME\pandoc\templates

  7. 将选项 --data-dir=C:/Users/YOURNAME/pandoc/templates" 添加到您对pandoc的调用中,或者如果使用R中的pander,则使用 Pandoc.convert("my file.md", format="pdf", options=c("--data-dir=C:/Users/YOURNAME/pandoc/templates"))

我希望这对您有用。

这个人试图从一个Rmd文件而不是Rnw文件制作一个html2pdf文档。 - Tyler Rinker
你是对的,抱歉。它不起作用。我不知道为什么我认为它会。 - Andrew

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