简体   繁体   中英

Automatically adjust LaTeX table width to fit pdf using knitr and Rstudio

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 

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.

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")
```

在此处输入图片说明

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.

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.

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.

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

The following works fine for me:

    print(xtable(wide.df), scalebox='0.75', floating=FALSE)

This is especially useful for tables in R Markdown.

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)]

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"
                )
            )
        )
    )    

```

Output: 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM