Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
331 views
in Technique[技术] by (71.8m points)

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

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"
)

```
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
    
    egin{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
    egin{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 egin{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, "
", sep = "")
  ESIZE <- "}
"
}

This small modification replaces { with egingroup 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, "
", sep = "")
  ESIZE <- "\endgroup
"
}

For LaTeX, this makes no difference, but as pandoc recognizes egingroup (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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...