An Introduction to the mutable Package

We have all been there.

Your data have been collected, cleaned, and analyzed. You have the results of a regression model or want to compare summaries of groups in a randomized study. All you want to do is create a basic table that you can quickly share with colleagues, students, or clients. It would be nice if you could define how the table looked with minimal time and effort. Oh yeah, it should be able to look as nice as you want.

Enter mutable.

Inspired heavily by xtable and Hmisc's summary.formula, the mutable package (https://github.com/erikriverson/mutable) provides a flexible suite of functions for generating markup tables from the R programming language. It allows users to construct objects of arbitrary tabular material such as data.frames, matrices, coefficient tables, and summaries of multiple variables. You can then output the object into a variety of formats. LaTeX, HTML, and plain text output functions are included by default.

But you don't have to trust that the author gave you the best way to represent a table in each markup language. You can supply your own formatting functions for all of these types of output. For example, the provided HTML output style for factors (percentages and fractions) can be completely changed if you specify your own muExportHTML function for objects of class factor. The modular design of the package allows every markup decision to be overridden easily and consistently. The result is that the user is in complete control over the final markup produced, and that multiple versions of the same table can easily be produced from the same data simultaneously.

Sound interesting? Let's walk through the basics!

First things first, let's install the package. It currently relies on a couple of other packages (Hmisc and RJSONIO) that you should make sure are installed so that the rest of the examples work. We also need to install devtools so that you can install the latest version of mutable from its Github repository. The following lines take care of all this housekeeping.

library(devtools)
install_github("mutable", "erikriverson")
library(mutable)
library(Hmisc)
library(RJSONIO)

Mutable can create markup tables from common R objects. For example, a data.frame. Simply call the mutable function on any data.frame. For this demo, we will use the mtcars data.frame that is built into base R.

m1 <- mutable(mtcars)

Mutable has created an object (m1) that contains markup for plain text, HTML, and LaTeX using its default markup functions!

summary(m1)
12 Columns: 

  mpg
  cyl
  disp
  hp
  drat
  wt
  qsec
  vs
  am
  gear
  carb 

3 markup objects: 
  plain
  html
  latex 

Since I am writing this demo using Markdown and using knitr to process it to HTML, I want to simply extract the HTML component. I can do this using the html function, which produces markup that generates the following table.

html(m1)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4
Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.46 20.22 1 0 3 1
Duster 360 14.3 8 360 245 3.21 3.57 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.19 20 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.15 22.9 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.44 18.3 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.44 18.9 1 0 4 4
Merc 450SE 16.4 8 275.8 180 3.07 4.07 17.4 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.73 17.6 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.78 18 0 0 3 3
Cadillac Fleetwood 10.4 8 472 205 2.93 5.25 17.98 0 0 3 4
Lincoln Continental 10.4 8 460 215 3 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 32.4 4 78.7 66 4.08 2.2 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.9 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.7 2.465 20.01 1 0 3 1
Dodge Challenger 15.5 8 318 150 2.76 3.52 16.87 0 0 3 2
AMC Javelin 15.2 8 304 150 3.15 3.435 17.3 0 0 3 2
Camaro Z28 13.3 8 350 245 3.73 3.84 15.41 0 0 3 4
Pontiac Firebird 19.2 8 400 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 27.3 4 79 66 4.08 1.935 18.9 1 1 4 1
Porsche 914-2 26 4 120.3 91 4.43 2.14 16.7 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2
Ford Pantera L 15.8 8 351 264 4.22 3.17 14.5 0 1 5 4
Ferrari Dino 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6
Maserati Bora 15 8 301 335 3.54 3.57 14.6 0 1 5 8
Volvo 142E 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2

That's about as basic an HTML table as you can get. But behind the scenes, mutable has generated not only the HTML markup to get you that table, but assigned each row and column its own CSS ID for you to customize.

Let's look at something a little more complex, summarizing multiple variables with columns for each value of a stratification variable. First, let's add variable labels to a different built-in data.frame.

data(airquality)
label(airquality$Ozone) <- "Ozone (ppb)"
label(airquality$Solar.R) <- "Solar R (lang)"
label(airquality$Wind) <- "Wind (mph)"
label(airquality$Temp) <- "Temperature (degrees F)"
airquality$Month <- factor(airquality$Month, labels = month.abb[5:9])

Now, use mutable's formula interface to create a summary table. This syntax follows Hmisc's summary.formula. Create an R formula with your stratification (column) variable on the left-hand side, and the list of variables you want to summarize on the right-hand side, separated with the + operator. This example only uses numeric (continuous) variables, but mutable handles all the common object classes.

m2 <- mutable(Month ~ Ozone + Solar.R + Wind + Temp, data = airquality)

And here is the HTML result.

html(m2)
Variable N May Jun Jul Aug Sep Overall
Ozone (ppb) 116 23.6 ( 22.2 ) 29.4 ( 18.2 ) 59.1 ( 31.6 ) 60 ( 39.7 ) 31.4 ( 24.1 ) 42.1 ( 33 )
Solar R (lang) 146 181.3 ( 115.1 ) 190.2 ( 92.9 ) 216.5 ( 80.6 ) 171.9 ( 76.8 ) 167.4 ( 79.1 ) 185.9 ( 90.1 )
Wind (mph) 153 11.6 ( 3.5 ) 10.3 ( 3.8 ) 8.9 ( 3 ) 8.8 ( 3.2 ) 10.2 ( 3.5 ) 10 ( 3.5 )
Temperature (degrees F) 153 65.5 ( 6.9 ) 79.1 ( 6.6 ) 83.9 ( 4.3 ) 84 ( 6.6 ) 76.9 ( 8.4 ) 77.9 ( 9.5 )

Want to use MathJax? No problem, mutable has an argument called markup.functions that you can specify to override the defaults. Since we only need to use the HTML version for this example, you can specify only one type of markup, html. However, the main idea is that markup.functions can be arbitrarily long, and contain all sorts of different types of markup-generating functions that will produce versions of your table.

m3 <- mutable(Month ~ Ozone + Solar.R + Wind + Temp, data = airquality, markup.functions = list(html = muExportHTMLMathJax))
html(m3)
Variable N May Jun Jul Aug Sep Overall
Ozone (ppb) \( 116 \) \( 23.6 \) ( \( 22.2 \) ) \( 29.4 \) ( \( 18.2 \) ) \( 59.1 \) ( \( 31.6 \) ) \( 60 \) ( \( 39.7 \) ) \( 31.4 \) ( \( 24.1 \) ) \( 42.1 \) ( \( 33 \) )
Solar R (lang) \( 146 \) \( 181.3 \) ( \( 115.1 \) ) \( 190.2 \) ( \( 92.9 \) ) \( 216.5 \) ( \( 80.6 \) ) \( 171.9 \) ( \( 76.8 \) ) \( 167.4 \) ( \( 79.1 \) ) \( 185.9 \) ( \( 90.1 \) )
Wind (mph) \( 153 \) \( 11.6 \) ( \( 3.5 \) ) \( 10.3 \) ( \( 3.8 \) ) \( 8.9 \) ( \( 3 \) ) \( 8.8 \) ( \( 3.2 \) ) \( 10.2 \) ( \( 3.5 \) ) \( 10 \) ( \( 3.5 \) )
Temperature (degrees F) \( 153 \) \( 65.5 \) ( \( 6.9 \) ) \( 79.1 \) ( \( 6.6 \) ) \( 83.9 \) ( \( 4.3 \) ) \( 84 \) ( \( 6.6 \) ) \( 76.9 \) ( \( 8.4 \) ) \( 77.9 \) ( \( 9.5 \) )

How about a SlickGrid table? SlickGrid is an exciting new JavaScript library with many interactive features. I was not able to (yet) figure out how to integrate the JavaScript output in the Rmd file through knitr, so until then, the results of this call are hosted at the link below. But the key point to notice is that we just had to write new wrapper functions and tell mutable about them. The SlickGrid-specific code is less than 70 lines long, and completely independent of the rest of mutable! It uses the RJSONIO package to convert R objects to JSON.


m4 <- mutable(mtcars)
html(m4, documentHeaderFunction = muSlickGridDocHeader, headerFunction = muSlickGridHeader, 
    markupFunction = muSlickGridMarkupGenerator, footerFunction = muSlickGridFooter, 
    documentFooterFunction = muSlickGridDocFooter, completeDocument = TRUE, 
    markupElement = "plain", file = "mutable-slickgrid.html")

See the results at
http://www.sigmafield.org/mutable-demo/mutable-slickgrid.html

I hope you enjoyed learning a little bit about what the mutable package can do. It is a flexible method for generating markup tables of all types, while allowing complete customization of the result.