r-markdownkableextramodelsummary

modelsummary wrapping notes in \num{} for kableExtra


When modelsummary produces a table for output type kableExtra, it wraps numbers in the notes in \num{} tags, which show up in my PDF output. I want to disable this behaviour, or know how to properly handle this, so that the \num{} tag doesn't show up in the output.

---
title: "My Document"
output: pdf_document
---

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

library(modelsummary)
library(kableExtra)
```

```{r table}
model <- lm(mpg ~ cyl, mtcars)

modelsummary(model,
             output = "kableExtra",
             escape = TRUE
             stars = c("*" = .1, "**" = .05, "***" = .001)) %>% 
  column_spec(1, width = "5cm")
```

Screenshot of the rendered table

In this example, I use the stars argument which automatically produces a legend below the table explaining the stars. When this document is rendered, the note reads * p \num{< 0.1}, ** p \num{< 0.05}, *** p \num{< 0.001}.

Theres a global option (discussed here) to disable wrapping numeric values, this however doesn't work in this case, as it only applies to values inside the table.

There's also the escape argument in modelsummary which is TRUE by default. Setting it to FALSEdid nothing for me.

Can this wrapping be disabled?

Possible workarounds:


Solution

  • I opened an issue on GitHub and the modelsummary author author answered me. TL;DR: This is a downstream bug in kableExtra that's unlikely to be fixed and you are probably better off with using tinytable in the long run.

    This is a workaround that worked for me:

    You can include a custom pandoc lua filter in the YAML header, to modify pandocs internal representation of the document during converting.

    The filter:

    local function fix_table_footer(text)
      return text:gsub("(\\multicolumn{%d+}{l}{\\rule{0pt}{1em})(.-)(}\\\\)", function(prefix, content, suffix)
        if content:find("textbackslash{}num") then
          io.stderr:write("Fixing table footer: " .. content .. "\n")
          return prefix .. "* p < 0.1, ** p < 0.05, *** p < 0.01" .. suffix
        else
          return prefix .. content .. suffix
        end
      end)
    end
    
    function RawBlock(el)
      if el.format:match("tex") or el.format:match("latex") then
        local modified = fix_table_footer(el.text)
        if modified ~= el.text then
          io.stderr:write("Modified RawBlock text.\n")
          el.text = modified
          return el
        end
      end
    end
    

    This matches my star specification as a whole exactly, but it should be easy to adjust this to your needs. You could check your .knit.md file, to find the problematic line to match.

    To use the filter, place the code in a .lua file (in your directory) and call this file in the YAML header of your rmarkdown document as an argument to pandoc.

    YAML header:

    ---
    output:
      pdf_document:
        pandoc_args: ["--lua-filter=filter.lua"]
    ---