Integrating Javascript and d3 into R notebooks

Recently the team over at RStudio released R Notebooks.

R Notebooks are really interesting. Here’s why:

  • You can write code in several different languages in one document (including python, bash, dot, ruby, javascript, sql)
  • You can write in Markdown
  • You can write in HTML
  • You can see your code as it runs
  • Writing reproducible code is easier
  • It’s easy to share code results with others

It’s the intertwining of languages bit that interests me the most.

This feature means we can do our data reading, wrangling and machine learning in R, and then create deep, powerful, interactive visualisations with d3.js. We can do all of this from one document, and the results are all in one document too.

It sounds complicated. But it’s not.

It’s actually really simple.

Getting started with R Notebooks Link to heading

To open a new R Notebook, open up RStudio, then go File > New File > R Notebook. Make sure you have RStudio version 1.0 or later installed otherwise this option won’t show up.

You’ll get a template file that contains a YAML header, a bunch of Markdown, and a chunk of R code that plots stuff from the cars  dataset.

This blog post isn’t intended to be an introduction to R Notebooks. For that I’ll point you towards the official resources. If you’re stuck, read that page, google round a bit and then come back here.

Including JavaScript/d3 code in R Notebooks Link to heading

Let’s take the d3 code from this example. If you’d like to learn how the d3 code works in this example, see this post or this page for lots of tutorials.

The key to incorporating d3 code is that the R Notebook accepts HTML along with Markdown outside of code chunks. You can mix and match the two - just don’t put them together without separating them with code chunks, else your code won’t compile.

Along with HTML, R Notebooks also accept CSS and Javascript. This means that we can just include a similar block of code as we would when writing a d3 visualisation, and it’ll just work.

One important thing to note is that you must compile to HTML if you want to incorporate d3 code. Knitting your results to PDF or Word format won’t work.

Anyway, here’s the R Notebook complete code:

---
title: "Mixing R and D3.js"
output:
  html_document: default
  html_notebook: default
---

## D3 / HTML / JAVASCRIPT 
```r
```
<svg width="400" height="400"></svg>
<script src="./d3.v4.min.js"></script>
<script src="./force_graph_code.js">  </script>
```r
```

## R 
```r
plot(cars$speed)
```

A quick explanation:

  • The chunks of code that look like
```r
```

are there to separate between the HTML and the Markdown in order to prevent compile issues. The echo = FALSE parameter means that the code chunks aren’t visible in the output.

  • Between those two blank chunks of code I create a SVG element, which will host our d3 visualisation. After, I call two scripts:

    • First script refers to version 4 of d3, which you can find here. I’ve saved it locally into the same folder as the R Notebook code.
    • Second script is my d3 code to make the visualisation, saved in the file force_graph_code.js. Again this is saved in the same folder as the R Notebook code.
  • After the d3 code is some R code just to prove that we can put both in the same R Notebook

The force_graph_code.js file is just all the stuff between the <script> and the </script> tags in the example.

Run the Knit to HTML button and you’ll get an interactive force-directed graph alongside your R code. Cool!

Thoughts Link to heading

Unfortunately R Notebooks don’t allow for sharing variables between languages. This means that your JavaScript and d3 code won’t be able to access variables in your R code and vice versa.

Hence probably the best and easiest way of passing data between the two languages is to save the data locally. For example, you can run some R code over a dataset, save the results as a CSV file and then use the d3.csv function to read the CSV file into JavaScript. From there you can build your interactive d3 graph.

I’m incredibly excited by all of this. I think we’ll see some great things from merging the two languages.

At the very least it allows for a data workflow option that’s easy and convenient. What’s not to love?