Reputation: 565
Using Rstudio and knitr to produce latex-tables in pdf, how do I make wide tables fit the page? I'm basically looking for at way to shrink the tables.
With figures, it is really easy in Knitr using out.width=, but with tables I can't seem find a way to do it.
Any suggestions?
\documentclass{article}
\begin{document}
The following tables are too wide to fit the pdf. I hope there is a simple way to shrink them to fit. In this example I've used tables generated from the xtable(), stargazer() and latex() functions.
<<message=FALSE>>=
library(xtable)
library(stargazer)
library(Hmisc)
library(tables)
wide.df <- cbind(iris[1:10,],iris[1:10,],iris[1:10,])
@
<<results='asis'>>=
xtable(wide.df)
@
<<results='asis'>>=
stargazer(wide.df,summary=FALSE)
@
<<results='asis'>>=
latex( tabular( Species ~ (Sepal.Length +Sepal.Length + Sepal.Width + Petal.Length + Petal.Width )*(mean + sd + mean + mean ) , data=iris) )
@
\end{document}
Following Stat-R's suggestions I've tried to use resizebox but can't get it to work:
\documentclass{article}
\usepackage{graphicx}
\begin{document}
I've tried to use reshapebox but I am really clueless on how to get it to work in Rstudio/knitr:
<<message=FALSE>>=
library(xtable)
wide.df <- cbind(iris[1:10,],iris[1:10,],iris[1:10,])
@
\resizebox{0.75\textwidth}{!}{%
<<results='asis'>>=
xtable(wide.df)
@
%}
\end{document}
I get this error:
! File ended while scanning use of \Gscale@box@dd.
sessioninfo()
R version 3.0.0 (2013-04-03)
Platform: i386-w64-mingw32/i386 (32-bit)
locale:
[1] LC_COLLATE=Danish_Denmark.1252 LC_CTYPE=Danish_Denmark.1252 LC_MONETARY=Danish_Denmark.1252 LC_NUMERIC=C
[5] LC_TIME=Danish_Denmark.1252
attached base packages:
[1] splines grid stats graphics grDevices utils datasets methods base
other attached packages:
[1] tables_0.7 Hmisc_3.10-1 survival_2.37-4 stargazer_3.0.1 pgirmess_1.5.7 splancs_2.01-32 spdep_0.5-56 coda_0.16-1 deldir_0.0-22
[10] maptools_0.8-23 foreign_0.8-53 MASS_7.3-26 Matrix_1.0-12 lattice_0.20-15 rgdal_0.8-9 sp_1.0-9 nlme_3.1-109 boot_1.3-9
[19] xtable_1.7-1 scales_0.2.3 plyr_1.8 reshape2_1.2.2 ggplot2_0.9.3.1
loaded via a namespace (and not attached):
[1] cluster_1.14.4 colorspace_1.2-2 dichromat_2.0-0 digest_0.6.3 evaluate_0.4.3 formatR_0.7 gtable_0.1.2 knitr_1.2
[9] labeling_0.1 LearnBayes_2.12 munsell_0.4 proto_0.3-10 RColorBrewer_1.0-5 stringr_0.6.2 tools_3.0.0
Upvotes: 37
Views: 50085
Reputation: 1457
I have an ugly but effective method for doing this in Stargazer. It looks like it is longer than the approaches above, but if you are reporting regression output, this may be an easier workflow for you as it was for me.
The function "WrapPageWidthLatex " appends / prepends the resize box code to stargazer output. It assumes that you've set float = FALSE and I've set up a number of other options to conserve space in my table. The rest is just to clean up the resulting output. "include=FALSE" helps suppress the annoying stargazer citation information in your document. "float = FALSE" helps suppress the latex code that would otherwise make this into a float. This makes it much easier to append the needed code. "column.sep.width = "0pt"" and "font.size="tiny"" help with get the columns narrower and therefore reducing the need for rescaling.
title: "StackOverflow Example"
author: "Bkay"
date: "6/15/2020"
output:
beamer_presentation:
keep_tex: true
header-includes:
- \usepackage{dcolumn}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(stargazer)
```
## Slide with R Output
```{r rcodehere, results='asis', warning = FALSE, echo=FALSE}
WrapPageWidthLatex <- function(InputCode){
OutputCode = append("\\resizebox{\\textwidth}{!}{", InputCode)
OutputCode = rlang::prepend("}", OutputCode)
return(OutputCode)
}
x = -10:10
xsqr = x^2
y = 2 + x*3 + 0.2 * xsqr + rnorm(length(x))
model1 = lm(y ~ x)
model2 = lm(y ~ x + xsqr)
cat(
WrapPageWidthLatex(
capture.output(
stargazer(
model1, model2,
align=TRUE,
omit.stat=c("adj.rsq", "ser", "f"),
font.size="tiny",
header=FALSE,
column.sep.width = "0pt",
float = FALSE,
type="latex"
)
)
)
)
```
Upvotes: 0
Reputation:
A huxtable
-based solution (my package):
library(huxtable)
h <- as_hux(iris)
width(h) <- 0.5
This doesn't guarantee the table won't exceed the specified width, and if so it will overrun. Possible solutions include changing the font size:
font_size(h) <- 8
Or splitting the table:
h1 <- h[, 1:5]
h2 <- h[, -(1:5)]
Upvotes: 1
Reputation: 15429
Updating to reflect the changes in code past few years, and the preference for people to typically work in .RMarkdown instead of Rnw file format.
The kableExtra
package in R is the easiest way for adjusting the size of tables. 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
Here is an example MWE:
---
title: "MWE"
author: "Mikey Harper"
date: "7 November 2017"
output: pdf_document
---
```{r setup, include=FALSE}
library(kableExtra)
library(magrittr)
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
# Build the dataframe
wide.df <- cbind(iris[1:10,],iris[1:10,],iris[1:10,])
```
```{r}
# Basic table
knitr::kable(wide.df)
```
```{r}
# Scaled Table
knitr::kable(wide.df, format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = "scale_down")
```
Upvotes: 19
Reputation: 191
The following works fine for me:
print(xtable(wide.df), scalebox='0.75', floating=FALSE)
This is especially useful for tables in R Markdown.
Upvotes: 1
Reputation: 21507
Another option might be something like:
my_wrap <- function(x, width) {
x_split <- strwrap(x, width = width, simplify = FALSE)
x_split <- lapply(x_split, paste, collapse = " \\\\ ")
vapply(x_split, function(s) sprintf("\\begin{tabular}[x]{@{}c@{}}%s\\end{tabular}", s),
character(1))
}
applied to all columns that are to wide
Upvotes: 0
Reputation: 177
The following are some typical steps that you can take to shrink the table size.
\setlength{\tabcolsep}{1pt}
\resizebox{\linewidth}{!}{ %% <-- The most effective way to fit a table / figure
\begin{tabular}
...
...
\end{tabular}
} %resizebox
For text use \sf
mode to make the text more visible.
Upvotes: 2
Reputation: 10203
You can pass a scalebox
argument to print.xtable
like so
<<results='asis'>>=
print(xtable(wide.df), scalebox='0.75')
@
That doesn't automatically resize the table to fit the page (unfortunately xtable
doesn't support a resizebox
argument) but for many applications the above might be good enough.
The problem with your code is that xtable
returns the table wrapped in a table
environment and not just a tabular. What you have to wrap in the resizebox
, however, is the tabular
. The only way I can see to get this to work as you want it is to let xtable return only the tabular
, like so:
\begin{table}
\resizebox{\textwidth}{!} {
<<results='asis'>>=
print(xtable(wide.df), floating=FALSE)
@
}
\end{table}
and then to write the LaTeX code around it manually.
Upvotes: 19
Reputation: 5165
The LaTeX package tabulary
is better in fitting a table to the page width. It can be told to break lines for example. But I don't know if you can use it with xtable.
Upvotes: 0
Reputation: 28682
What about automatically splitting the wide tables to parts just like on the good old 80 character wide VT100 terminals? This is usually a good practice for LaTex/docx/odt tables and set by default in pander:
> set.caption('Hello Fisher!')
> pander(wide.df)
---------------------------------------------------------
Sepal.Length Sepal.Width Petal.Length Petal.Width
-------------- ------------- -------------- -------------
5.1 3.5 1.4 0.2
4.9 3 1.4 0.2
4.7 3.2 1.3 0.2
4.6 3.1 1.5 0.2
5 3.6 1.4 0.2
5.4 3.9 1.7 0.4
4.6 3.4 1.4 0.3
5 3.4 1.5 0.2
4.4 2.9 1.4 0.2
4.9 3.1 1.5 0.1
---------------------------------------------------------
Table: Hello Fisher! (continued below)
-----------------------------------------------------
Species Sepal.Length Sepal.Width Petal.Length
--------- -------------- ------------- --------------
setosa 5.1 3.5 1.4
setosa 4.9 3 1.4
setosa 4.7 3.2 1.3
setosa 4.6 3.1 1.5
setosa 5 3.6 1.4
setosa 5.4 3.9 1.7
setosa 4.6 3.4 1.4
setosa 5 3.4 1.5
setosa 4.4 2.9 1.4
setosa 4.9 3.1 1.5
-----------------------------------------------------
Table: Table continues below
----------------------------------------------------
Petal.Width Species Sepal.Length Sepal.Width
------------- --------- -------------- -------------
0.2 setosa 5.1 3.5
0.2 setosa 4.9 3
0.2 setosa 4.7 3.2
0.2 setosa 4.6 3.1
0.2 setosa 5 3.6
0.4 setosa 5.4 3.9
0.3 setosa 4.6 3.4
0.2 setosa 5 3.4
0.2 setosa 4.4 2.9
0.1 setosa 4.9 3.1
----------------------------------------------------
Table: Table continues below
--------------------------------------
Petal.Length Petal.Width Species
-------------- ------------- ---------
1.4 0.2 setosa
1.4 0.2 setosa
1.3 0.2 setosa
1.5 0.2 setosa
1.4 0.2 setosa
1.7 0.4 setosa
1.4 0.3 setosa
1.5 0.2 setosa
1.4 0.2 setosa
1.5 0.1 setosa
--------------------------------------
Please see ?pandoc.table
and table.split.table
in ?panderOptions
for more details.
Upvotes: 1