formattable was originally designed to offer additional formatting to the markdown generated by the deliberately sparse knitr::kable. This design limited formattable to only the context of an Rmarkdown document. Other contexts, such as the R console or RStudio IDE, would only see the much less attractive character markdown output.

library(formattable)

as.character(formattable(head(mtcars,3)))
## [1] "|              |  mpg| cyl| disp|  hp| drat|    wt|  qsec| vs| am| gear| carb|"
## [2] "|:-------------|----:|---:|----:|---:|----:|-----:|-----:|--:|--:|----:|----:|"
## [3] "|Mazda RX4     | 21.0|   6|  160| 110| 3.90| 2.620| 16.46|  0|  1|    4|    4|"
## [4] "|Mazda RX4 Wag | 21.0|   6|  160| 110| 3.90| 2.875| 17.02|  0|  1|    4|    4|"
## [5] "|Datsun 710    | 22.8|   4|  108|  93| 3.85| 2.320| 18.61|  1|  1|    4|    1|"

Fortunately, a new function as.htmlwidget uses markdown to easily convert a formattable object to an htmlwidget. Once converted to an htmlwidget, a user in these other contexts can leverage the infrastructure of htmlwidgets to benefit from the final HTML output of formattable.

Demonstration of conversion

note, please run these in an ?interactive environment such as the console or RStudio IDE to see the difference

Let’s explicitly convert a formattable to an htmlwidget to help us understand what is happening.

as.htmlwidget( formattable( head(mtcars,3) ) )

Although our htmlwidget version looks virtually the same when generated from a Rmd document such as this vignette, a user in the console will have a noticeably different experience than before. The function interactive() can help formattable to guess when it should automatically convert to a htmlwidget. formattable will not auto-convert in the special situation where format = "pandoc" as shown below.

formattable( head(mtcars,3), format = "pandoc" )
## 
## 
##                   mpg   cyl   disp    hp   drat      wt    qsec   vs   am   gear   carb
## --------------  -----  ----  -----  ----  -----  ------  ------  ---  ---  -----  -----
## Mazda RX4        21.0     6    160   110   3.90   2.620   16.46    0    1      4      4
## Mazda RX4 Wag    21.0     6    160   110   3.90   2.875   17.02    0    1      4      4
## Datsun 710       22.8     4    108    93   3.85   2.320   18.61    1    1      4      1

If you prefer to avoid the automatic conversion to an htmlwidget, use as.character(formattable(...)).

As an additional example, we can recreate the example from Tristan Mahr(@tjmahr) with formattable.

## use formattable to recreate the example in
## https://rpubs.com/tjmahr/prettytables_2015

library("magrittr")
library("dplyr")
## Warning: package 'dplyr' was built under R version 3.1.3
library("broom")
library("stringr")
library("knitr")

fix_names <- . %>%
  str_replace(".Intercept.", "Intercept") %>%
  str_replace("Species", "") %>%
  # Capitalize species names
  str_replace("setosa", "Setosa") %>%
  str_replace("versicolor", "Versicolor") %>%
  str_replace("virginica", "Virginica") %>%
  # Clean up special characters
  str_replace_all(".Width", " Width") %>%
  str_replace_all(".Length", " Length") %>%
  str_replace_all(":", " x ")

# Print with n digits of precision
fixed_digits <- function(xs, n = 2) {
  formatC(xs, digits = n, format = "f")
}

# Don't print leading zero on bounded numbers.
remove_leading_zero <- function(xs) {
  # Problem if any value is greater than 1.0
  digit_matters <- xs %>% as.numeric %>%
    abs %>% is_greater_than(1)
  if (any(digit_matters)) {
    warning("Non-zero leading digit")
  }
  str_replace(xs, "^(-?)0", "\\1")
}

lm(Sepal.Length ~ Species * Sepal.Width, iris) %>%
  tidy %>%
  set_colnames( c("Param", "Estimate", "SE", "_t_", "_p_") ) %>%
  mutate( Param = fix_names( Param ) ) %>%
  formattable(
    list(
      "_p_" = formatter(
        "span"
        ,style = x ~ ifelse( x < 0.05, style( color = "red", font.weight = "bold" ), NA )
        ,ps ~ {
          tiny <- "< .001"
          ps_chr <- ps %>% fixed_digits(3) %>%
            remove_leading_zero
          ps_chr[ps < 0.001] <- tiny
          ps_chr
        }
      )
    )
    ,digits=2
  )
Param Estimate SE t p
Intercept 2.64 0.57 4.62 < .001
Versicolor 0.90 0.80 1.13 .261
Virginica 1.27 0.82 1.55 .123
Sepal Width 0.69 0.17 4.17 < .001
Versicolor x Sepal Width 0.17 0.26 0.67 .503
Virginica x Sepal Width 0.21 0.26 0.83 .411

htmlwidgets inside a formattable

Courtesy of this issue we have an interesting example of interactive sparkline htmlwidgets inside a formattable. ** note: only works in Rmd currently **

# use builtin chickwts ?chickwts

library(dplyr)
library(formattable)
# devtools::install_github( "htmlwidgets/sparkline" )
library(sparkline)

chickwts %>%
  group_by( feed ) %>%
  summarise(
    weight = sprintf("`r sparkline(c(%s), type = 'box')`", paste0(weight, collapse=","))
  ) %>%
  ungroup %>%
  as.data.frame %>%
  formattable(
    list(
      weight = function(spkline){
        sapply(spkline, function(md) knitr::knit(text=md, quiet=T) )
      }
    )
  )
feed weight
casein
horsebean
linseed
meatmeal
soybean
sunflower