Hard to come up with a handy short title for this question, sorry.
I'm working on a PDF report using RMarkdown, and have need to conditionally format one of my tables. I've managed to get this to work just fine with HTML conditional formatting, but I am running into problems with conditional formatting for PDF export.
The goal is to conditionally format the background of a cell if the value in the cell is 0
, and leave the background blank if the value is not. The custom colours in the MWE below are from my preamble.tex
, so that's not the problem I'm running into.
MWE chunks are below, with both sample data and the kable arguments.
``` {r packages, message = FALSE, echo = FALSE}
## Load required packages
library(tidyverse)
library(kableExtra)
```
``` {r mwe-data}
## Create MWE Data Example
mwe_data <- tibble(
proj_na = rep(paste("PROJECT", 1:10), 5),
proj_yr = rep(2020:2024, each = 10),
proj_st = sample(rep(c(0, 1), each = 10), 50, replace = TRUE)
)
## Kable Output
mwe_data %>%
mutate(
proj_st = cell_spec(
proj_st,
format = "latex",
bold = TRUE,
background = case_when(
proj_st == 0 ~ "mpsred!50",
TRUE ~ "mpswine!0"
)
)
) %>%
pivot_wider(
names_from = proj_yr,
values_from = proj_st
) %>%
kable(
format = "latex",
booktabs = TRUE,
align = "lccccc",
) %>%
kable_styling(latex_options = c("HOLD_position", "repeat_header")) %>%
row_spec(row = 0, color = "mpswine", align = "c")
```
When I knit the document with the above code chunks, I get a PDF output that looks like the following:
Obviously, this is not what I want. That said, it is correctly adding \cellcolor{mpsred!50}
and \cellcolor{mpswine!0}
to the correct cells, so that's good. After some googling and searching around stack overflow, I found that I should add the escape=FALSE
argument to my kable()
.
I added the escape=FALSE
argument to kable()
and tried to knit the document. Unfortunately, the document won't knit with escape=FALSE
. I get the following error in the console:
! Missing $ inserted. $ l.113 ...icolumn{1}{c}{\textcolor{mpswine}{proj_na}} & \multicolumn{1}{c}> {\tex...
Try to find the following text in testing.Rmd: ...icolumn{1}{c}{\textcolor{mpswine}{proj_na}}
You may need to add $ $ around a certain inline R expression
r
in testing.Rmd (see the above hint). See https://github.com/rstudio/rmarkdown/issues/385 for more info. Error: LaTeX failed to compile testing.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips. See testing.log for more info. Execution halted
The .log
file shows the same error, but it did keep the .tex
file it tried to generate. The table from the .tex
file looks like this:
\begin{table}[H]
\centering
\begin{tabular}{lccccc}
\toprule
\multicolumn{1}{c}{\textcolor{mpswine}{proj_na}} & \multicolumn{1}{c}{\textcolor{mpswine}{2020}} & \multicolumn{1}{c}{\textcolor{mpswine}{2021}} & \multicolumn{1}{c}{\textcolor{mpswine}{2022}} & \multicolumn{1}{c}{\textcolor{mpswine}{2023}} & \multicolumn{1}{c}{\textcolor{mpswine}{2024}}\\
\midrule
PROJECT 1 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 2 & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 3 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}}\\
PROJECT 4 & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}}\\
PROJECT 5 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}}\\
\addlinespace
PROJECT 6 & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 7 & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 8 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 9 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}}\\
PROJECT 10 & \cellcolor{mpswine!0}{\textbf{1}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpsred!50}{\textbf{0}} & \cellcolor{mpswine!0}{\textbf{1}}\\
\bottomrule
\end{tabular}
\end{table}
The table looks mostly correctly formatted for latex, though I'm assuming the &
is what's breaking the knitting at this point.
I thought maybe escape=FALSE
might belong in the cell_spec()
call, but that doesn't work either. I get the document to knit, but I get the same output as in the screenshot above.
I did some digging, and the new documentation on kableExtra
says to use column_spec()
for conditional formatting, rather than cell_spec()
, so I tried the following code:
``` {r mwe-test2}
mwe_data1 <- mwe_data %>%
pivot_wider(
names_from = proj_yr,
values_from = proj_st
)
mwe_data1 %>%
kable(
format = "latex",
booktabs = TRUE,
align = "lccccc",
) %>%
kable_styling(latex_options = c("HOLD_position", "repeat_header")) %>%
row_spec(row = 0, color = "mpswine", align = "c") %>%
column_spec(
column = 2:6,
bold = TRUE,
background = case_when(
mwe_data1$`2020` == 0 ~ "mpsred!50",
mwe_data1$`2021` == 0 ~ "mpsred!50",
mwe_data1$`2022` == 0 ~ "mpsred!50",
mwe_data1$`2023` == 0 ~ "mpsred!50",
mwe_data1$`2024` == 0 ~ "mpsred!50",
TRUE ~ "mpswine!0"
)
)
```
This knit just fine, but the output is not conditionally formatted as expected:
I feel like I'm missing something fairly obvious here, but my google-fu and searching through stack overflow haven't yielded anything terribly useful for this purpose. Most of what I'm seeing is just "add escape=FALSE
and all will be well," except that isn't working. What am I missing?
Looking at the error
Missing $ inserted. $ l.95 ...column{1}{c}{\textcolor{mpswine}{proj_na}} & \multicolumn{1}{c}{\tex... I've inserted a begin-math/end-math symbol since I think you left one out. Proceed, with fingers crossed.
Try to find the following text in bgCells.Rmd: ...column{1}{c}{\textcolor{mpswine}{proj_na}}
You may need to add $ $ around a certain inline R expression
r
in bgCells.Rmd (see the above hint). See https://github.com/rstudio/rmarkdown/issues/385 for more info. Fehler: LaTeX failed to compile bgCells.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips. See bgCells.log for more info.
you can see that LaTeX has a problem with column proj_na
because it has an underscore which is interpreted as math mode subscripts. So it specifically fails, trying to apply your textcolor mpswine
from the code piece row_spec(row = 0, color = "mpswine", align = "c")
.
To prevent this, simply add rename("Project Name" = proj_na)
to remove the underscore from the problematic column.
Note: I tried to recreate your custom colors, since you did not specify them using header-includes
and this, although it's not necessary to recreate the issue and might detract.
---
title: "Untitled"
output:
pdf_document: default
header-includes:
- \definecolor{mpswine}{RGB}{106, 107, 143}
- \definecolor{mpswine!0}{RGB}{255, 255, 255}
- \definecolor{mpsred!50}{RGB}{223, 153, 147}
---
```{r table, echo = FALSE, warning = FALSE, message = FALSE}
library(kableExtra)
library(tidyverse)
set.seed(123) # For reproducibility
tibble(
proj_na = rep(paste("PROJECT", 1:10), 5), # or remove underscore here
proj_yr = rep(2020:2024, each = 10),
proj_st = sample(rep(c(0, 1), each = 10), 50, replace = TRUE)
) %>%
mutate(
proj_st = cell_spec(
proj_st,
format = "latex",
bold = TRUE,
background = case_when(
proj_st == 0 ~ "mpsred!50",
TRUE ~ "mpswine!0"
)
)
) %>%
pivot_wider(
names_from = proj_yr,
values_from = proj_st
) %>%
rename("Project Name" = proj_na) %>%
kable(
format = "latex",
booktabs = TRUE,
align = "lccccc",
escape = FALSE
) %>%
kable_styling(latex_options = c("HOLD_position", "repeat_header")) %>%
row_spec(row = 0, color = "mpswine", align = "c")
```
and it works: