19

I'm writing in R Markdown and have a contingency table that is quite wide. I am converting the R markdown document to a PDF using pandoc.

Is it possible to rotate or shrink the table? Ideally this would be done without having to switch to LaTeX formatting.

My Attempts:

I've been abusing the figure options in knitr to attempt this, but whether I use kable or xtable, I haven't had any luck. Some permutations I have tried include:

```{r out.extra='angle=90', results='asis'}
library(knitr)
kable(iris[1:5,])
``` 

``{r size='footnotesize', results='asis'}
library(knitr)
kable(iris[1:5,])
```

```{r out.extra='angle=90', results='asis'}
library(xtable)
xtable(iris[1:5,])
```

```{r size='footnotesize', results='asis'}
library(xtable)
xtable(iris[1:5,])
```  

All of these show the table nicely, but do not rotate it.

The code I'm using to knit is:

Rscript -e "library(knitr); knit('table.Rmd', 'table.md')"

And to convert to pdf:

pandoc table.md -o table.pdf
Michael Harper
  • 14,721
  • 2
  • 60
  • 84
sus
  • 335
  • 1
  • 3
  • 13
  • An alternative "solution" would be using [pander](http://rapporter.github.io/pander/#tables) that can split "too wide" tables into multiple pieces. – daroczig Feb 17 '14 at 23:08
  • My actual table is a contingency table, so it's important to be able to read all the way across it for comparison. – sus Feb 18 '14 at 00:05
  • 1
    You could try plotting the table as an image [something like this](http://blog.mollietaylor.com/2013/10/table-as-image-in-r.html), which could presumably be more easily manipulated. – Gregor Thomas Sep 15 '14 at 19:30
  • Thanks Gregor! This was the approach that worked for me! – sus Nov 06 '14 at 00:40
  • 1
    This works: http://stackoverflow.com/questions/25849814/rstudio-rmarkdown-both-portrait-and-landscape-layout-in-a-single-pdf – Jason Feb 01 '16 at 16:52

4 Answers4

15

The out.extra='angle=90' only works on Figures, and unfortunately not tables. Here are several potential approaches:

KableExtra (Rotate Page)

You can easily rotate tables using the useful addon package kableExtra. Specifically, the landscape() function will put the table on an single landscape page. It’s useful for wide tables that can’t be printed on a portrait page.

library(kableExtra)

kable(iris[1:5,],
      format = "latex", booktabs = TRUE) %>%
  kableExtra::landscape()

The limitation of these function is that it does force a new page, so depending on the size of your table it could leave a bit of blank space.

KableExtra (Scale Width)

You can scale the width of the table using the function kable_styling(latex_options = "scale_down"). This will force the table to the width of the page.

   kable(iris[1:5,],
          format = "latex", booktabs = TRUE) %>%
          kable_styling(latex_options = "scale_down")

For more examples of the kableExtra package, check out the package here: https://haozhu233.github.io/kableExtra/awesome_table_in_pdf.pdf

Stargazer (Rotate Table)

Other options are available, but these largely require the installation of additional LaTeX packages. For example, the stargazer package can print tables in landscape using the float.env argument:

```{r, results="asis"}
stargazer(iris[1:5,], 
          float.env = "sidewaystable")
```

This requires \usepackage{dcolumn} in LaTeX preamble

Read more about customising your LaTex preamble here: https://tex.stackexchange.com/questions/171711/how-to-include-latex-package-in-r-markdown

Michael Harper
  • 14,721
  • 2
  • 60
  • 84
2

You can add some LATEX code in your Rmd file :

\usepackage{lscape}
\usepackage{pdfpages}

Some text on a portrait page.

\newpage
\blandscape

## Title, lorem ipsum

```{r, results = "asis"}
kable(iris[1:5,], caption = "Lorem again")
```
Lorem ipsum...

\elandscape

Some other text on a portrait page.
mdag02
  • 1,035
  • 9
  • 16
0

Can you just use t()?

library(xtable)
xtable(t(iris[1:5,]))

If your table is still to long, split it up into multiple tables. e.g.:

splits = floor(seq(1, ncol(iris), length=5))
for(i in 2:length(splits)){
 mini.tab = iris[ , splits[i-1]:splits[i]]
 xtable(mini.tab)
}
Hillary Sanders
  • 5,778
  • 10
  • 33
  • 50
  • While that works fine for this example, my actual table is still too wide transposed! – sus Feb 18 '14 at 00:03
  • Yes, splitting the table would normally be a good option, but my table is a contingency table, so splitting it makes it much less comprehensible. – sus Feb 19 '14 at 23:13
0

Two other solutions that work if you want the titles on the same page as the table, using kable and kableExtra:

  1. Posted by user16024709 in this question Rotate table pdf output from Markdown (including a for-loop):

---
output: pdf_document
header-includes:
  \usepackage{lscape}
  \usepackage{pdfpages}
  \usepackage{graphicx}
  \usepackage[figuresright]{rotating}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```  

Report page - 


```{r results='asis', warning=FALSE, message=FALSE}  
library(knitr)
library(kableExtra)
for (i in 1:3) {
  cat('\\rotatebox{90}{')
  print(kable(iris[i:(i+5), ], format = "latex", align = "c", booktabs = TRUE,
          row.names = FALSE))
  cat('}')
  cat("\n\\newpage\n")
}
```
  1. Based on the first solution, but adjusted by me in order to use kable_styling. You have to add 'position="left"'. Otherwise you get an "! LaTeX Error: Not in outer par mode." Also no for-loop included in this.

---
output: pdf_document
header-includes:
  \usepackage{lscape}
  \usepackage{pdfpages}
  \usepackage{graphicx}
  \usepackage[figuresright]{rotating}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```  
    
```{r warning=FALSE, message=FALSE}  
library(kableExtra)
table <- kable(iris[1:5, ], format = "latex", align = "c", booktabs = TRUE, row.names = FALSE)
table <- kable_styling(table, latex_options = c("striped"), position="left", font_size=7, stripe_color="#D3D3D3")
```

# Some Title

```{r results='asis', warning=FALSE, message=FALSE}  
library(knitr)

cat('\\rotatebox{90}{')
print(table)
cat('}')
cat("\n\\newpage\n")
```