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::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.
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.
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
index_files under the post’s directory.
- 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.
- js files under
index_filesdirectory will make source code dirty.
index_filesfolder 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
.Rmarkdownfiles, you have to use
.Rmdfiles 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;
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.
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.