rlatexknitrxtablernw

xtable for conditional cell formatting not with special characters


I'm apply solution from xtable for conditional cell formatting significant p-values of table to my data set; however, I can't use sanitize.text.function = function(x) x as per the suggested answer.

Example

Data set

The data set contains text columns that utilise _ character, as in the example below:

dta <- data.frame(
    varA = c("this_and_that", "something_else", "def"),
    varB = c("other_thing", "something_different", "abc")
)

xtable

When passed to it using the syntax:

print.xtable(x = xtable(dta), 
             booktabs = TRUE,
             comment = FALSE,
             floating = TRUE,
             type = "latex",
             include.rownames = FALSE,
             NA.string = "NA",
             # Font and linespace size
             size = "\\fontsize{5pt}{5pt}\\selectfont")

the code generates usable latex snippet:

\begin{table}[ht]
\centering
\begingroup\fontsize{5pt}{5pt}\selectfont
\begin{tabular}{ll}
  \toprule
varA & varB \\ 
  \midrule
this\_and\_that & other\_thing \\ 
  something\_else & something\_different \\ 
  def & abc \\ 
   \bottomrule
\end{tabular}
\endgroup
\end{table}

Problem

I would like to apply \textbf{} to columns with word something. Following the answers discussed in the linked question this could be done via ifelse and sanitize.text.function = function(x) x as in the example below:

print.xtable(
    x = xtable(dta %>%
                   mutate_all(funs(
                       ifelse(grepl("something", .), paste0("\\textbf{", ., "}"), .)
                   ))),
    booktabs = TRUE,
    comment = FALSE,
    floating = TRUE,
    type = "latex",
    include.rownames = FALSE,
    NA.string = "NA",
    # Font and linespace size
    size = "\\fontsize{5pt}{5pt}\\selectfont",
    sanitize.text.function = function(x) {
        x
    }
)

This will generate correct syntax with respect to the \\textbf{} but the _ is not escaped due to : sanitize.text.function = function(x) {x}.

\begin{table}[ht]
\centering
\begingroup\fontsize{5pt}{5pt}\selectfont
\begin{tabular}{ll}
  \toprule
varA & varB \\ 
  \midrule
this_and_that & other_thing \\ 
  \textbf{something_else} & \textbf{something_different} \\ 
  def & abc \\ 
   \bottomrule
\end{tabular}
\endgroup
\end{table}

Removed sanitize.text.function

The code:

print.xtable(
    x = xtable(dta %>%
                   mutate_all(funs(
                       ifelse(grepl("something", .), paste0("\\textbf{", ., "}"), .)
                   ))),
    booktabs = TRUE,
    comment = FALSE,
    floating = TRUE,
    type = "latex",
    include.rownames = FALSE,
    NA.string = "NA",
    # Font and linespace size
    size = "\\fontsize{5pt}{5pt}\\selectfont"
)

will generate awful mess as default sanitize behaviour will attempt to escape \\textbf

\begin{table}[ht]
\centering
\begingroup\fontsize{5pt}{5pt}\selectfont
\begin{tabular}{ll}
  \toprule
varA & varB \\ 
  \midrule
this\_and\_that & other\_thing \\ 
  $\backslash$textbf\{something\_else\} & $\backslash$textbf\{something\_different\} \\ 
  def & abc \\ 
   \bottomrule
\end{tabular}
\endgroup
\end{table}

Alternative approach / side point

Probably better approach would be to make use of the sanitize function:

print.xtable(
    x = xtable(dta),
    booktabs = TRUE,
    comment = FALSE,
    floating = TRUE,
    type = "latex",
    include.rownames = FALSE,
    NA.string = "NA",
    # Font and linespace size
    size = "\\fontsize{5pt}{5pt}\\selectfont",
    sanitize.text.function = function(x) {
        ifelse(grepl("something", x), paste0("\\textbf{", x, "}"), x)
    }
)

Summary

Is there other way of addressing this problem than greping all the special characters in my table and manually escaping them via custom sanitize function that would handle both elements textbf{} and _ correctly?


Working solution

Using:

  sanitize.text.function = function(x) {
    gsub(fixed = TRUE, pattern = "_", replacement = "\\_", 
         x = ifelse(grepl(pattern = "something", x = x), paste0("\\textbf{", x, "}"), x)
         )
  }

will work as it manually escapes _, ideally I would like to find a solution where I wouldn't have to manually espace each single character.


Solution

  • There is a function in Hmisc which does the work : latexTranslate. Run it first and then apply the LATEX format commands.

    library("Hmisc")
    library("xtable")
    dta <- data.frame(
        varA = c("this_and_that", "something_else", "def"),
        varB = c("other_thing", "something_different", "abc")
    )
    print.xtable(
        x = xtable(dta),
        file=paste0(getwd(),"/table/sanitize_test.tex"),
        booktabs = TRUE,
        comment = FALSE,
        floating = TRUE,
        type = "latex",
        include.rownames = FALSE,
        NA.string = "NA",
        # Font and linespace size
        size = "\\fontsize{5pt}{5pt}\\selectfont",
        sanitize.text.function = function(x) {
          x <- latexTranslate(x)
          x <- ifelse(grepl("something", x), paste0("\\textbf{", x, "}"), x)
          return(x)
        }
    )   
    

    enter image description here