Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
The htmlTable 2.0 package was just released on CRAN! It is my most downloaded package with 160 000+ downloads/month and this update is something that I have been wanting to do for a long time. For those of you that never encountered htmlTable it is a package that takes a matrix
/data.frame
and outputs a nicely formatted HTML table. When I created the package there weren’t that many alternatives and knitr was this new thing that everyone was excited about, magrittr with its ubiquitous %>%
pipe had not even entered the scene. The current update should make it easier to streamline table look, separate layout from content and use tidyverse functionality.
Style and theming
The biggest change in how to use the htmlTable
is that you have a separate function for adding style to the table. The change is implemented in a non-breaking fashion, i.e. all the old options should work just as before but the new API is encouraged as it simplifies a lot. The new API changes so that instead of all the css.*
arguments we now have a separate function that applies these, addHtmlTableStyle
and passes them on as an attribute to the htmlTable
:
library(htmlTable) library(magrittr) options(table_counter = TRUE) rbind( `Group A` = c(20, 5, 380, 95), `1` = c(11, 55, 9, 45), `2` = c(11, 55, 9, 45) ) %>% addHtmlTableStyle(css.rgroup = "-style: italic", css.header = "-weight: normal") %>% htmlTable(header = rep(c("No", "%"), times = 2), n.cgroup = list(c(2), c(2, 2)), cgroup = list('Super', c("First", "Second")), rgroup = c("", "Group B"), n.rgroup = 1, caption = "A simple htmlTable example with the core components")
As we usually want the same layout for the entire table we can accomplish the same effect for all of our tables using setHtmlTableTheme
and the style will be applied to all your tables.
library(glue) setHtmlTableTheme(css.rgroup = "-style: italic", css.header = "-weight: normal", pos.caption = "bottom") rbind( `Group A` = c(20, 5, 380, 95), `1` = c(11, 55, 9, 45), `2` = c(11, 55, 9, 45) ) %>% htmlTable(header = rep(c("No", "%"), times = 2), n.cgroup = list(c(2), c(2, 2)), cgroup = list('Super', c("First", "Second")), rgroup = c("", "Group B"), n.rgroup = 1, caption = glue("Same as Table {last} but with general styling and caption positioned at the bottom.", last = tblNoLast()))
There is an option for selecting themes with predefined layouts. In addition to the standard
which has the traditional htmlTable
look, you also have Google docs
and blank
. The Google docs is still a work in progress and any help making it as compatible as possible with Google’s Drive document when copy-pasting is much appreciated.
Using tidyverse syntax in tidyHtmlTable
In 2017, Stephen Gragg added the tidyHtmlTable
to the package. Since then advances to RStudio has impacted in how we use R and it became obvious that the function should instead of strings as arguments directly accept column names just as defined by tidyselect. The tidyHtmlTable
solves one of htmlTable
‘s greates weaknesses, the need for calculating the rgroup
, tspanner
, cgroup
arguments and using it with the tidyselect
interface is now pure joy:
library(tidyverse) tribble( ~ rowname, ~ `No (First)`, ~ `% (First)`, ~ `No (Second)`, ~ `% (Second)`, "Group A", 20, 5, 380, 95, "Group B1", 11, 55, 9, 45, "Group B2", 11, 55, 9, 45, ) %>% pivot_longer(cols = c(starts_with("No"), starts_with("%"))) %>% mutate(group = str_replace(rowname, "Group ([AB]).*", "\\1"), rowname = str_replace(rowname, "Group ([AB12]+).*", "\\1"), group = if_else(group == rowname, "", group), header = str_replace(name, "([^ ]+).*", "\\1"), cgroup = str_replace(name, ".*\\(([^)]+)\\)$", "\\1")) %>% tidyHtmlTable(rgroup = group, header = header, cgroup = cgroup, rnames = rowname, caption = "A version of the first tables but using the tidyHtmlTable")
A more advanced example on how tidyHtmlTable
works with tidyverse
we can have a look at the example in the vignette("tidyHtmlTable")
:
mtcars %>% as_tibble(rownames = "rnames") %>% pivot_longer(names_to = "per_metric", cols = c(hp, mpg, qsec)) %>% group_by(cyl, gear, per_metric) %>% summarise(Mean = round(mean(value), 1), SD = round(sd(value), 1), Min = round(min(value), 1), Max = round(max(value), 1), .groups = 'drop') %>% pivot_longer(names_to = "summary_stat", cols = c(Mean, SD, Min, Max)) %>% ungroup() %>% mutate(gear = paste(gear, "Gears"), cyl = paste(cyl, "Cylinders")) %>% arrange(per_metric, summary_stat) %>% addHtmlTableStyle(align = "r") %>% tidyHtmlTable(header = gear, cgroup = cyl, rnames = summary_stat, rgroup = per_metric, caption = "A full example of how to apply the tidyverse workflow to generate a table")
When using tidyHtmlTable
you can decouple it from htmlTable
and provide any table function by supplying the table_fn
function.
Options
In htmlTable 2.0 there are plenty of options that have been added. Most of them should start with the prefix “htmlTable.”, e.g “htmlTable.css.tspanner.sep”. While the prefix is useful for reducing the risk of conflicting options between packages, options such as “table_counter” are unchanged in order to avoid unnecessary breaking changes.
NEWS for 2.0
- Added theming and styling with
addHtmlTableStyle
andsetHtmlTableTheme
to reduce the cognitive burden of finding the right option within the docs. Note: this may impact your current tables and hence the major version (2.0.0). - Changed so that
css.cell
is properly applied torownames
, cell fillers and the actual cells of interest (may impact the final layout!) - Breaking change
tidyHtmlTable
: Moved to a fully tidyverse compatible system withtidyHtmlTable
. This is a breaking change to the API as we switch from columns as strings totidyselect
syntax and asgather
/spread
have been replaced bypivot_longer
/pivot_wider
the default values have been updated in accordance with their defaults, e.g.rnames = "name"
andvalue = "value"
. - Breaking change
tidyHtmlTable
: Sorting of rows is skipped as we may have situations with repeating inputs and this can easily be performed pre-function by callingdplyr::arrange
. This has furthermore the desirable feature that any custom sorting is retained. - Added mso-number-format to help (Issue #63) – thanks Rasmus Hertzum
txtRound
can now addtxtInt
when formatting the integer section for easier readability- Added
htmlTable
css options – they should all start withhtmlTable.
pos.caption
now uses match.arg as expected- Fixed proper S3 function definition for htmlTable with all the arguments
- Added
htmlTable.css.border
style option for allowing to choose border style. Also fixed bug withcgroup
empty cells and vertical border. - Added
htmlTable.pretty_indentation
option for skipping the stripping of all the tabs that was required due to old Pandoc bug. - Added
attr(x, "html") < - TRUE
by default and UTF-8 encoding on all outputted strings to mimic thehtmltools::HTML
function behavior. - For simple
tibble
output thetidyHtmlTable
can now be used to choose a column for thernames
argument - The
print
statement now respects thechunk_output_type
in Rmd files in RStudio
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.