3

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?

Community
  • 1
  • 1
  • One easy thing you could do is adding `align = c("rrrr|lr")` to your `xtable` call. I think the only way to achieve your original goal is to manually use a subfigure. This should not be too difficult, but inolves some manual writing of LaTeX instead of just letting knitr and xtable do the work for you. However, I don't think that there is an alternative as knitr is able to create subfigures, but as to my knowledge only with graphs. – CL. Jul 06 '15 at 14:58

1 Answers1

3
\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}
Community
  • 1
  • 1
CL.
  • 14,577
  • 5
  • 46
  • 73
  • Thank you, @user2706569, but this solution does not take into account the page break! If I increase the number of rows, it will just run off the page. –  Jul 06 '15 at 16:17
  • Yes. I see two possible solutions. A: Find a solution that does not use subfigures, then you can easily use `longtable` (my comment on your question may help). B: Find a way to include a `longtable` into subfigures. This is a pure LaTeX problem. (C: Split the table manually) – CL. Jul 06 '15 at 16:32
  • Also thank you for your suggestion regarding using the align call in xtable. Yes, that does add the vertical line I desired. I would rather have a vertical space than the vertical line, so I will see if anyone has ideas for that for a little bit. Otherwise, I will keep the line! –  Jul 06 '15 at 16:33
  • Thanks again. Can you explain a bit more what you mean by the third option... splitting the table manually? I just want to make sure I understand what that means so I can research it! –  Jul 06 '15 at 16:36
  • What I mean is something like `print(xtable(df1[1:10,])); print(xtable(df1[11:20,]))` if you know that you will need a page break after the first 10 rows. But be careful - your document may change and so will the available space. Therefore, I do not consider this a good solution. Alternatively: Use one table with `only.contents = TRUE, include.colnames = FALSE, hline.after = NULL` and build the "header" on your own. – CL. Jul 06 '15 at 17:00
  • I included the idea from the last comment into my answer. – CL. Jul 06 '15 at 17:22