I'm creating a R Markdown document using knitr
and am running into trouble using xtable
to create a table. My table is very large and I'm trying to reduce the size using the size
command in the print
statement. The issue I'm running into is that the command seems to add two extra curly braces which show up in the PDF, one before the table and one after.
Does anyone know a way to fix this?
MWE:
---
output:
pdf_document:
keep_tex: yes
tables: true
---
```{r, results='asis', echo=FALSE}
library(xtable)
my.df <- data.frame(matrix(c(1:18),nrow=2))
glossaryprint <- xtable(my.df, caption="Summary of Terms")
print(glossaryprint,
comment=FALSE,
floating=FALSE,
size="footnotesize"
)
```
Note: The issue that is subject of the question and this answer has been resolved in xtable
1.8-2.
Although the question has been self-answered with a workaround, I think for other users some more details might be helpful.
What happens?
To understand what is happening here, we need to take a close look at the conversion steps the document undergoes on its way from RMD to PDF. The steps are:
RMD --> MD --> TEX --> PDF
Let's look at the files in reversed order:
PDF
: (generated from TEX
by pdflatex
)
TEX
: (generated from MD
by pandoc
)
% …
\{\footnotesize
\begin{tabular}{rrrr}
\hline
& X1 & X2 & X3 \\
\hline
1 & 1 & 3 & 5 \\
2 & 2 & 4 & 6 \\
\hline
\end{tabular}
\}
% …
MD
(generated from RMD
by knitr
)
---
output:
pdf_document:
keep_tex: yes
---
{\footnotesize
\begin{tabular}{rrrr}
\hline
& X1 & X2 & X3 \\
\hline
1 & 1 & 3 & 5 \\
2 & 2 & 4 & 6 \\
\hline
\end{tabular}
}
RMD
: (source file)
---
output:
pdf_document:
keep_tex: yes
---
```{r, results='asis', echo=FALSE}
library(xtable)
mytable <- xtable(data.frame(matrix(c(1:6), nrow = 2)))
print(mytable,
comment = FALSE,
floating = FALSE,
size = "footnotesize"
)
```
Recall: The problem is, that there are visible curly braces in the PDF
. Where do they come from?
- They are the result of the escaped curly braces in the
TEX
file (\{
and \}
).
- These curly braces also exist in the
MD
file, but there they are not escaped.
So we know two things by now: We see the curly braces because they are escaped and they are escaped by pandoc
.
But why do these curly braces exist at all? print.xtable
outputs them when a size
is specified. The goal is to create a group and to apply size
only within that group. (With floating = TRUE
, no grouping by curly braces is required because there is a figure
environment whithin which the size
is set. The curly braces are printed anyways.)
And why does pandoc
escape that pair of curly braces but leaves all the other curly braces (e.g. in \begin{tabular}
) unescaped? This is because pandoc
is supposed to escape special characters that are meant literally but leave raw LaTeX unescaped. However, pandoc
does not know that the outer curly braces are LaTeX commands and not text.
(With floating = TRUE
the problem does not occur because the curly braces are within a figure
environment which is recognized as LaTeX.)
Solutions
After having understood the problem, what can we do about it? One solution has already been posted by the OP: Abstain from spefifying size
in print.xtable
and insert the footnotesize
command manually:
---
output:
pdf_document:
keep_tex: yes
---
```{r, results='asis', echo=FALSE}
library(xtable)
mytable <- xtable(data.frame(matrix(c(1:6), nrow = 2)))
cat("\\begin{footnotesize}")
print(mytable,
comment = FALSE,
floating = FALSE
)
cat("\\end{footnotesize}")
```
However, on the long run it would be nice if xtable
(current version: 1.8-0
) generated LaTeX code that survives the pandoc
conversion. This is quite simple: print.xtable
checks if size
is set and if so, inserts {
before the size specification and }
at the end of the table:
if (is.null(size) || !is.character(size)) {
BSIZE <- ""
ESIZE <- ""
}
else {
if (length(grep("^\\\\", size)) == 0) {
size <- paste("\\", size, sep = "")
}
BSIZE <- paste("{", size, "\n", sep = "")
ESIZE <- "}\n"
}
This small modification replaces {
with \begingroup
and }
with \endgroup
:
if (is.null(size) || !is.character(size)) {
BSIZE <- ""
ESIZE <- ""
}
else {
if (length(grep("^\\\\", size)) == 0) {
size <- paste("\\", size, sep = "")
}
BSIZE <- paste("\\begingroup", size, "\n", sep = "")
ESIZE <- "\\endgroup\n"
}
For LaTeX, this makes no difference, but as pandoc
recognizes \begingroup
(as oppsed to {
) it should solve the problem. I reported this as a bug in xtable
and hopefully the issue will be fixed in future versions.
I was able to fix this by not including the size parameter in the print statement but rather directly before and after the chunk.
\begin{footnotesize}
#chunk
\end{footnotesize}