Extra Curly Braces When Using Xtable and Knitr, After Specifiying Size

Extra curly braces when using xtable and knitr, after specifiying size

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)

PDF output

  • 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.

How to output to pdf using knitr/xtable when tex has square braces ( [ )?

The problem is that the end of each row in the table is a \\ which has an optional argument to specify how much space to leave before the next row, for example, \\[1in]. There's allowed to be white space between the \\ and the [, so in this case, it's trying to read the [2,5) as that argument.

A simple workaround would be to change the labels of the factor to include some non-printing blank character first, however, if you do so, by default, print.xtable will "sanitize" it so that it actually does print, so you'd need to turn that off by passing a new sanitize function; identity will do none of this fixing.

levels(x.freq$Var1) <- paste0("{}", levels(x.freq$Var1))
print(xtable(x.freq),include.rownames=FALSE, sanitize.text=identity)

Changing fontsize of a single line in rmarkdown without altering global fontsize

TL;DR

---
output: pdf_document
---

With a minimal example of the problem, many questions can be answered easily.

\begingroup\Large
\begin{equation*}
Y_{ij} = [\beta_0 + \beta_1 (\text{Dose}-300)] + [\varepsilon_{ij}]
\end{equation*}
\endgroup

And usually, this is fun. ;-)

Longer answer

As far as I know, the only sensible output format for this is LaTeX anyways. Therefore, let's start with improving the equation's TEX code:

*$Y_{ij}$* = [*$\beta_0$* + *$\beta_1$*(Dose-300)] + [*$\varepsilon_{ij}$*]

becomes

$Y_{ij} = [\beta_0 + \beta_1 (\text{Dose}-300)] + [\varepsilon_{ij}]$

No need for the asterisks; math is typeset in italics anyways. No need to use separate $...$ for each expression. Wrap Dose in \text to use upright font.

Next step: Increase the size. Basically, this is accomplished using \Large, but we need to tell LaTeX to enlarge the equation only. Usually, this can be done using curly braces like this: {\Large ... }. However, pandoc escapes {, so we need an alternative (see here for a related problem and some explanations):

\begingroup\Large $Y_{ij} = [\beta_0 + \beta_1 (\text{Dose}-300)] + [\varepsilon_{ij}]$\endgroup

Or simply (but less elegant because dependent on the original font size):

\Large $Y_{ij} = [\beta_0 + \beta_1 (\text{Dose}-300)] + [\varepsilon_{ij}]$
\normalsize

We're basically done, but I suggest using display mode:

\begingroup\Large
\begin{equation*}
Y_{ij} = [\beta_0 + \beta_1 (\text{Dose}-300)] + [\varepsilon_{ij}]
\end{equation*}
\endgroup

As above, alternatively \normalsize could be used instead of the groupings.

print.xtable with multi-line header?

(Writing my comment up into a proper answer)

In the call to xtable, you can specify various alignment arguments, one of which is a parbox of a fixed width in which text will be wrapped. That is specified with p{1in} where the value specified within the braces is how wide the box (column) will be. You have to manually specify this (rather than have it adapt to the available space), but it does give you one option for wrapping text.

Using same onClick listener with more than one view

I think what you are referring to when you say "get the name" is the id string from resources. So you would have a switch statement like:

switch(view.getId()) {
case R.id.HomeButtonOne:
// Do Button One Action
break;
case R.id.HomeButtonTwo:
// Do Button Two Action
break;
}

otherwise please elaborate more on what you are trying to achieve.



Related Topics



Leave a reply



Submit