Search code examples
rbookdownqwraps2

Percent symbol in qwraps2 summary table not rendering properly in bookdown


I am struggling to get a qwraps2 summary table to render properly in a markdown file knitting to a pdf document using bookdown. The issue arises when using the percent sign in the row names.

Sample markdown document:

---
title: "Untitled"
author: "TEST"
output:
  pdf_document: default
  bookdown::pdf_document2: null
---

```{r results = 'asis'}
library(qwraps2)
library(knitr)
library(kableExtra)

# Create som sample data
set.seed(2)
df <- data.frame(
  group = as.factor(sample(c("A","B"),8, replace = T)),
  value = sample(2:10,8, replace=F),
  pos = as.factor(sample(c("pos.","neg."),8, replace = T))
)

# Define the table for summary_table
summary <- list(
  "Groups" = list(
    "Value" = ~ median_iqr(value),
    "Pos. (\\\\%)" = ~ qwraps2::n_perc(pos == "pos."))
)

new_table <- summary_table(df, summaries = summary, by = "group")

new_table

I am aware that the percent sign needs to be escaped with backslash, but with two backslashes the rendering fails. With four the table is not rendered correctly. See below.

PDF Output with four \

How do I add a percent sign to the qwraps2 summary table row?


Solution

  • This looks like a bug in R triggered by bad code in qwraps2.

    The qwraps2 package converts the summaries argument to a character string and then parses it, purely for the purpose of giving a warning about using data in summaries. This doesn't make sense: summaries is already a list, so it shouldn't need parsing. That code should be fixed.

    However, the bug in R is that the conversion to a character string is done incorrectly when you have "Pos. (\\%)" = ~ qwraps2::n_perc(pos == "pos."), and that's why you get the error.

    The easiest fix I can think of is to remove that warning from the qwraps2:::summary_table.data.frame function. If you insert this code into your document, you'll do that:

    summary_table.data.frame <- qwraps2:::summary_table.data.frame
    body(summary_table.data.frame)[[2]] <- NULL
    

    After that change, you can use

    summary <- list(
      "Groups" = list(
        "Value" = ~ median_iqr(value),
        "Pos. (\\%)" = ~ qwraps2::n_perc(pos == "pos."))
    )
    

    and things will be fine: enter image description here

    However, this fix is not very robust: if the author of qwraps2 changes that function, this could fail badly. So your workaround of editing the result of the summary_table call is probably safer.