Search code examples
rlatexknitrxtable

xtable and knitr: How to center table on full page width?


(This question does not solve this because that was about centering within linewidth. I'm interested in the full page width.)

I'm producing a table like this:

\documentclass{article}

\begin{document}

<<tabletest, message=F, warning=F, echo = F, results = "asis">>=
library(readr)
library(xtable)
# Create dummy data.frame
values <- 1:14
df <- t(data.frame(values, values))
colnames(df) <- paste("column", values, sep="")
rownames(df) <- c("row1", "row2")
ltable <- xtable(
  x = df
)
print(ltable)
@

\end{document}

The result looks like this:

enter image description here

I want to center this horizontally on the page. My first try was wrapping the chunk in \centerline{}, but that got me this:

Runaway argument?
{ \begin {table}[ht] \centering \begin {tabular}{rrrrrrrrrrrrrrr} \hline \ETC.
! Paragraph ended before \centerline was complete.
<to be read again> 
                   \par

The interesting part in the resulting .tex file looks like this:

\centerline{
% latex table generated in R 3.2.5 by xtable 1.8-2 package
% Mon Apr 25 16:40:48 2016
\begin{table}[ht]
\centering
\begin{tabular}{rrrrrrrrrrrrrrr}
  \hline
 & column1 & column2 & column3 & column4 & column5 & column6 & column7 & column8 & column9 & column10 & column11 & column12 & column13 & column14 \\ 
  \hline
row1 &   1 &   2 &   3 &   4 &   5 &   6 &   7 &   8 &   9 &  10 &  11 &  12 &  13 &  14 \\ 
  row2 &   1 &   2 &   3 &   4 &   5 &   6 &   7 &   8 &   9 &  10 &  11 &  12 &  13 &  14 \\ 
   \hline
\end{tabular}
\end{table}

}

If I manually edit that to this:

% latex table generated in R 3.2.5 by xtable 1.8-2 package
% Mon Apr 25 16:40:48 2016
\begin{table}[ht]
\centerline{
\begin{tabular}{rrrrrrrrrrrrrrr}
  \hline
 & column1 & column2 & column3 & column4 & column5 & column6 & column7 & column8 & column9 & column10 & column11 & column12 & column13 & column14 \\ 
  \hline
row1 &   1 &   2 &   3 &   4 &   5 &   6 &   7 &   8 &   9 &  10 &  11 &  12 &  13 &  14 \\ 
  row2 &   1 &   2 &   3 &   4 &   5 &   6 &   7 &   8 &   9 &  10 &  11 &  12 &  13 &  14 \\ 
   \hline
\end{tabular}
}
\end{table}

Then it works. But how can I accomplish this automatically? After reading this and this, I tried:

x <- capture.output(print(xtable(ltable)))
x <- gsub("\\\\centering", "", x, fixed=TRUE) # Remove \centering
x <- gsub("\\begin{table}[ht]", "\\begin{table}[ht]\\centerline{", x, fixed=TRUE) # Add \centerline{
x <- gsub("\\end{table}", "\\end{table}}", x, fixed=TRUE) # Add ending }

But the format of x is not as I got when calling print(ltable) earlier:

> print(x)
 [1] "% latex table generated in R 3.2.5 by xtable 1.8-2 package"                                                                                                                                                                                                                                                                             
 [2] "% Mon Apr 25 16:51:02 2016"

That is, this will output the brackets with numbers in front of every line and it will not produce a table. Can anyone help me with this?


Solution

  • Case 1: Non-floating table

    If the table is not supposed to float, it is easy to enclose the tabular in a makebox as suggested here:

    \documentclass{article}
    \begin{document}
    
    <<echo = F, results = "asis">>=
    library(xtable)
    
    cat("\\makebox[\\textwidth]{")
    print(xtable(t(cars)[, 1:16]), floating = FALSE)
    cat("}")
    
    @
    \end{document}
    

    Output case 1

    Case 2: Floating table

    In this case, the best solution I found uses the adjustwidth environment from the changepage package.

    First, define a new environment that encloses its content in an adjustwidth environment to remove the left margin.

    \newenvironment{widestuff}{\begin{adjustwidth}{-4.5cm}{-4.5cm}\centering}{\end{adjustwidth}}
    

    Second, pass this new environment as latex.environments to print.xtable. (If there was a way to pass arguments to the environment in latex.environments, the custom environment would not be necessary at all.)

    \documentclass{article}
    \usepackage{changepage}
    \newenvironment{widestuff}{\begin{adjustwidth}{-4.5cm}{-4.5cm}\centering}{\end{adjustwidth}}
    \begin{document}
    <<echo = F, results = "asis">>=
    library(xtable)
    print(xtable(t(cars)[, 1:16]), latex.environments = "widestuff")
    
    print(xtable(t(cars)[, 1:12]), latex.environments = "widestuff")
    @
    \end{document}
    

    Output case 2

    (The screenshots contain some text that is not present in the code example. It is only there to visualize the page dimensions.)