library("highcharter")
library("tidyverse")
library("widgetframe")
library("quantmod")
usdjpy <- getSymbols("USD/JPY", src = "oanda", auto.assign = FALSE)
eurjpy <- getSymbols("EUR/JPY", src = "oanda", auto.assign = FALSE)
hc_stock_data <- highchart(type = "stock") %>%
hc_add_series(usdjpy, id = "usdjpy", name = "USD / JPY") %>%
hc_add_series(eurjpy, id = "eurjpy", name = "EUR / JPY") %>%
hc_size(width = "350px", height = "200px") %>%
hc_rangeSelector(enabled = FALSE) %>%
hc_legend(enabled = TRUE)
frameWidget(hc_stock_data)Update, October 2025: The htmlwidgets hex sticker wish came true! Read 7 Years in the Making: a htmlwidgets hex sticker! for the full story.
If you’ve never heard of them, htmlwidgets are an amazing part of the work that RStudio (plus Ramnath Vaidyanathan and Kent Russell)1 have undertaken to make R a beautiful tool for doing data science and communicating things about your data. You probably haven’t heard about htmlwidgets, so let’s cover what it is first:
htmlwidgets is a tool for R developers that allows them to easily build R wrappers for JavaScript libraries, which means useRs can build interactive visualisations! Here are two of my favourite htmlwidget libraries:
highcharter: uses the awesome Highcharts library and allows beautiful looking charts, time series and more to be created directly from R code! I really love how professional it looks - see what happens if you select one of the items in the legend 😄
leaflet: uses the awesome Leaflet library that allows us to create interactive maps, choropleth and other charts. It has a cousin called
mapviewthat’s even more powerful that I’ll be switching preference to as 2018 rolls on.
library("sf")
library("gapminder")
library("leaflet")
geojson_worldmap <- st_read(
"https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json",
quiet = TRUE
)
geojson_worldmap <- invisible(
geojson_worldmap %>%
left_join(
gapminder %>%
filter(year == max(year)),
by = c("name" = "country")
) %>%
filter(name != "Antarctica")
)
palette_pop <- colorNumeric(
"YlOrBr",
geojson_worldmap$pop,
na.color = "#c0c1c4"
)
lf_gapminder_pop <- geojson_worldmap %>%
leaflet(width = "300px", height = "200px") %>%
addPolygons(
fillColor = ~ palette_pop(pop),
fillOpacity = 0.8,
color = "#000",
weight = 1,
label = ~name
)
frameWidget(lf_gapminder_pop)So why do I assume you haven’t heard of them?
Well, they’re hardly ever spoken about or searched for! Hadley Wickham is a huge promoter of the benefits of visualisation in data science2 but has only ever mentioned htmlwidgets on Twitter explicitly 3 times prior to February 2018. And just compare the Google Search Trends for tidyverse and htmlwidgets, there’s desperately little love for htmlwidgets.
The crux of the problem really is that htmlwidgets is a developer tool. The actual packages that folks build using it are really popular! htmlwidgets spiritual home is htmlwidgets.org which is maintained by the RStudio folks, where they keep a list of featured htmlwidgets libraries available on CRAN. Here’s a quick overview of these libraries (as of February 2018):
| package | so.tag | mention.htmlwidgets |
|---|---|---|
| leaflet | leaflet | FALSE |
| dygraphs | dygraphs | FALSE |
| plotly | plotly | FALSE |
| rbokeh | rbokeh | FALSE |
| highcharter | r-highcharter | FALSE |
| visNetwork | visnetwork | FALSE |
| networkD3 | networkD3 | TRUE |
| d3heatmap | d3heatmap | TRUE |
| DT | datatable | TRUE |
| threejs | three.js | TRUE |
| DiagrammeR | diagrammer | FALSE |
| metricsgraphics | metricsgraphicsjs | FALSE |
| htmlwidgets | htmlwidget | NA |
It’s really easy to get download figures for CRAN using the cranlogs library. In the table below I’ve collected the daily download figures for the featured htmlwidget libraries and calculated the median daily downloads.
library("cranlogs")
release_date_htlmlwidgets <- lubridate::ymd("2014-12-09")
cran_downloads <- featured_htmlwidget_libraries |>
select(package) |>
pmap(function(package, ...) {
cran_downloads(packages = package, from = "2014-12-09", to = Sys.Date())
}) |>
bind_rows() |>
as_tibble()
median_daily_downloads <- cran_downloads |>
filter(count > 0) |>
filter(package != "htmlwidgets") |>
group_by(package) |>
summarise(median.downloads = median(count)) |>
arrange(desc(median.downloads))I hoped to get a good idea on Twitter about how many folks were using htmlwidgets libraries without knowing that’s what they were. Unfortunately, the reach of my poll was very small with the tweet only appearing in a timeline 307 times.
#rstats #dataviz folks! Do you use any of these libraries:
— Charlie Joey Hadley (@charliejhadley) February 5, 2018
leaflet, dygraph, plotly, rbokeh, highcharter, visNetwork, or DT?
If so, did you know these are examples of htmlwidgets?
(See https://t.co/DtVNBSFJZA if you didn't know!)
Promoting the htmlwidgets brand
I think it’s shame that there isn’t more exposure for the htmlwidgets brand and underlying technology. I meet a lot of folks in my training courses who have simply never heard the term, despite perhaps using leaflet or plotly already. If these folks knew they were htmlwidgets they could perhaps find more tools for visualising their data in new and interesting ways.
These are the things I’d really love to see:
htmlwidgetshexsticker: Hexstickers are awesome and really popular amongst useRs, it would be awesome to have a dedicated sticker for thehtmlwidgetsbrand.htmlwidgetsmentioned in plain simple human language in the following places; GitHub README pages, Package DESCRIPTION files, and in the welcome pages for dedicated package websites.- Talk about
htmlwidgetsmore in Tweets and other comms channels from RStudio.
I kind of get the feeling that htmlwidgets is currently in stealth mode and I’m not sure why. Maybe RStudio are waiting until the (exciting!) crosstalk features are added to more htmlwidgets libraries? But that feels like a 2.0 feature!
I’m going to do everything I can in my teaching, evangelism and general talking about R at parties to promote htmlwidgets and I’d love to see others do the same.
Footnotes
Thanks to Joe Chung for highlighting @ramnath_vaidya and @timelyportfolio’s contributions on Twitter link.↩︎