Rstudio rmarkdown:如何在单个PDF文件中实现纵向和横向页面布局

114
我想知道如何使用 rmarkdown 生成一个既有纵向又有横向布局的pdf文档。如果有纯粹的 rmarkdown 选项,那就比使用latex更好了。
这里有一个简单可复现的示例。首先,在RStudio中呈现这个 .Rmd(点击Knit PDF按钮),生成的pdf所有页面都是横向布局:
---
title: "All pages landscape"
output: pdf_document
classoption: landscape
---

```{r}
summary(cars)
```

\newpage
```{r}
summary(cars)
```

接下来是尝试创建一个混合纵向和横向布局的文档。基本设置在YAML中根据这里的'Includes'部分完成(链接)。文件'in_header'中只包含\usepackage{lscape},这是一个建议用于knitr横向布局的包(链接).tex文件与.Rmd文件在同一目录中。

---
title: "Mixing portrait and landscape"
output:
    pdf_document:
        includes:
            in_header: header.tex
---

Portrait:
```{r}
summary(cars)
```

\newpage
\begin{landscape}
Landscape:
```{r}
summary(cars)
```
\end{landscape}

\newpage
More portrait:
```{r}
summary(cars)
```

然而,这段代码会导致错误:
# ! You can't use `macro parameter character #' in horizontal mode.
# l.116 #

# pandoc.exe: Error producing PDF from TeX source
# Error: pandoc document conversion failed with error 43

非常感谢您的帮助。

6个回答

110

因此,pandoc 无法 解析LaTeX环境的内容,但是您可以通过在header.tex文件中重新定义命令来欺骗它:

\usepackage{lscape}
\newcommand{\blandscape}{\begin{landscape}}
\newcommand{\elandscape}{\end{landscape}}

因此,这里将\begin{landscape}重新定义为\blandscape,将\end{landscape}重新定义为\elandscape。在.Rmd文件中使用这些新定义的命令似乎可以正常工作:

---
title: "Mixing portrait and landscape"
output:
    pdf_document:
        includes:
            in_header: header.tex 
---

Portrait
```{r}
summary(cars)
```

\newpage
\blandscape
Landscape
```{r}
summary(cars)
```
\elandscape

\newpage
More portrait
```{r}
summary(cars)
```

6
这是一个复杂的工具链,有三到四个不同的组成部分(knitr-rmarkdown/pandoc-latex),我发现除了文档中提到的内容之外,很难弄清楚哪些地方出了问题。最好的方法似乎是独立运行它们:首先进行编织,查看生成的 .md 文件(可以),然后进行 md->tex 转换(这就是出错的地方)。错误信息并没有帮助,因为已经进入了下一步(latex)。 - baptiste
使用此解决方案后,在 PDF 中,"#Introduction" 创建的结构化标题将以符号 # 的形式出现。 - JMarcelino
5
我猜这是一个愚蠢的LaTeX问题:header.tex文件应该放在哪里,以便被读取?我经常使用RMarkdown,但相对较新,还没有完全理解所有相互关联的包及其如何一起运作。请注意,我会尽力使用通俗易懂的语言进行翻译,但不会改变原意。 - Mike Williamson
header.tex文件应该在同一个目录下。 - baptiste
1
使用这种方法,页面编号在页面的左侧而不是底部。有什么想法吗? - Karen Liu
显示剩余3条评论

74
建立在之前的解决方案基础上,以下方案不需要辅助的 header.tex 文件,并且所有内容都包含在 .Rmd 文件中。LaTeX 命令是在 YAML 头部的 header-includes 块中定义的。更多信息可以在这里找到。
此外,我发现使用 lscape LaTeX 包旋转页面内容,但并不旋转 PDF 页面本身。这个问题可以通过使用 pdflscape 包来解决。
---
title: "Mixing portrait and landscape WITHOUT a header.tex file"
header-includes:
- \usepackage{pdflscape}
- \newcommand{\blandscape}{\begin{landscape}}
- \newcommand{\elandscape}{\end{landscape}}
output: pdf_document
---

Portrait
```{r}
summary(cars)
```

\newpage
\blandscape
Landscape
```{r}
summary(cars)
```
\elandscape

\newpage
More portrait
```{r}
summary(cars)
```

1
在我的系统上,这个解决方案没有起作用。我正在运行R-3.4.4、rmarkdown_1.9、knitr_1.20,在Mac OS_10.13.4上运行。想知道可能是什么问题? - Geochem B
@GeochemB LaTeX必备的包是否已正确安装?我最近使用TinyTeX 取得了成功,并推荐使用它。 - Megatron
1
@GeochemB 我使用这段代码也遇到了同样的问题。我尝试在SumatraPDF v3.1.1和Adobe Acrobat DC和Pro中查看文档。根据文档,Oberdeik已经包含在MikTex中。据我所知,如果我安装了MikTex,pdflscape应该是可以用的。不知道是否有人找到了解决方案。 - Patrick
2
这个很好用,但是页面数字会在横向页面的左侧侧向打印。有没有简单的方法来解决这个问题并仍然保留页面数字? - djhocking
1
我和@djhocking有同样的问题。有人知道答案吗? - Chris
显示剩余5条评论

26

针对最常见的情况。

有三种条件。

  1. 全部为竖屏模式。
  2. 全部为横屏模式。
  3. 混合了竖屏模式和横屏模式。

让我们逐一讨论每个条件。

  1. 首先考虑第一种情况,假设我们有一个以以下代码开头的Markdown文档。当你在Rstudio中创建一个rmd文件时,默认设置就是这样。当你运行它时,它会自动假定它是竖屏模式,毫无疑问。

title: "Landscape and Portrait"
    author: "Jung-Han Wang"
    date: "Thursday, March 19, 2015"
    output: pdf_document
当您想将PDF文件编织为横向模式时,唯一需要添加的是classoption: landscape。
    title: "Landscape and Portrait"
    author: "Jung-Han Wang"
    date: "Thursday, March 19, 2015"
    output: pdf_document
    classoption: landscape
如果你想要混合两者,你需要在YAML中添加.tex文件,并参考我上面提到的链接下载.tex代码。你可以在这里下载.tex代码:http://goo.gl/cptOqg 或者只需复制代码并将其保存为header.tex。然后,为了更方便,将这个.tex文件与要编织的rmd文件放在一起。确保你完成了以下两件事情: 复制tex文件并将其与rmd文件移动到同一个文件夹。 修改rmd的开头为:
 title: "Landscape and Portrait"
    author: "Jung-Han Wang"
    date: "Thursday, March 19, 2015"
    output:
      pdf_document:
        includes:
          in_header: header.tex
这是我在解决这个问题时的总结,大部分受益于baptiste的答案。在我的博客(点击此处)中包含了一些快照和例子。
希望对你有所帮助。 祝你好运。

2
你的方法可行。为了更容易理解,我认为 pandoc 的问题在于当你使用环境而不是宏时,它会变得奇怪。这就是为什么我在我的头文件中(pdflandscape 包)包含了你建议的 \newcommand{\blandscape}{\begin{landscape}} 和 \newcommand{\elandscape}{\end{landscape}},它完美地工作了。谢谢! - gvegayon
1
我按照上述步骤(参考博客)进行操作,效果非常好。谢谢! - Scott Worland
1
代码链接已失效 - robertspierre

7
如Baptiste所提到的,如果您将R命令放在LaTeX环境中,则pandoc不会解析它们,并将它们原样放置到生成的LaTeX中:这就是导致错误的原因。除了Baptiste的简单有效的解决方法外,您还可以使用xtable R包,该包提供了从R输出创建更漂亮的LaTeX表格的可能性。要使以下示例起作用,您需要在header.tex文件中添加\usepackage{rotating}代码:
---
title: "Mixing portrait and landscape"
output:
    pdf_document:
        keep_tex: true
        includes:
            in_header: header.tex
---
```{r, echo=FALSE}
library(xtable)
```

Portrait
```{r, results='asis', echo=FALSE}
print(xtable(summary(cars), caption="Landscape table"), comment=FALSE)
```

Landscape:
```{r, results='asis', echo=FALSE}
print(xtable(summary(cars), caption="Landscape table"),
      floating.environment="sidewaystable", comment=FALSE)
```

第二个表格将被打印在sidewaystable环境中,而不是通常的table环境:因此它将在横向模式下打印,在单独的页面上。请注意,使用lscape包或sideways环境放置在横向模式下的表格和图形将始终放置在单独的页面上,请参见这份非常重要的文档的第91页: http://www.tex.ac.uk/tex-archive/info/epslatex/english/epslatex.pdf
由于我发现这有点烦人,我设法找到了一种方法,可以在同一页上同时保留纵向和横向的表格(在这个过程中浪费了我整个下午)。
---
title: "Mixing portrait and landscape"
output:
    pdf_document:
        keep_tex: true
        includes:
            in_header: header.tex
---
```{r, echo=FALSE}
library(xtable)
```

Portrait:
```{r, results='asis', echo=FALSE}
print(xtable(summary(cars), caption="Portrait table."), comment=FALSE)
```

Landscape:
```{r, results='asis', echo=FALSE}
cat(paste0(
    "\\begin{table}[ht]\\centering\\rotatebox{90}{",
    paste0(capture.output(
      print(xtable(summary(cars)), floating=FALSE, comment=FALSE)),
      collapse="\n"),
    "}\\caption{Landscape table.}\\end{table}"))
```

对于横向表格,我使用了这里提供的\rotatebox建议: http://en.wikibooks.org/wiki/LaTeX/Rotations 为了使其起作用,我只需要生成表格的tabular部分,通过print(xtable(...部分来捕获输出,并手动将其包围在tablerotatebox命令中,将所有内容转换为字符串R输出,以便pandoc不将它们视为LaTeX环境。对于纯rmarkdown解决方案...祝你好运!

这是页面上唯一对我有效的东西。谢谢你,Renato! - Stuart

1

0
使用一个header.tex文件,并按照其他答案中提到的方法添加下面的行,这对我来说效果很好。
\usepackage{pdflscape}
\newcommand{\blandscape}{\begin{landscape}}
\newcommand{\elandscape}{\end{landscape}}

然而,正如一些评论中指出的那样,这也会使页面编号旋转,以至于它们位于横向页面的左侧。它们也朝着错误的方向。如果您可以接受简单地省略页面编号,将这行LatEx代码添加到您的RMarkdown文件中可以解决这个问题。
\pagenumbering{gobble}

如果您想保留页面编号并将其放置在页面底部,您可以使用fancyhdr和lastpage LaTeX包提供的自定义页面编号解决方案,具体方法请参考这里

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