user2808302
user2808302

Reputation:

Xtable two columns using longtable customizations

This is a continuation of a question I posted earlier. I have a code.Rnw file in RStudio which I knit into a code.tex file using knit("code.Rnw") command.

I have a data frame that I am printing using the xtable command. In the example below, it is 20 rows. However, to save space, I am printing it out as two columns, each with 10 rows.

Below is my code:

\documentclass[11pt, a4paper]{article}
\usepackage[margin=3cm]{geometry}
\usepackage{longtable}

\begin{document}

<<echo=FALSE,results='asis'>>=
library(xtable)
set.seed(1)

spaceCol =  rep("     ",10)
df1 = data.frame(student = letters[1:10], vals=runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))
dfFull = data.frame(df1,spaceCol,df2)
names(dfFull) = c(" ","% Correct","     "," ", "% Correct")
row.names(dfFull) = NULL

x.big <- xtable(dfFull, label ='tabtwo',caption ='Caption for table with student scores')
print(x.big, tabular.environment ='longtable', floating = FALSE, include.rownames=FALSE)
@

\end{document}

This is what the output looks like:

Current output

I like the aesthetics of this output, especially because in the longtable format, this output will automatically page-break if need be. However, what I am trying to improve, is to make it more easy to visualize that this output is really two distinct columns.

To do that, I would like to add a space between the two columns, so the output looks more as follows:

Desired output

However, if that proves impossible, then I could consider something like adding a vertical line to distinguish the two columns, as shown below:

Alternative desired output

How might this be possible given my limitation in using xtable?

Upvotes: 3

Views: 2646

Answers (1)

CL.
CL.

Reputation: 14997

\documentclass[11pt, a4paper]{article}

\usepackage{subfig}

\begin{document}

<<echo = FALSE>>=
library(xtable)

opts_chunk$set(
  echo = FALSE,
  results = 'asis'
)

set.seed(1)

mynames <- c("", "% Correct")

df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))

colnames(df1) <- mynames
colnames(df2) <- mynames
@

\begin{table}\centering
\subfloat{
<<>>=
print(xtable(df1), floating = FALSE, include.rownames = FALSE)
@
} \hspace{2cm}
\subfloat{
<<>>=
print(xtable(df2), floating = FALSE, include.rownames = FALSE)
@
}
\caption{Caption for table with student scores} \label{tabtwo}
\end{table}
\end{document}

Result

The only drawback is, that you cannot use longtable with this approach.

UPDATE: Here is an alternative that makes use of longtable. The trick is to use xtable for the contents of the table only and build the headline by hand, so you have full control over all lines etc. I decided to use an empty column for the space because making column 2 wider would make the horizontal lines look ugly.

\documentclass{article}

\usepackage{longtable}

\begin{document}
\thispagestyle{empty}

<<echo = FALSE>>=
library(xtable)

opts_chunk$set(
  echo = FALSE,
  results = 'asis'
)

set.seed(1)

df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))

dfFull <- cbind(df1, NA, df2)
@

\begin{longtable}{lrl@{\hskip 2cm}lr} \cline{1-2} \cline{4-5}
 & \% Correct & & & \% Correct \\ \cline{1-2} \cline{4-5}
<<>>=
print(xtable(dfFull), only.contents = TRUE, include.rownames = FALSE, include.colnames = FALSE, hline.after = NULL)
@
\cline{1-2} \cline{4-5}
\caption{Caption for table with studen scores} \label{tabtwo}
\end{longtable}
\end{document}

Result

UPDATE2: Finally, a solution that uses longtable and doesn't involve creating half of the table "by hand". The trick is to remove all horizontal lines (hline.after = NULL) and than add \clines where required using add.to.row (inspired by this question).

\documentclass{article}

\usepackage{longtable}

\begin{document}
\thispagestyle{empty}

<<echo = FALSE, results = 'asis'>>=
library(xtable)

set.seed(1)


df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(letters[11:20], runif(10, 1, 10))

dfFull <- cbind(df1, NA, df2)

# To test "longtable", rbind data several times:
multiply <- 5
dfFull <- do.call("rbind", replicate(multiply, dfFull, simplify = FALSE))

colnames(dfFull) <- c("", "% Correct", "", "", "% Correct")

print(xtable(dfFull,
             caption = "Caption for table with student scores",
             label = "tabtwo",
             align = c("l",  # ignored (would apply to colnames)
                       "l", "r",
                       "l@{\\hskip 2cm}", # space between blocks
                       "l", "r")),
      include.rownames = FALSE,
      include.colnames = TRUE,
      hline.after = NULL, # Remove all default lines. A line after the very last row remains, which is automatically added when using "longtable".
      tabular.environment = "longtable",
      floating = FALSE,
      add.to.row = list(
        pos = list(-1, 0),
        command = rep("\\cline{1-2} \\cline{4-5}", 2))
      )
@
\end{document}

Upvotes: 3

Related Questions