rr-markdownpdflatexkableextra

KableExtra column width not working when knitting to PDF in R Markdown


I'm unable to adjust the column widths in column_spec() in my KableExtra table when knitting to PDF. I'm wondering if it has something to do with the cnames object which I apply to the col.names = argument. The error that returns is:

! Paragraph ended before \mcell@tabular was complete.
<to be read again> 
                   \par 
1.129 
Execution halted Error: LaTex failed to compile TestDoc.tex. 
See https://yihui.org/tinytex/r/#debugging for debugging tips. 
See TestDoc.log for more info.
Execution halted.

The reason I say this is adjusting the width for only column 1 works fine, and this column has no LaTeX code in the header. I really need to keep the cnames object as is due to needing to include the units of measurement spread over two lines in the header in my real data.

Some example code is below to replicate the error. Really hoping someone has a solution. Thanks!

---
title: >
  `\vspace{-1.8cm}`{=latex}
header-includes:
 - \usepackage{geometry}
 - \geometry{margin=0.2in}
 - \usepackage[default]{sourcesanspro}
 - \usepackage[T1]{fontenc}
 - \usepackage{makecell}
 - \usepackage{fancyhdr}
 - \pagestyle{fancy}
 - \usepackage[export]{adjustbox}
 - \fancyhf{}
 - \pagenumbering{gobble}
mainfont: SourceSansPro
output: pdf_document
editor_options:
  chunk_output_type: console
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  echo = FALSE,
  message = FALSE,
  warning = FALSE,
  dev = "cairo_pdf"
  )
```

```{r}
library(kableExtra)

set.seed(10)
df <- data.frame(
  activity = paste("Activity", 1:10),
  var1 = round(rnorm(10, 1000, 500)),
  var2 = round(rnorm(10, 1000, 500)),
  var3 = round(rnorm(10, 1000, 500))
)

cnames <- c(
  "Period",
  "\\makecell[ct]{Time\\\\(mins)}",
  "\\makecell[ct]{Volume\\\\(m)}",
  "\\makecell[ct]{Speed\\\\(s)}"
  )

kbl(df,
      booktabs = TRUE,
      escape = FALSE,
      col.names = cnames,
      align = c("l", rep("c", ncol(df) - 1)),
      linesep = "\\addlinespace") %>%
  kable_styling(latex_options = c("HOLD_position"),
                font_size = 8) %>%
  column_spec(column = 1, width = "2in") %>%
  column_spec(column = c(2:4), width = "1in")
```

Solution

  • It's a bit cumbersome but setting the cell width inside cnames apparently works. For some reason both the explicit \centering command inside the cell text and the align argument in kbl are needed to produce the desired alignment.

    cnames <- c(
      "\\makecell[{{p{2in}}}]{Period}",
      "\\makecell[{{p{1in}}}]{\\centering Time\\\\(mins)}",
      "\\makecell[{{p{1in}}}]{\\centering Volume\\\\(m)}",
      "\\makecell[{{p{1in}}}]{\\centering Speed\\\\(s)}"
      )
    
    kbl(df,
          booktabs = TRUE,
          escape = FALSE,
          col.names = cnames,
          align = c("l", rep("c", ncol(df) - 1)),
          linesep = "\\addlinespace") %>%
      kable_styling(latex_options = c("HOLD_position"),
                    font_size = 8)
    

    Resulting table: table

    Hope that works for you!


    My specs:

    > packageVersion("kableExtra")
    [1] ‘1.3.4’
    > packageVersion("knitr")
    [1] ‘1.45’
    > sessionInfo()
    R version 4.3.2 (2023-10-31)
    Platform: x86_64-pc-linux-gnu (64-bit)
    Running under: Ubuntu 22.04.3 LTS