The Marketing Technologist.

We talk about analytics, code, data science and everything related to marketing technology. Backed by the tech geeks of Greenhouse.

How to make an interactive data visualisation with Matplotlib and JavaScript

On May 4, I found a nice data set on Kaggle with all the lines from the original Star Wars trilogy. I had the idea to make an analysis of those lines and quickly decided to present the results in an interactive plot. It turned out to be quite an interesting challenge.

Generating an SVG in Matplotlib

The first step is easy. I created a visualisation of my output data with Matplotlib. You can simply set the extension in your file name to .svg and run your script to get your file. Nothing fancy here.

Making the SVG interaction friendly

Now this is where it gets interesting. Let’s start by having a look at the visualisation. My visualisation is an abstract representation of the sentiment development in the movie. Each dot represents a line. The x-axis is time, the y-axis the sentiment score, and the size of a dot the magnitude of sentiment.

Here's an example of Han Solo's lines from the first movie:

It would be nice if each dot had an associated data point. In my case, each dot represents a line by a Star Wars character and the results of the sentiment analysis of that line. So it would be nice if each dot on my scatter plot includes the following meta data:

  • Index of line in movie.
  • Character.
  • Character dialogue.
  • Sentiment score.
  • Magnitude.

Matplotlib doesn’t seem to allow you to add classes or data attributes to the plot elements when you export it as an SVG. But it would be really nice to have that right? Especially when you want to make the plot interactive.

A small detour

I first forgot to take a step back, and started looking for a solution within my web application. Every character was represented with their own unique colour. So I thought: if I fetch the colour of a data point, I can infer the character from that colour. This initially worked, but as soon as I started implementing interactions based on data values (e.g. sentiment score), this mapping setup was not sufficient.

The real fix

It’s funny how not working on a project often helps you work on the project. I like to take walks, and during this project I had a few (safe) walks outside. Nine out of ten times, I find my solution to a problem by not not being behind my computer. And this problem was no different.

The fix was actually quite nice. As I run the data analysis in Python myself, I have access to all the data behind the dots in my scatter plot. So I thought: why not print a list that includes a data object (dictionary) for every dot in my scatterplot? Then all I have to do is copy-paste this list into JavaScript as an array, loop through the elements of my plot, and add the data attributes I want to them.

My assumption here is that the index of a dot I fetch with JavaScript matches the index of the data in my array. Luckily, good code is predictable, and may assumption holds true. Here’s the JavaScript code I use to fetch the SVG elements and add data attributes to them:

var paths = document.querySelectorAll('#PathCollection_1 path');

for (var i = 0; i < paths.length; i++) {	
    var element = paths[i],			
        element_data = data_list[i],
        character = element_data.character,
        sentiment = element_data.sentiment;                        
    element.setAttribute("data-sentiment", sentiment);

Now this gave the result I wanted: easy accessible data attributes for each dot.

Having fun with data visualisation

The new approach made it easier to add the interactions that I wanted. It allowed me to have some fun with the data visualisation. Let me give you two examples of what this allows you to do.

1: Expand or collapse the space between dots by using a ‘use the force’ button

2: Change colours from character colours to sentiment colours

Pretty nice right?

Give it a try

I have no clue how many people build interactive visualisation based on Matplotlib SVGs. Probably most people use D3.js to make custom interactive plots. But it’s good to know that with a little extra preparation work in Python, adding some interactions is quite easy and fun.

You can visit this page to give my Star Wars data visualisation a try.