Disabling processing for tables when using knitr::kable() in R

TL;DR

In some specific cases where you don’t get the output you expect from specific features on tables (for example, when producing tables with a R function), you may be required to opt-out Quarto Tables processing by adding a specific attribute on the table (Docs)

This example shows how to do that when using knitr::kable() ecosystem.

About Tables Processing with Quarto

Quarto has specific features for tables : https://quarto.org/docs/authoring/tables.html. It was designed to handle Tables natively for good outputs in all formats. For that, Quarto will do a specific processing for Markdown tables, but also for HTML tables that will be parsed the same way as Markdown tables.

If this has a lot of advantages to offer some special features to tables, it will also have some side effects on tables produced by other tools. That is why Quarto offers an opt-out mechanism to disable Quarto processing using a specific attributes on tables

<table data-quarto-disable-processing="true">
  ...
</table>

Tables Produced with R Code

Tables can also be produced using R packages as several R packages exist to produce HTML tables. These packages often introduced some specific features for tables, which Quarto could ignore and even overwrite.

Let’s take the example of kableExtra R package (https://haozhu233.github.io/kableExtra/). This package extends knitr and will produce HTML tables. Among the feature kable_styling() helps to set some style.

Let’s see what Quarto does with the output.

We load the package

library(kableExtra)

And produce a table using the following code

```{r}
#| label: tbl-res1
#| tbl-cap: "mtcars with full_width = FALSE doesn't work."
kable(mtcars[,1:3]) |>
  kable_styling(full_width = FALSE)
```
Table 1: mtcars with full_width = FALSE doesn’t work.
mpg cyl disp
Mazda RX4 21.0 6 160.0
Mazda RX4 Wag 21.0 6 160.0
Datsun 710 22.8 4 108.0
Hornet 4 Drive 21.4 6 258.0
Hornet Sportabout 18.7 8 360.0
Valiant 18.1 6 225.0
Duster 360 14.3 8 360.0
Merc 240D 24.4 4 146.7
Merc 230 22.8 4 140.8
Merc 280 19.2 6 167.6
Merc 280C 17.8 6 167.6
Merc 450SE 16.4 8 275.8
Merc 450SL 17.3 8 275.8
Merc 450SLC 15.2 8 275.8
Cadillac Fleetwood 10.4 8 472.0
Lincoln Continental 10.4 8 460.0
Chrysler Imperial 14.7 8 440.0
Fiat 128 32.4 4 78.7
Honda Civic 30.4 4 75.7
Toyota Corolla 33.9 4 71.1
Toyota Corona 21.5 4 120.1
Dodge Challenger 15.5 8 318.0
AMC Javelin 15.2 8 304.0
Camaro Z28 13.3 8 350.0
Pontiac Firebird 19.2 8 400.0
Fiat X1-9 27.3 4 79.0
Porsche 914-2 26.0 4 120.3
Lotus Europa 30.4 4 95.1
Ford Pantera L 15.8 8 351.0
Ferrari Dino 19.7 6 145.0
Maserati Bora 15.0 8 301.0
Volvo 142E 21.4 4 121.0

As we can full_width = FALSE does not apply. Quarto table processing needs to be opt-out. This can be done easily because knitr::kable() has a specific way to set arbitrary attributes on a table:

```{r}
#| label: tbl-res2
#| tbl-cap: "mtcars with full_width = FALSE"
kable(mtcars[,1:3], table.attr = "quarto-disable-processing=true") |>
  kable_styling(full_width = FALSE)
```
Table 2:

mtcars with full_width = FALSE

mpg cyl disp
Mazda RX4 21.0 6 160.0
Mazda RX4 Wag 21.0 6 160.0
Datsun 710 22.8 4 108.0
Hornet 4 Drive 21.4 6 258.0
Hornet Sportabout 18.7 8 360.0
Valiant 18.1 6 225.0
Duster 360 14.3 8 360.0
Merc 240D 24.4 4 146.7
Merc 230 22.8 4 140.8
Merc 280 19.2 6 167.6
Merc 280C 17.8 6 167.6
Merc 450SE 16.4 8 275.8
Merc 450SL 17.3 8 275.8
Merc 450SLC 15.2 8 275.8
Cadillac Fleetwood 10.4 8 472.0
Lincoln Continental 10.4 8 460.0
Chrysler Imperial 14.7 8 440.0
Fiat 128 32.4 4 78.7
Honda Civic 30.4 4 75.7
Toyota Corolla 33.9 4 71.1
Toyota Corona 21.5 4 120.1
Dodge Challenger 15.5 8 318.0
AMC Javelin 15.2 8 304.0
Camaro Z28 13.3 8 350.0
Pontiac Firebird 19.2 8 400.0
Fiat X1-9 27.3 4 79.0
Porsche 914-2 26.0 4 120.3
Lotus Europa 30.4 4 95.1
Ford Pantera L 15.8 8 351.0
Ferrari Dino 19.7 6 145.0
Maserati Bora 15.0 8 301.0
Volvo 142E 21.4 4 121.0

Deactivating the processing for this tables allows the full_width = FALSE to work. However, the default formatting applied by Quarto is lost. It would be required to add it back using specific feature from the R functions used. With kableExtra we can do that:

```{r}
#| label: tbl-res3
#| tbl-cap: "mtcars with full_width = FALSE and some styles applied."
kable(mtcars[,1:3], table.attr = "quarto-disable-processing=true") |>
  kable_styling(c("striped", "bordered"), full_width = FALSE)
```
Table 3:

mtcars with full_width = FALSE and some styles applied.

mpg cyl disp
Mazda RX4 21.0 6 160.0
Mazda RX4 Wag 21.0 6 160.0
Datsun 710 22.8 4 108.0
Hornet 4 Drive 21.4 6 258.0
Hornet Sportabout 18.7 8 360.0
Valiant 18.1 6 225.0
Duster 360 14.3 8 360.0
Merc 240D 24.4 4 146.7
Merc 230 22.8 4 140.8
Merc 280 19.2 6 167.6
Merc 280C 17.8 6 167.6
Merc 450SE 16.4 8 275.8
Merc 450SL 17.3 8 275.8
Merc 450SLC 15.2 8 275.8
Cadillac Fleetwood 10.4 8 472.0
Lincoln Continental 10.4 8 460.0
Chrysler Imperial 14.7 8 440.0
Fiat 128 32.4 4 78.7
Honda Civic 30.4 4 75.7
Toyota Corolla 33.9 4 71.1
Toyota Corona 21.5 4 120.1
Dodge Challenger 15.5 8 318.0
AMC Javelin 15.2 8 304.0
Camaro Z28 13.3 8 350.0
Pontiac Firebird 19.2 8 400.0
Fiat X1-9 27.3 4 79.0
Porsche 914-2 26.0 4 120.3
Lotus Europa 30.4 4 95.1
Ford Pantera L 15.8 8 351.0
Ferrari Dino 19.7 6 145.0
Maserati Bora 15.0 8 301.0
Volvo 142E 21.4 4 121.0

Opt-out Globally instead of Chunk by Chunk

knitr allows to set the table.attr as an R options. This means the following can be done in two ways:

  1. Setting the option globally in a setup chunk

    ---
    title: "Disabling processing globally using setup chunk"
    ---
    
    ```{r}
    #| label: setup
    library(kableExtra)
    options(knitr.table.html.attr = "quarto-disable-processing=true")
    ```
    
    ```{r}
    #| label: tbl-results2
    #| tbl-cap: "mtcars with full_width = FALSE"
    kable(mtcars[,1:3]) |>
    kable_styling(c("striped", "bordered"), full_width = FALSE)
    ```
  2. Setting the option globally using knitr’s chunk option R.options set globally in YAML header as Quarto offers

    ---
    title: "Disabling processing globally using YAML"
    knitr: 
    opts_chunk: 
        R.options: 
        knitr.table.html.attr: "quarto-disable-processing=true"
    ---
    
    ```{r}
    #| label: setup
    library(kableExtra)
    ```
    
    ```{r}
    #| label: tbl-results2
    #| tbl-cap: "mtcars with full_width = FALSE"
    kable(mtcars[,1:3]) |>
    kable_styling(c("striped", "bordered"), full_width = FALSE)
    ```