TeXing R tables: Save yourself a lot of typing…

March 27, 2013
By

(This article was first published on Rcrastinate, and kindly contributed to R-bloggers)

I want to share a function I wrote for my dissertation. The function is useful for putting up to two R tables into one TeX table.

You have to load the package 'languageR' to have the dataset 'dative' available.

Let's suppose you have two tables, one with means and another one with standard deviations. Of course, these two tables have the same number of rows and columns - this is also checked in the function.


library(languageR)

mean.tab <- tapply(dative$LengthOfTheme, list(dative$PronomOfTheme, dative$AnimacyOfTheme), FUN = mean)

sd.tab <- tapply(dative$LengthOfTheme, list(dative$PronomOfTheme, dative$AnimacyOfTheme), FUN = sd)

The tables look like this:

> mean.tab
               animate inanimate
nonpronominal 3.365854  4.588718
pronominal    2.000000  2.270619
> sd.tab
               animate inanimate
nonpronominal 3.440611  4.493893
pronominal    2.715695  2.621017

But what you want, is this:








(click to enlarge)

As TeX code, this looks like this:

\begin{table}
  \centering
  \caption{Mean (SD) lengths of theme.}
  \begin{tabularx}{\textwidth}{X X X X}
  \toprule
   & & \multicolumn{2}{c}{Animacy of Theme} \\
   & & animate & inanimate \\
   \midrule
  \multirow{2}{*}{Pronominal}& no & \SI{3{,}37}{letters} (\SI{3{,}44}{}) & \SI{4{,}59}{letters} (\SI{4{,}49}{}) \\
  & yes & \SI{2}{letters} (\SI{2{,}72}{}) & \SI{2{,}27}{letters} (\SI{2{,}62}{}) \\
  \bottomrule
  \end{tabularx}
\label{yourlabel}
\end{table}

Most of the time, you have your raw code for the table without the values. The part that sucks is the typing of all the numbers, brackets, backslashes for the actual values in the table. This part is done by my function 'make.tex.vals' (see the bottom of the text).

A few more comments: In the TeX table, I used the \toprule, \midrule and \bottomrule commands. These are from the TeX package 'booktabs' and allow for APA style tables. The \SI{...} commands are from the package 'siunitx' and allow for good value-unit formatting. The function provided below creates output according to this package and fills in the values and units for you.

The function takes the following arguments:
tab: The first table to convert.
dig: The number of digits the values are rounded to (default: 1)
unit1: The unit of the values in the first table (default: "s" for seconds)
dec: The decimal separator (default: "," for German style numbers)
prefix1: A string to put before each value from 'tab' (default: "" for no prefix)
suffix1: Same as 'prefix1' but after each value
tab2: The second table, the values in each cell are written behind the values of 'tab' in the respective cell (default: NULL, no second table)
unit2: See 'unit1'
prefix2: See 'prefix1' (default: "(", e.g., for standard deviations)
suffix2: See 'suffix1' (default: ")")
eor: End of row marker (default: "\\\\", two backslashes, makes it easier to copy the whole line of output from R to TeX)

So, if I do a call like this:
make.tex.vals(tab = mean.tab, dig = 2, unit1 = "letters", dec = ",", tab2 = sd.tab)

I get this output on the R console:
\SI{3{,}37}{letters} (\SI{3{,}44}{}) & \SI{4{,}59}{letters} (\SI{4{,}49}{}) \\
\SI{2}{letters} (\SI{2{,}72}{}) & \SI{2{,}27}{letters} (\SI{2{,}62}{}) \\


I simply copy this into my raw table and saved myself a lot of typing.

Leave a comment if you have any questions regarding the use of the function...

Now, here is the function:

make.tex.vals <- function (tab, dig = 1, unit1 = "s", dec = ",", prefix1 = "", suffix1 = "", tab2 = NULLunit2 = "", prefix2 = "(", suffix2 = ")", eor = " \\\\") {
  dec.sep <- paste("{", dec, "}", sep = "")
  if (!is.null(tab2)) {
    stopifnot(all.equal(dim(tab), dim(tab2)))
    for (row.i in 1:nrow(tab)) {
      row.tab1 <- tab[row.i,]
      row.tab2 <- tab2[row.i,]
      vals <- c()
      for (val.i in 1:length(row.tab1)) {
        val1 <- as.character(round(row.tab1[val.i], dig))
        val2 <- as.character(round(row.tab2[val.i], dig))
        val1c <- paste(prefix1, "\\SI{", gsub(".", dec.sep, val1, fixed = T), "}{", unit1, "}", suffix1, sep = "")
        val2c <- paste(prefix2, "\\SI{", gsub(".", dec.sep, val2, fixed = T), "}{", unit2, "}", suffix2, sep = "")
        both.vals <- paste(val1c, val2c)
        vals <- c(vals, both.vals)
        }
      cat(vals, sep = " & ")
      cat(eor)
      cat("\n")
      }
    }
  else {
    for (row.i in 1:nrow(tab)) {
      row.tab1 <- tab[row.i,]
      vals <- c()
        for (val.i in 1:length(row.tab1)) {
        val1 <- as.character(round(row.tab1[val.i], dig))
        val1c <- paste(prefix1, "\\SI{", gsub(".", dec.sep, val1, fixed = T), "}{", unit1, "}", suffix1, sep = "")
        vals <- c(vals, val1c)
        }
      cat(vals, sep = " & ")
      cat(eor)
      cat("\n")
      }
    }
}







To leave a comment for the author, please follow the link and comment on his blog: Rcrastinate.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.