published on 31.12.2020
edited on 26.06.2021

I’ve, recently, published a blog post called Perfect Workflow for Publishing Python Notebooks. I talked about 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.

1
knitr::opts_chunk$set(eval = FALSE, echo = TRUE)

Let’s start with basics.

1
2
3
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.

1
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:

1
2
3
4
5
6
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:

1
2
3
library(dygraphs)
lungDeaths <- cbind(mdeaths, fdeaths)
frameWidget(dygraph(lungDeaths))

Holt-winters example with dygraph & dySeries:

1
2
3
4
5
6
7
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.

You are reading the 2nd of 2 episodes in Rmarkdown.
Published on 31.12.2020 by Mert Bakır. Last update on 26.06.2021 with commit 4fa6ba7.
rmarkdown
#hugo #rmarkdown #rstudio #workflow
published on 30.11.2020

I’ve been searching for a good workflow for publishing Jupyter or RMarkdown Notebooks as static blog posts. I think I’ve found the optimal solution for my use case. In this post, I’ll explain my workflow and why chose this way with examples. […] In reality my main purpose to …

published on 03.08.2020

In this post, I aim to explain this website. Template by template… The main purpose here is to create a document to myself for future reference. Templates are complicated and not easy to read. That’s why I’ll probably forget what I did and why I coded this way. […] We are …

published on 24.01.2021
edited on 11.06.2021

Some time ago, I wanted to display image galleries on my Hugo website and searched for Hugo themes for photography and gallery. I can’t say I find much. Then, I met with a javascript library called nanogallery2 which is using another javascript library as an image viewer lightbox2. In this …

published on 23.01.2021
edited on 11.06.2021

Image processing may seem complicated at first but it’s actually easy and definitely worth implementing since it’ll help you decrease page load times. As you probably know, we don’t want to load raw images with huge sizes for small thumbnails or blog-posts. We want to load a small …

published on 05.12.2020

Resume A4 is a side project of mine. It’s one page Hugo Theme that allows you to write your resume in YAML format and keep track of it using git. Also, you can publish it online as a static site using GitLab, GitHub Pages, Netlify, or some other service you are familiar with. A few months …

published on 29.11.2020
edited on 05.12.2020

Plotly is a visualization library that allows us to write code in Python, R, or Julia and generates interactive graphs using Javascript. So, we don’t have to deal with Javascript. You can checkout Plotly gallery, there are interesting works. Anyway, last week, I’ve started learning …