How to Use Plotly with Jekyll and Github Pages

14 May 2016

Any data analysis report can be more interesting with interactive charts and tables. Readers enjoy being able to ask questions of the data themselves to confirm your conclusions. You can add interactivity to your analyses by using Plotly. Plotly is a powerful software tool that enables you to make amazing charts with R.

My first thought after playing around with the library was wondering if I could use it when sharing to my website. My site is hosted on Github and powered by Jekyll. You can see the repo here. I usually knit my blog posts to a markdown file but that doesn't work with Plotly- the charts don't show up in the post. I searched for step-by-step instructions on how to make it work and came up empty handed. I did find this post which pointed me in the right direction but it took a little editing from there. Here is what I learned.

How to Build a Blog Post with Plotly from an .RMD for Your Github Hosted Blog

  1. Starting with the post itself, you'll have to write with html tags instead of using markdown. For me, that consisted of using <h3> instead of ### for headers and <ul> and <li> for lists. It's an inconvenience but it shouldn't stop you from writing your post.
  2. Add this line to your YAML front-matter: htmlwidgets: TRUE. By the end of this post you'll understand why this is neccessary but the short version is you'll use this switch to indicate if your post includes Plotly. Loading the page will probably take longer than a regular page so using this switch means we'll only have the delay when necessary.
  3. Edit your _layouts/post.html file to include this code snippet. This checks for the htmlwidgets switch from the previous step and if its found, builds in a link to all of the dependency files. I call them dependency files because they are Javascript libraries that power Plotly charts- your site now depends on these library files. Without them you'll only see a blank space in your blog.
  4. {% if page.htmlwidgets %}
    {% for html_dep in site.static_files %}
      {% if html_dep.path contains 'htmlwidgets_deps/' %}
        {% assign start = "<script src=" | append: {{site.baseurl}} %}
        {{html_dep.path | prepend: start | append: "></script>" }}
        {% endif %}
      {% endfor %}
    {% endif %}
    
  5. Now we have to either build a makefile or edit the file you are already using. We can't use the Knit HTML button from within RStudio because it won't know it needs to link with the dependency files. We start the makefile by downloading the brocks package built by Brendan Rocks. (With many thanks!) This package will take care of a lot of the back end tasks for us.
    devtools::install_github("brendan-R/brocks")
    library(brocks)
    
    With that package now installed, then the next step is to start on the build file. My build file uses this script, but the key functions are:
    filename <- "your-blog-post.Rmd"
    knit(input= filename,
         output=output,
         encoding= 'UTF-8')
    htmlwidgets_deps(paste0(Sys.Date(),"-",filename), always = T)
    
    Once you run those lines, you will have a knitted post and a new directory called htmlwidgets_deps. This new directory holds Javascript libraries from step 2 & 3.

    The function will also create a directory called _includes/htmlwidgets but the snippet we added to your posts.html file makes this other directory unnecessary. I recommend not pushing it to Github.

    To bring it all together, Step 2 is the switch to look for the Javascript libraries. If any are detected Step 3 will create the link between the post and Javascript libraries. Finally in Step 4 the libraries are saved to the root directory.

A Few Demonstrations

plot_ly(x= mpg,
        y= disp,
        data= mtcars,
        mode="markers") 


This next one is fun, go ahead and drag this one around to get a better view!

dat<- MASS::kde2d(x= iris$Sepal.Length, 
                y= iris$Sepal.Width, 
                h= iris$Petal.Length, 
                n= 50)

plot_ly(x = x,
        y = y,
        z = z,
        data = dat,
        type="surface",
        colorscale="Greens")

Posted with : R