Integrating D3.js into R Shiny

Spotify Interactive Discography Shiny App

In the past I’ve built apps with R Shiny, and I’ve also developed a few data visualisations with d3.js. Given that R Shiny is an R based Back End Server that renders a Front End in Java Script, it seemed like it would be possible to integrate a d3.js visualisation into an R Shiny App. After some quick research, it turns out that it is possible, this blog explains how to do it, and here is an example (please note this is hosted on Shiny.io and sometimes runs out of free hours each month)

I’m assuming a basic understanding of both R Shiny and d3.js. The process works around sending custom messages between the back end and the front end. Here’s how:

In your Shiny server file, create the JSON dataset that you wish to visualize. Then in the server file use the command:

session$sendCustomMessage(type="jsondata",var_json)

This sends a custom message across to the front end. In this case var_json would be the R object containing the JSON data. The type can be any label you like. You just reference it in the d3.js script to pick it up.

Next in the Shiny app area, create a folder labelled “www”. In this folder create a “.css” styling file for your d3 visualisation, and a “.js” javascript file to contain the d3.js code. At the top of the “.js” file, add message handling function like this:

Shiny.addCustomMessageHandler("jsondata",
function(message){
var json_data = message;

This searches for the custom message of the type “jsondata”. Then it takes the contents of the message, and assigns them to a java script variable, in this case json_data. Then place the d3.js code here referencing the json_data variable for the data, and close off the function. Make sure the div containing the visualisation has an ID to reference. Next alter the “.css” file to style your visualisation.

Finally in the Shiny UI file,

Use the tag$head to read in your “.css” file
tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "style.css"))

Use tags$script to load the d3 library
tags$script(src="https://d3js.org/d3.v3.min.js")

Use it again to read in the “.js” script containing the d3 visualisation
tags$script(src="d3script.js")

Then finally use the tags$div to render the div in position in the Shiny App
tags$div(id="div_reference")

And that’s it.

I’ve created an interactive discography app around the SpotifyAPI package I previously built. The Shiny App takes an input artist from the user. Then hits the Spotify API to find all the albums and tracks for that artist. Then renders them in a d3.js tree diagram with the ability to play a sample from each track. The code is on my github.

For lots of other useful Shiny tricks check out this useful book

8 thoughts on “Integrating D3.js into R Shiny

  1. Hello James,

    Your blog post and your codes in github inspired me to develop a shiny app, but now I’m stuck in it. I took every step correctly but shiny doesn’t seem to want to render the plot. I indeed need help. How can I contact you?

    I’ve posted the question here but no useful answer yet.
    http://stackoverflow.com/questions/38032231/how-to-link-a-json-object-from-r-source-code-to-d3-js-for-building-a-shiny-app/38037537#38037537

    Thanks in advance

  2. This is awesome. Thanks! I learned R and shiny and now am starting to try and learn d3. This is a very helpful example.

  3. Hi Mahtab – I was following this post too, and got stuck for awhile.

    I found a key statement was to use Json.parse. It is in James’ js file on Github. I think it is necessary with the toJSON function in R (?)

    I was trying to get this example form Mike Bostock, d3 creator to work. (link below). When I click run in Shiny it pulls in the data he used, but I needed to add JSON.parse to the code from the example.

    Shiny server:
    observeEvent(input$run,{
    json_data <- fromJSON(file="readme.json")
    var_json<-toJSON(json_data)
    session$sendCustomMessage(type="jsondata",var_json)
    })

    Added this to the js from the example:

    Shiny.addCustomMessageHandler("jsondata",
    function(message){
    var data=message;

    root = JSON.parse(data);

    Link to the d3 Example I was able to make work with shiny:
    https://bl.ocks.org/mbostock/1283663

    1. Thanks Joel. Unfortunately Spotify have made big changes to their API. If I get time I will re-work this.

Leave a Reply

Your email address will not be published. Required fields are marked *