haozhu233 / kableExtra

Construct Complex Table with knitr::kable() + pipe.
https://haozhu233.github.io/kableExtra/
Other
691 stars 147 forks source link

Math symbols in add_header_above escaped when rjtools generates a LaTeX pdf #836

Closed Dr-Eti closed 7 months ago

Dr-Eti commented 7 months ago

I am trying to use an R Journal article template (package rjtools) for my Rmd. When "knitting", this template joinlty produces an html and a LaTeX pdf.

The issue concerns the use of LaTeX of math symbols as part of the column headers text, when such headers are introduced via KableExtra's add_header_above(). For some reason, rjtools won't render correclty those math symbols in the pdf, even though - and this is the strange part - the same syntax will work if used elsewhere in the same table.

I am aware of several posts on e.g., StackExchange for which the answer usually boils down to something along the lines of setting the "escape" parameter in kbl, and doubling "\" for certain LaTeX macros. Yet it seems to me this is not what is at play here.

Below is how a dummy Rmd that replicates the problem looks like. The html should be fine, but the pdf generated by LaTeX should. Grateful if you could advise

---
title: "Table math bug test"
date: "2024-04-11"
abstract: >
  Just testing an issue with math in tables.
draft: true
author:  
  - name: someone
type: something
output: 
  rjtools::rjournal_article:
    self_contained: yes
    toc: no
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
library(ggbiplot)               # provides crime dataset
library(kableExtra)
data(crime)
temp_data <- force(crime)
mydata <- temp_data[which(temp_data$region == "Northeast"),2:3]
rownames(mydata)  <- temp_data[which(temp_data$region == "Northeast"),"st"]
X <- mydata
Y <- apply(X,2,function(x) (x - mean(x)))                       

# add some math symbols in additional rows, these should create no issue
test_tab_1 <- cbind(X, Y)
test_tab_extd <- rbind(test_tab_1, 
                  apply(test_tab_1, 2, mean), 
                  apply(test_tab_1, 2, var))
test_tab_extd <- round(test_tab_extd,2)
rownames(test_tab_extd) <- c(rownames(mydata),
                             "mean $\\mu$",                                   # this is rendered in both html and pdf
                             "sample variance")

# Add further math symbols in the caption (no issue) and in the added header (where the issue is)
kbl(test_tab_extd, 
     booktabs = TRUE,
     escape = FALSE, 
     caption = "Let's call this $\\mathbf{Z}$") %>%           # this is rendered in both html and pdf
   kable_classic(full_width = F, 
                 position = "left",
                )%>%
   row_spec(nrow(X), extra_css = "border-bottom: 1px solid")%>%
   add_header_above(c(" " = 1,
                       "raw $\\left[\\mathbf{X}\\right]$" = 2,          # this is NOT rendered in pdf, but works fine in html
                       "centred $\\left[\\mathbf{Y}\\right]$"=2      # this is NOT rendered in pdf, but works fine in html             
                       )) %>%
   add_header_above(c(" " = 1,
                      "Features" = 4))
dmurdoch commented 7 months ago

I found the issue: the second block of code should have been wrapped separately as a code chunk.

I think this really is a bug in add_header_above. To get what you want in the PDF, you need to change the call to it to

   add_header_above(c(" " = 1,
                       "raw $\\\\left[\\\\mathbf{X}\\\\right]$" = 2,          
                       "centred $\\\\left[\\\\mathbf{Y}\\\\right]$"=2             
                       ),  escape = FALSE)

Unfortunately, this messes up the HTML display. I'd guess there's probably some ugly workaround which figures out which format is being produced and uses the appropriate expression there. I'll see if I can find a better bug fix.

Dr-Eti commented 7 months ago

Hi that's very helpful, thank you for taking a look and for the clarification. I guess at the end of the day this is really just an issue for those who may be interested in submitting an academic article to R Journal. But their submission procedure is very structured and reliant on rjtools. Also, I appreciate that the ideal worflow - from article preparation to submission - appears like it should be self-contained (i.e. one should be able to do everything in say, RStudio). Hence why I've flagged this up even though I appreciate going too deep might not be worth the pain.

dmurdoch commented 7 months ago

I have a bug fix for this, which I'll be uploading soon. At the moment I'm just looking for the same kind of issue in other functions that allow user input to modify content of tables.

dmurdoch commented 7 months ago

You should be able to get the fixed version using

remotes::install_github("haozhu233/kableExtra")

It is version 1.4.0.4. Once CRAN has a higher version, regular install.packages("kableExtra") should work.

Dr-Eti commented 7 months ago

Thanks a lot I appreciate

Dr-Eti commented 7 months ago

Conscious this has been closed but just a quick comment to state the obvious, probably, just in case it helps other users:

To summarise

## some users might need to fix their token before being able to access this fix
usethis::create_github_token()
remotes::install_github("haozhu233/kableExtra", auth_token = 'MY_TOKEN_HERE')

## assuming the update is in place, and everything as in the example with which we started
 add_header_above(c(" " = 1,
                       "raw $\\left[\\mathbf{X}\\right]$" = 2,          
                       "centred $\\left[\\mathbf{Y}\\right]$"=2             
                       ),  escape = FALSE)

I confirm everything works fine now. Also, for those interested in the R Journal template specifically, it is sometetimes worth having a "double standard" in designing tables for html rather than LaTeX, which are then called as appropirate using eval = knitr::is_html_output() rather than eval = knitr::is_latex_output(). It's twice the workload but might be necessary to avoid predictable suprises. This comes across quite clearly in this vignette: https://rjournal.github.io/rjtools/articles/format-details.html

Again thanks a lot for this fix, it really helps

dmurdoch commented 7 months ago

@Dr-Eti : That's strange that you required a setting for auth_token. This is a public repository, so I thought anyone would be allowed to download. Maybe you have a token set for some other site that Github doesn't recognize, and you need to override that?

Dr-Eti commented 7 months ago

Don't think so - I've done standard checks as advised e.g., here https://stackoverflow.com/questions/70908295/failed-to-install-unknown-package-from-github. However, commands like

Sys.getenv("GITHUB_PAT")

returned nothing (literally ""). Resetting that woulnd't make any change, hence why I thought I'd share what happend to work for me. I was very puzzled