Search code examples
htmlrmathlatexkableextra

kableExtra: Cannot save HTML table with math expressions & can't get in-line hist to display with Latex table


I want to save a table in R as an image that both includes math expressions in the column names and an in-line histogram from the spec_hist() function in kableExtra. Ideally, I would like the table formatted as a Latex table, but HTML would do too.

The problem I have is that when I try to save a kable HTML table, the math expressions are not properly interpreted, but the in-line histogram shows up nicely.

Meanwhile, if I try to save a kable Latex table, the math expressions are interpreted correctly, but the histogram will not appear.

Could this be a bug (two bugs?) in kableExtra? Or am I missing something?

Note that the kable HTML table looks perfectly fine (math expressions and in-line plot) in R Studio/R Markdown. But I want to save an reuse the image. The kable Latex table however never shows the in-line histogram, whether displaying in R or saved to a file.

Here is a reproducible example:

library(knitr)
library(kableExtra)

df <- mtcars[1:6,] %>% 
          mutate(`$\\theta_{boot}$` = "") %>% # add an empty column where the in-line histograms will go
          rename(`$mpg$` = mpg, # rename some columns to math expressions
                 `$\\bar{cyl}$` = cyl, 
                 `$\\bar{disp}$` = disp,
                 `$hp$` = hp, 
                 `$drat$` = drat)

# create dummy data for the in-line histograms
hist_dat <- list(runif(20), runif(20), runif(20), runif(20), runif(20), runif(20))


# Make HTML Table
kbl(df, escape = FALSE, booktabs = T, format = "html") %>%
  add_header_above(c("Some Header" = 6, "Some Other Header" = 7)) %>% # add header
  kable_styling(latex_options = c("repeat_header"), font_size = 12) %>%
  column_spec(12, image = spec_hist(hist_dat)) %>% # add in-line hist
  pack_rows("Group 1", 1, 3) %>%
  pack_rows("Group 2", 4, 6) %>%
  kable_paper() %>%
  as_image(file = 'temp.png')
  #save_kable(file = 'temp.png')

The above saves this image: enter image description here

The histogram is there, but the column names are printed as the literal rather than the interpreted math expressions.

Now for the Latex version:

# Make Latex Table
kbl(df, escape = FALSE, booktabs = T, format = "latex") %>%
  add_header_above(c("Some Header" = 6, "Some Other Header" = 7)) %>% 
  kable_styling(latex_options = c("repeat_header"), font_size = 12) %>%
  column_spec(12, image = spec_hist(hist_dat)) %>%  
  pack_rows("Group 1", 1, 3) %>%
  pack_rows("Group 2", 4, 6) %>%
  kable_paper(full_width = TRUE) %>%
  as_image(file = 'temp_latex.png')
  #save_kable(file = 'temp.png')

Using format = "latex" and full_width = TRUE generates the following file: enter image description here

Now the column names are interpreted correctly, but the histograms are not plotted.

I also found no difference whether I used as_image() or save_kable() to save the images.

Any ideas?

Thanks!

EDIT: Hardware notes: I'm on a Mac with a LaTeX install. Graphics work fine, although all calls that involved latex failed on my Windows machine (same code, MikTeX, Ghostscript & Magick installed).

> R.version
               _                           
platform       x86_64-apple-darwin17.0     
arch           x86_64                      
os             darwin17.0                  
system         x86_64, darwin17.0          
status                                     
major          4                           
minor          1.0                         
year           2021                        
month          05                          
day            18                          
svn rev        80317                       
language       R                           
version.string R version 4.1.0 (2021-05-18)
nickname       Camp Pontanezen 

Solution

  • If you knit the rmarkdown document then both the pdf document is generated (with the image included in the document) and the image is separately saved as a file.

    It seems as if the column spec needs to be adjusted to take into account the row names.

    Adding column widths helps to manage the table on the page.

    ```{r, results='asis'}
    
    library(knitr)
    library(kableExtra)
    library(dplyr)
    
    
    kable(df,
          format = "latex",
          escape = FALSE,
          booktabs = TRUE) %>%
      add_header_above(c("Some Header" = 6, "Some Other Header" = 7)) %>%
      kable_styling(font_size = 8, full_width = TRUE) %>%
      column_spec(1, width = "30mm") %>% 
      column_spec(2:12, width = "6mm") %>%
      column_spec(13, image = spec_hist(hist_dat, col = "red")) %>%  
      pack_rows("Group 1", 1, 3) %>%
      pack_rows("Group 2", 4, 6) %>%
      as_image(file = 'temp/as-image.png') 
      # as_image(file = 'temp/as-image.pdf') # works as pdf as well
    ```
    

    Image saved as pdf or png