3

I am running in an odd result. I have inserted a number of tables in my document in Rmarkdown. This is the YAML:

---
output:
  pdf_document:
    toc: true
    toc_depth: 2
    number_sections: true
header-includes:
 \usepackage{float}
 \floatplacement{figure}{H}
 \floatplacement{table}{H}
---

And the first chunk:

{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE,
                      fig.pos = "H",
                      fig.width=8,
                      fig.height=7,
                      tab.pos = "H",
                      collapse = TRUE,
                      message = FALSE,
                      warning = FALSE,
                      comment = "#>"
)

knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())

options(knitr.kable.NA = "-")

The tables are inserted in this manner:

kable(tableX, caption = "Caption", booktabs = TRUE) %>% 
  row_spec(0, bold=TRUE) %>% 
  kable_styling(bootstrap_options = "condensed") %>% 
  column_spec(1, italic = TRUE)

Now, most tables are inserted correctly, but there is just one which is printed with the latex code, \begin{table}, then \caption{}, then the table, and at the end \end{table}. How is it possible that one table is being printed in this manner with the code being the same?

Thank you

Daniel Estévez
  • 113
  • 1
  • 11
  • It's hard to reproduce the issue without the full code, but I'm suspecting knitr got confused on some latex bits. For further insights, you can add the keep_tex option to inspect the latex that is being generated. Likely, you'll find a `\textbackslash{}begin` there, which results in latex code being shown in pdf output. – All Downhill From Here Sep 20 '21 at 13:52
  • I thought I have included all required code there. The only thing lacking is the header of the chunk and I am only including the option echo=FALSE. But thank you, if I can solve it from there I will accept the answer. – Daniel Estévez Sep 20 '21 at 15:47
  • No, nothing new nor solved. – Daniel Estévez Sep 20 '21 at 15:50
  • I'm afraid I can't reproduce your error. What is different about the table that generates the error (or the chunk header, e.g. the caption). Can you create a minimal example (including packages loaded, please) that reproduces the issue? – All Downhill From Here Sep 20 '21 at 16:32
  • I can reproduce *some* error when I put a special character (e.g. %) in the caption. Knitr will effetively 'get confused' about the latex code and just prints it as escaped pre-formatted latex code. – All Downhill From Here Sep 20 '21 at 16:38
  • Oh ok. A caption from one valid table: "Sampling effort. SZ: sample size; Mu: number of fish weighted; Otoliths: number of otoliths collected; Stomachs: number of stomachs collected; Me: Median length (cm); Mn: Mean length (cm); Min: minimum length (cm); Max: maximum length (cm); MeanW: mean weight (kg)." From the one that is giving problems: "Catch of all species. C(kg): total catch in kg; C(no): total catch in numbers; CPUE: fishing effort in kg of fish catced in 6 hours; NPUE: fishing effort in number of fish catched in 6 hours; % Catch: percentage of the total catch." – Daniel Estévez Sep 21 '21 at 11:17
  • Ok, that was it. I will have to find a way to escape the character or similar. Many thanks – Daniel Estévez Sep 21 '21 at 11:19

2 Answers2

4

R markdown will produce latex code when the output option is set to pdf_document (the latex code can be viewed by selecting the option keep_tex and inspecting the produced .tex file) or when the output is set to latex_fragment.

knitr::kable output the full latex output for a table (when in tex mode), but consumes any caption provided literally. The knitr interpreter then consumes the produced latex block. When somewhere in between the \begin and \end environment statement something illegal is produced (such as a caption with an unescaped % in there), the interpreter instead produces escaped latex code.

The valid code

```{r tab1, echo=F}
tableX=data.frame(col1 = "Empty data frame")
kable(tableX, caption = "Caption 20pct", booktabs = TRUE) |> 
  row_spec(0, bold=TRUE) |>
  kable_styling(bootstrap_options = "condensed") %>% 
  column_spec(1, italic = TRUE)
```

produces latex code as expected:

\begin{table}

\caption{\label{tab:tab1}Caption 20pct}
\centering
\begin{tabular}[t]{>{}l}
\toprule
\textbf{col1}\\
\midrule
\em{Empty data frame}\\
\bottomrule
\end{tabular}
\end{table}

But when a % is added to the caption, the latex code generation breaks. The code block

```{r tab1, echo=F}
tableX=data.frame(col1 = "Empty data frame")
kable(tableX, caption = "Caption 20%", booktabs = TRUE) |> 
  row_spec(0, bold=TRUE) |>
  kable_styling(bootstrap_options = "condensed") %>% 
  column_spec(1, italic = TRUE)
```

produces

\textbackslash begin\{table\}

\textbackslash caption\{\label{tab:tab1}Caption 20\%\} \centering

\begin{tabular}[t]{>{}l}
\toprule
\textbf{col1}\\
\midrule
\em{Empty data frame}\\
\bottomrule
\end{tabular}

\textbackslash end\{table\}

which just renders in the pdf as literal latex code.

4

As the author of rmarkdown Yihui Xie noted here, you can disable the character-escaping argument in kable() to include LaTeX's spacial characters in the table caption, or column/row names, or both. Then you need to manually escape such characters by adding \\ before each special character.

```{r tab1, echo=F}
tableX=data.frame(col1 = "Empty data frame")
kable(
  tableX,
  caption  = "Caption 20\\%",
  booktabs = TRUE,
  escape   = FALSE
  ) |> 
  row_spec(0, bold=TRUE) |>
  kable_styling(bootstrap_options = "condensed") %>% 
  column_spec(1, italic = TRUE)
```
Carlos Luis Rivera
  • 3,108
  • 18
  • 45