The world’s leading publication for data science, AI, and ML professionals.

Creating beautiful stand-alone interactive D3 charts with Python

With application to D3 force-directed network graphs

Screenshot from: https://d3js.org/
Screenshot from: https://d3js.org/

Visualizing your data can be the key to success in projects because it can reveal hidden insights in the data, and improve understanding. The best way to convince people is by letting them see and interact with their data. Despite many visualization packages being available in Python, it is not always straightforward to make beautiful stand-alone and interactive charts that can also work outside your own machine. The key advantage of D3 is that it works with web standards so you don’t need any other technology than a browser to make use of D3. Importantly, interactive charts can help to not just tell the reader something but let the reader see, engage, and ask questions. In this blog, I will outline how you can build your own stand-alone, interactive force-directed D3 network using Python. Note that the steps are similar to any other D3 chart. __ If you need a working version, the _d3grap_h library is for you!


If you found this article helpful, use my referral link to continue learning without limits and sign up for a Medium membership. Plus, follow me to stay up-to-date with my latest content!


Motivation to use D3

D3 is short for Data-Driven Documents, which is a JavaScript library for producing dynamic, interactive data visualizations in web browsers. It makes use of Scalable Vector Graphics (SVG), HTML5, and Cascading Style Sheets (CSS) standards. D3 is also named D3.js or D3js. I will use the names interchangeably. There are many advantages of using D3 above interactive Python solutions, let me list a few [1];

  • D3 is a Javascript library. So, it can be used with any JS framework of your choice like Angular.js, React.js, or Ember.js.
  • D3 focuses on data, so in case you are in the field of Data Science, it is a relief that tens of thousands of data points remain interactive without putting any extra effort into it.
  • D3 is lightweight, works directly with web standards and is therefore extremely fast, and works well with large datasets.
  • D3 is open-source. So you can work with the source code and add your own features.
  • D3 works with web standards so you don’t need any other technology or plugin other than a browser to make use of D3.
  • D3 works with web standards like HTML, CSS, and SVG, there is no new learning or debugging tool required to work on D3.
  • D3 does not provide any specific feature, so it gives you complete control over your visualization to customize it the way you want.

D3 charts.

D3 is a collection of modules that are designed to work together; you can use the modules independently, or you can use them together as part of the default build. The D3 website provides 168 working charts that allow for performant incremental updates during interaction and supports popular interaction such as dragging, brushing, and zooming. The charts can be used for many purposes, such as quantitative analysis, visualizing hierarchies, creating networks graphs, but also bar plots, line plots, scatter plots, radial plots, geographic projections, and various other interactive visualizations for explorable explanations. Some cherry-picked charts are shown in Figure 1. Various of these d3js charts are readily Pythonized in the D3Blocks library. Read the D3Blocks medium article for more details.

Figure 1: Various examples of D3 charts. Screenshots from https://d3js.org/
Figure 1: Various examples of D3 charts. Screenshots from https://d3js.org/

Getting started!

Let’s begin our D3-Python project! Before we can make the step towards Pythonizing the D3 charts, we need to understand how D3 works. I will demonstrate it by creating a very small force-directed network graph in D3 (without Python) and after that, I will demonstrate the integration in Python. The best way to explain the development of the chart in D3 is by splitting the development into four distinct parts;

  1. The Cascading Style Sheets (CSS).
  2. The D3 module contains all required libraries.
  3. Javascript to build the chart.
  4. The Data as JSON file.

Each part has its own role in the chart and to get a working version, we need to connect all parts which we can do in an HTML file as depicted in Figure 2. In the following sections, I will describe the role and implementation of each part.

Figure 2: Four parts are connected in a final HTML file to build the D3 graph. Image from the author.
Figure 2: Four parts are connected in a final HTML file to build the D3 graph. Image from the author.

1. The Cascading Style Sheets (CSS)

The CSS file is a simple mechanism for adding style in a structured manner to HTML files. For example, CSS files can define the size, color, font, line spacing, indentation, borders, and location of HTML elements. We are going to create force-directed network graphs, for which we will define the overall font sizes, font family, style, colors but also properties specific for the nodes, and edges. You can change the CSS accordingly, and set the properties as you think is best. The file I created can be downloaded here and looks as follows:

2. D3 module

The D3 module is the easiest part because you only need to import it or embed the entire content in the final HTML file. The D3 module contains all functions to create any of the charts. No edits in this file are required. The newest version is v7 which can be imported from a local source or the website.

<script src="https://d3js.org/d3.v7.min.js"></script>

I will be using a slightly older version (v3) because I readily created many of my scripts using this version. It can be downloaded here, and it is included in my example code a few steps below. If you build your own graph, I strongly recommend using the latest version.

3. Javascript that builds the chart.

Building a chart does not require you to start coding from scratch. We can go to the chart of interest on the D3 website and use the code that is open-source available. Let’s go to the force-directed graph page and read the section "How do I use this code?". The following is described:

Figure 3: Screenshot from https://observablehq.com/@d3/force-directed-graph.
Figure 3: Screenshot from https://observablehq.com/@d3/force-directed-graph.

It tells us to copy-paste the entire "ForceGraph" function that is shown in the part below. I created another screenshot (Figure 4) where you can see the part "function Forcegraph({" which thus is the ForceGraph function. You need to copy the entire function and paste it into a new file. I will name my file d3graphscript.js which can be downloaded here. Note that my function is slightly different than the newest one shown over here. The website also tells us to import the D3 module which we readily covered in the previous section.

Figure 4: Part of the ForceGraph code. The screenshot is taken from: https://observablehq.com/@d3/force-directed-graph.
Figure 4: Part of the ForceGraph code. The screenshot is taken from: https://observablehq.com/@d3/force-directed-graph.

4. Data

The fuel for the charts is the data that we need to get in the right shape. Although there is functionality in D3 to import a local .json-file using d3.json(), it may not work because importing a local csv or json file with D3 is not considered to be safe. A solution is to embed the data directly in the final HTML file. However, depending on the amount of data, it can result in a massive HTML file. Nevertheless, embedding the data directly in the HTML will integrate all scripts and data into a single file which can be very practical. An example of a json data file is shown in the box underneath where some of the nodes and edges are described. We can embed such data block in the HTML. The complete json data file can be downloaded here.

graph = {"links":[{"node_weight":5,"edge_weight":5,"edge_width":20,"source_label":"node_A","target_label":"node_F","source":0,"target":2},{"node_weight":3,"edge_weight":3,"edge_width":12,"source_label":"node_A","target_label":"node_M","source":0,"target":4}"]}

5. Connecting the parts

We now have our four parts (CSS, D3, javascript graph, and Data) that are required to build the chart. I created an HTML boilerplate where the four parts will be connected; downloaded here. The parts are included as follows:

  1. The Cascading Style Sheets (CSS) as style.css
  2. The D3 module as d3.v3.js
  3. The javascript to build the chart as d3graphscript.js
  4. The Data as _json_data_

    To create the final HTML, you can replace the content in each file on the line where it is included. Or in other words, replace {% include "style.css" %} with the content in style.css and so on. You will get a working chart which will look like this. Check the page source or the script below to see the four parts combined. That’s it! you created a force-directed network graph in D3! Because we created four building blocks, it is a small step to integrate this graph in Python.


Turn D3 into Python

The step to Pythonize the D3 scripts is by changing the static values into variables. We can do this for the final HTML file and for the properties in the force-directed javascript file. The idea is as follows:

  1. Import/read the final HTML and/or javascript file using Python.
  2. Replace the variables with any desired value using Python.
  3. Write the final adjusted HTML file to disk.

But first, we need to manually change the static values into variable names in the final HTML. Let’s do this for width, height, charge, distance, directed, and collision into variables. It is important to create unique variable names to avoid accidental wrong replacements. My solution was by creating variable names such as {{ width }}, which can now easily be found and replaced in Python with the real value. In addition to the final HTML file, and javascript graph file, the json data file also contains variables that can be changed accordingly. Note that the D3 module will remain untouched. Before you start implementing all of this, read the next section!


The d3graph library

The d3graph library is designed in a similar manner as described in the sections above. It is a Python library that is built on D3 and creates a stand-alone, and Interactive force-directed network graph. The input data is an adjacency matrix for which the columns and indexes are the nodes and the elements with a value of one or larger are considered to be an edge. The output is a single HTML file that contains the interactive force-directed graph. Here is a demonstration of the network from the Titanic use case. My D3 version has some extensions, among them a slider that can break the edges of the network based on the edge value, and a double click on a node will highlight the node and its connected edges. To make your own network graph, pip install the d3graph package with:

pip install d3graph

Now you can make the interactive Network with various parameters:

Figure 5: Various graphs created using d3graph. Image by the author.
Figure 5: Various graphs created using d3graph. Image by the author.

Final words

Congratulations! You have just learned how to create beautiful D3 charts and in particular force-directed networks using D3 and how to integrate it into Python. I hope this blog will give you the knowledge needed to create any D3 chart you wish with or without Python. The d3graph library will help you create your own D3 force-directed graph using Python. The output is a single HTML file that works in a stand-alone fashion and can be shared or posted on websites for which you don’t need any other technology than a browser. You can also integrate the D3 network graph as a visualization in your existing library. Read this blog about how I did it for the HNet library to learn associations. In case you want to create other d3js charts such as Scatterplot, Violin plot, Movingbubbles, Sankey, Heatmap, Chord, Timeseries, Imageslider, or Particles, we created the D3Blocks library with 10 beautiful charts that can be created with Python. Read the D3Blocks medium post [2] for more details. Feel free to play around with the library and fork the source code.

Be safe. Stay frosty.

Cheers, E.


If you found this article helpful, use my referral link to continue learning without limits and sign up for a Medium membership. Plus, follow me to stay up-to-date with my latest content!


Software

Let’s connect!

References

  1. https://www.tutorialsteacher.com/d3js
  2. E. Taskesen, D3Blocks: The Python Library to Create Interactive and Standalone D3js Charts, Medium, Towards Data Science, September 2022

Related Articles