Search code examples
rlatexknitrpdflatexxtable

R: diagonal columnnames in xtable


R-3.1.1, Win7 x64, knitr version 1.6, xtable version 1.7-3

I am trying to build a table with angled column names, following the ideas from the discussion here. My workflow builds on knitr/Latex, to automate my reporting, so I want to incorporate the ideas in xtable. My code is as follows:

\documentclass[a4paper,11pt]{article}

\usepackage{graphicx}
\usepackage[T1]{fontenc}
\usepackage{tabularx}
\usepackage{longtable}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand{\rothead}[2][60]{\makebox[9mm][c]{\rotatebox{#1}{\makecell[c]{#2}}}}%


\begin{document}

<<global_opts, echo=FALSE>>=
opts_chunk$set(fig.keep='none', results='hide', echo=FALSE)
@

<<tab01>>=
require(xtable, quietly = TRUE)
test <- matrix(95:110, ncol = 4) 
rownames(test) <- paste0("row ", 1:4)
colnames(test) <- paste0("\\multicolumn{2}{c}{\\rotatebox{60}{column ", 1:4, "}}")
tab10 <- xtable(test)
tab10 <- print(tab10, sanitize.colnames.function = function(x){x})
@

{\Sexpr{tab10}}
\end{document}

This kinda gets the job done, but not as nicely as I was hoping for. The output looks like:

enter image description here

Of course, I want the column names NEXT to each other, rather than on top of one another. In addition, I get the following warning:

knit2pdf("diagonal_headers.Rnw")

Warning message:
running command '"C:\PROGRA~1\MIKTEX~1.9\miktex\bin\x64\texi2dvi.exe" --quiet --pdf     "tab_tests_diagonaal.tex" --max-iterations=20 -I "C:/PROGRA~1/R/R-31~1.1/share/texmf/tex/latex" -I "C:/PROGRA~1/R/R-31~1.1/share/texmf/bibtex/bst"' had status 1 

Overall, I am getting close. What can I do to get the table layout fixed?


Solution

  • Here is one way to get it done. The preamble is unaltered, so I only show the code chunk here.

    The barebones version of the code is:

    <<tab01_barebones>>=
    require(xtable, quietly = TRUE)
    test <- matrix(95:110, ncol = 4)
    rownames(test) <- paste0("row ", 1:4)
    cols <- paste0("\\rothead{column ", 1:4, "}", collapse = " & ")
    cols <- paste0("\\rothead{} & ", cols, "\\\\")
    tab10 <- xtable(test)
    tab10 <- print(tab10, include.colnames = FALSE, add.to.row = list(pos = as.list(0), command = cols), sanitize.colnames.function = function(x) {x}, booktabs = FALSE, hline.after = NULL)
    @
    

    which yields:

    enter image description here

    There were a couple of issues with your code. You actually need code for the cell above the row names as well, which is basically an empty version of the other cells in the header column: \\multicolumn{1}{c}{\\rothead{}}. Also, \\multicolumn{2} had to be \\multicolumn{1}, since you are not actually merging cells. In fact, you can do away with \\multicolumn{1} altogether and just keep \\rothead.

    You will see that the layout becomes a bit clumsy, b/c of the angled headers. Here is one way to make it a bit prettier:

    <<tab01>>=
    require(xtable, quietly = TRUE)
    test <- matrix(95:110, ncol = 4)
    rownames(test) <- paste0("row ", 1:4)
    cols <- paste0("\\multicolumn{1}{c}{\\rothead{column ", 1:4, "}}", collapse = " & ")
    cols <- paste0("\\multicolumn{1}{c}{\\rothead{}} & ", cols, "\\\\")
    tab10 <- xtable(test)
    align(tab10) <- "r|cccc|"
    tab10 <- print(tab10, include.colnames = FALSE, add.to.row = list(pos = as.list(c(0,0,4)),     command = c(cols, "\\cline{2-5}","\\cline{2-5}")), 
               sanitize.colnames.function = function(x) {x}, booktabs = FALSE, hline.after = NULL)
    @
    

    I reinstated \\multicolumn{1} here so the vertical lines would not extend to the header cells (b/c that is ugly, with these angled headers). I also added cline, to produce partial horizontal lines. The resulting table is:

    enter image description here

    Perhaps it is nicer to use align(tab10) <- "r|llll|" instead, although I am not a big fan of left aligned numbers:

    enter image description here

    HTH, Peter