TITLE: R functions for creating LaTeX variables
DATE: 2020-01-07
AUTHOR: John L. Godlee
====================================================================


After writing some more for a manuscript I decided to formalise my
workflow where I output numerical variables from R for use in LaTeX,
so if the values change they update automatically in the manuscript.
Below is a collection of functions which make the process easier:

Formatting a number with the correct number of decimal points or
significant figures:

    num_format <- function(x, digits = 2, method = "round"){
      sprintf(paste0("%.",digits,"f"),
        if(method == "round"){
          round(x, digits = digits)
        }else if(method == "signif"){
          signif(x, digits = digits)
        })
    }

Formatting a p-value:

    p_format <- function(p, digits = 2){
      dplyr::case_when(p < 0.01 ~ "p<0.01",
        p < 0.05 ~ "p<0.05",
        TRUE ~ paste0("p = ", as.character(num_format(p, digits = digits)))
      )
    }

-   p_format(1.1) = “p = 1.10”
-   p_format(0.025) = “p<0.05”
-   p_format(0.494, digits = 1) = “p = 0.5”

Extracting the slope and standard error from a linear regression:

    lm_format <- function(x, digits = 2){
      paste0("F(",
        summary(x)$fstatistic[2],
        ",",
        summary(x)$fstatistic[3],
        ") = ",
        num_format(summary(x)$fstatistic[1], digits = digits),
        ", ",
        p_format(anova(x)$`Pr(>F)`[1])
      )
    }

mod1 <- lm(mtcars$mpg ~ mtcars$hp

-   lm_format(mod1) = “F(1,30) = 45.46, p<0.01”

Formatting two arbitrary numbers as x plus/minus y:

    pm_format <- function(x, y, dx = 2, dy = dx + 1, pm = "$\\pm$"){
      paste0(num_format(x, digits = dx),
        pm,
        num_format(y, digits = dy)
      )
    }

-   pm_format(0.3332, 0.4673) = “0.33$\pm$0.467”
-   pm_format(0.3332, 0.4673, dx = 1, dy = 3) = “0.3$\pm$0.467”

Output the value of a variable as a LaTeX variable:

    command_output <- function(x, name){ 
      paste0("\\newcommand{\\",
        ifelse(missing(name), deparse(substitute(x)), name), 
        "}{", 
        x, 
        "}"
      )
    }

x <- 0.4367

-   command_output(x) = “\newcommand{\x}{0.4367}”
-   command_output(x, "test") = “\newcommand{\test}{0.4367}”

Notice that all the backslashes have to be duplicated to escape them
when they are written to a file.

Write a list of commands to a .tex file:

    latex_write <- function(list, path){
      fileConn <- file(path)
      writeLines(
        unlist(list, use.names = FALSE), fileConn)
      close(fileConn)
    }

Full example:

    val1 <- 0.55
    val2 <- 0.2477
    val3 <- 0.044

    values_list <- list(val1 = val1, val2 = val2, val3 = val3)

    command_list <- list()
    for(i in 1:length(values_list)){
        command_list[[i]] <- command_output(
          num_format(
            values_list[[i]]
            ),
          names(values_list[i])
        )
    }

    latex_write(command_list, "test.tex")