edited on 19.01.2021
I’ve, recently, published a blog post called Perfect Workflow for Publishing Python Notebooks. I tried to explain some of the benefits of using Rmarkdown and reticulate. In this post, I’ll try HTML widgets and explain how we can embed those in our blog post using nothing but R.
knitr::opts_chunk$set(eval = FALSE, echo = TRUE)
Let’s start with basics.
library(MASS)
data(iris)
head(iris)
See, the result is a little different than what you are used to see in RStudio. What we see in the website using the code above, is just text printed out, not even an HTML table. This is not very important for displaying only 6 rows but what if I want to show more? For a better experience, we can use the datatable
function from DT
library.
DT::datatable(iris, filter="top", options = list(pageLength = 5))
Now, it’s a dataframe with pagination, sort, filter, and search options.
What else we can embed?
A simple example of leaflet:
library(widgetframe)
library(leaflet)
map <- leaflet(height=300) %>%
addTiles() %>%
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
frameWidget(map)
Time-series data with dygraph:
library(dygraphs)
lungDeaths <- cbind(mdeaths, fdeaths)
frameWidget(dygraph(lungDeaths))
Holt-winters example with dygraph & dySeries:
hw <- HoltWinters(ldeaths)
p <- predict(hw, n.ahead = 72, prediction.interval = TRUE)
graph <- dygraph(p, main = "Predicted Lung Deaths (UK)") %>%
dySeries(c("lwr", "fit", "upr"), label = "Deaths")
frameWidget(graph)
We can also use, plotly to generate interactive plots, xaringan for slides, rbokeh, networkD3 and probably more.
Details
Normally when we use Hugo or any other static site generator, they use some markdown engine to render markdown documents into HTML files. Hugo is using an engine called Goldmark since v0.60.
An R Markdown document is different. An R Markdown document can contain executable code chunks of R, Python, SQL, Bash, and even more programming languages. Hugo (goldmark) can’t render it directly. So, to publish the RMarkdown document on our website, we can generate a markdown file then give it to Hugo’s markdown renderer or convert it directly to HTML. In order to use these widgets, we are going to generate an HTML file directly from the r markdown. The HTML page will include some javascript libraries. Thankfully, all these happen automatically. R Markdown documents get compiled through the packages rmarkdown, bookdown and Pandoc and converted into HTML files. Then Hugo uses these HTML files.
For example, this document’s extension is .Rmd
. When I call the blogdown::serve_site()
function, blogdown renders through this .Rmd
file and generates an HTML file based on the blogdown::html_page
output format. It creates all necessary javascript and CSS files into the folder named index_files
under the post’s directory.
Trade Offs
- Using R Markdown can make things slower, compared to plain markdown. Well, isn’t it normal? We are executing the code each time we render the document. It may not affect much though. You should read from here, instead of listening to me.
- Widgets are not responsive, but we can wrap them with iframes using widgetframe by bhaskarvk.
- If you are using a custom CSS file instead of a compatible theme from the community, you may get weird results. Wrapping the widget by iframe may also help with that.
- Don’t forget that you are introducing new javascript files that are overhead.
- js files under
index_files
directory will make source code dirty. index_files
folder is replicated for each rmarkdown file. There must be a better way to handle these dependencies and share them along with posts yet I couldn’t find any.- HTML widgets will not work with
.Rmarkdown
files, you have to use.Rmd
files if you are going to use HTML widgets.
Rmarkdown vs Rmd
Well, they are the same thing. Text files that contain markdown as a markup language and they can contain code chunks. These code chunks get compiled via R. Difference between these two extensions lies in how r packages are treating them. I don’t know if there is any difference for pandoc or knitr but when we are using blogdown; .Rmarkdown
generates .markdown
while .Rmd
generates .html
.
So, if we try to use HTML widgets with .Rmarkdown
we will get an error saying that “objects that have dependencies (e.g. HTML widgets) do not work when the output format is Markdown instead of HTML.”.
Another difference between these two is that when using .Rmd
you’ll need a client-side syntax highlighter like highlight.js. Because blogdown doesn’t use server-side syntax highlighter. On the contrary, you won’t need a client-side highlighter with .Rmarkdown
. Because, in the end, it generates .markdown
files, and then they are rendered via Hugo. Hugo has a built-in server-side highlighter called Chroma.
Conclusion
In conclusion, we can use HTML widgets in r markdown documents for pretty much everything. You don’t need to know javascript thanks to r packages. You don’t need R runtime once the file is compiled. It should be easy if you are already using these packages and familiar with the R environment. Yet, probably, there will be a learning curve for new comers.
I don’t think I’ll use these widgets. Most of the time, a markdown with plots (as images) should suffice in a blog post. I like to stay close to pure markdown files as much as possible because that way the content will have fewer dependencies.
Update: This was just an experiment for me and maybe a demo for you. I didn’t want to keep the aforementioned “index_files” in the repo. So, I removed them and set the evaluation of all chunks to FALSE. The codes above should work if you try them in your R environment.