possible to create latex multicolumns in xtable?

Eric Green picture Eric Green · Dec 21, 2012 · Viewed 14.1k times · Source

I am using xtable with R Markdown and knitr to produce .tex files that I call with \input{}. Works great, but I have not figured out how to create multicolumns like the one shown here. Does anyone know how to to this?

So far I am using:

tbl <- xtable(data, align="l r r r r r")
colnames(tbl) <- c("Variable", 
                  "Mean", "Std Dev", 
                  "Mean", "Std Dev", 
                  "Difference")
caption(tbl) <- c("Table Title")
print(tbl, 
    include.rownames=FALSE,
    caption.placement="top",
    booktabs=TRUE,
    type="latex", 
    file="output.tex")

I'd like to have a different grouping header over each "Mean" and "Std Dev" ("Treatment" and "Control").

Alternatively, is there a better method for using R Markdown/knitr to automatically generate tables? I don't want to manually edit the tables because the report needs to generate automatically.

UPDATE: @agstudy: I'm new to latex, but I think this is the output I am looking to produce automatically with xtable (or something like xtable):

\begin{tabular}{lrrrrr}
  \toprule
      & \multicolumn{2}{c}{Treatment} & \multicolumn{2}{c}{Control} & \\
  \cmidrule(lr){2-3} \cmidrule(lr){4-5}
  Variable & Mean & Std Dev & Mean & Std Dev & Difference \\ 
  \midrule
  var1 & 1 & 2 & 3 & 4 & 5 \\ 
  \bottomrule
\end{tabular}

UPDATE 2: @Jonathan: it took me a few reads to understand what you were suggesting. I took your recommendation, and it worked.

In the R markdown chunk I now use:

tbl <- xtable(data)
print(tbl,
    only.contents=TRUE,
    include.rownames=FALSE,
    type="latex",
    digits(tbl) <- c(0,1,1,1,1,1),
    file="output/tblout.tex")

Then in the text, I use:

\begin{tabular}{lddddd}
\toprule
    & \multicolumn{2}{c}{Treatment} & \multicolumn{2}{c}{Control} & \\
    \cmidrule(lr){2-3} \cmidrule(lr){4-5}
    Variable  &  \multicolumn{1}{r}{Mean}  &  \multicolumn{1}{r}{Std Dev}  &       \multicolumn{1}{r}{Mean}  &  \multicolumn{1}{r}{Std Dev}  &  \multicolumn{1}{r}{Difference}  \\
\midrule
\input{../output/tblout}
\bottomrule
\end{tabular}

I'll see if anyone has any other suggestions for a native xtable (or other package) solution. Otherwise, I will accept your answer. Thanks!

Answer

AdamO picture AdamO · Feb 9, 2015

I think the add.to.row option in xtable achieves this perfectly.

Example code here:

require(xtable)
age <- sample(c('30-50', '50-70', '70+'), 200, replace=T)
sex <- sample(c('Male', 'Female'), 200, replace=T)
val <- table(age, sex)
val <- rbind(val, formatC(prop.table(val)*100, format='f', digits=1))
val <- structure(val, dim=c(3, 4))
val <- rbind(c('n', '%'), val)
rownames(val) <- c('', sort(unique(age)))
val <- xtable(val)


addtorow <- list()
addtorow$pos <- list(0)
addtorow$command <- paste0(paste0('& \\multicolumn{2}{c}{', sort(unique(sex)), '}', collapse=''), '\\\\')

print(val, add.to.row=addtorow, include.colnames=F)