Got a random fun one today. How to create circular packing in Tableau! This run-through won’t be as heavily detailed on the python side of things today. If you’re new to python, I’d recommend just running the code as it is and trying the Tableau aspect first before you feel comfortable to go back and edit the data input. Shoot me a message if you get stuck.
What is circular packing?
You may be sitting there thinking this looks oddly similar to the packed bubble on the show me tab in Tableau. You’d be correct! The packed bubbles is a non-hierarchal version of this.
Circular packing is also an alternative to tree-maps. It allows the individual to visualise a hierarchal organisation. Each tree is represented as a circle and its sub-nodes are represented as circles.
In the case of what we will run through today you will see the overall chart visualises at level 1 – The world. At level 2, The chart shows continents (within the world). Within this circle for each continent are circles representing countries, level 3. Hence, you can see how the circles become packed within their parent level.
It is important to note that the area of the circles are proportional to the values passed in at the same hierarchical level. For instance, countries are not sized against continents, but they are sized against one another within a continent.
Where did the inspiration come from?
The idea initially came from seeing this method of visualising a code repository by Amelia Wattenberger. I advise clicking the link and scrolling through the example it is well worth the time!
I think it is a stunning way of easily translating what is quite a lot of heavy code, into a structure of folder, types of code format. Once you’re familiar with the visual language, it becomes much easier to see similarities, differences, and patterns across codebases.
Anyway, back to the run-through…
You can download my amended code from the github link at the top of the blog.
The original python code that has been amended for Tableau purposes can be found here. I would highly recommend looking at this original code to understand the process.
If you’d like to create your own circular packing here are a few pointers:
- You can hover over the package details to see how the data gets inputted. You will see the data naming conventions want the data to be prepped having an “ID”, and “Datanum” as default. Alternatively search for circlify documentation online.
- I’ve tried to organise the GIT code to be easily digestible in terms of how the data needs to be passed in. It can be a little challenging getting the brackets correct and understanding how the different levels work.
- One main change to the code is the addition of exporting our data to a csv. I’ve added a field name of rank. We use the rank to be able to position the circles as well as sort them for colouring purposes when it comes to the Tableau build. You will also notice we want to export centre point of each circle as well as the radius. This is important for sizing in Tableau!
- I amended the figure size for convenience of keeping things proportional when we want to use the value exports in Tableau.
- I’ve left in the parts of the python code that create the graph using Matpotlib, I felt like this was useful so you would know if 1) your code runs, 2) what the graph in Tableau should look like!
You can download the dashboard at the top of the page.
If you’d like to give the Tableau part a go only download the data from the Github repository.
This is the python output we are trying to replicate:
Once we have run our code we will get the csv export countries, that we will want to add in another sheet of T values between 1 and 100. You can find a copy of what that looks like in the repo.
We will want to join the sheets with a custom calculation of 1 = 1. This duplicates our dataset with 100 rows for each country as we will use these points to create circles.
Next we create 6 calculations.
Angle – We will want to plot 100 points in a circle. This calculation finds what the angle between each point will be. You will see I minus 1 in order for the lines to overlap allowing for me to use a polygon and line tool effectively.
*The T value is 100 not 50 as shown in the comment as I wanted the circle to be a bit more rounded.
Rank Angle – Find the angle for each point. If you’ve followed my blogs you will see I tend to build most my radial vizzes using the same logic.
X – Now we use trigonometry to make our circle…. a circle. We multiply by the radius as otherwise without this all our radius’ would be equal to 1. This allows for the circles to be the correct proportion.
Y – Same as above but wrapped in a sin function.
3a X – So what are we doing here? As you can imagine we have created our sizes circles but at the moment they all sit on top of one another. We add the X co ordinate from the original data in order to shift it to where the centre point of the specific country should be. (I.e Transpose)
Same for 3b Y, we transpose the circle adding on the centre point to the calculation to move the circle upwards by Y cord.
Now you can plot your 3a. X against your 3b. Y
(Side note: I apologise for the naming conventions the use of numbers and lettering is so that you can see in which order the calculations are made)
Make both X and Y dimensions.
Add ID to detail and change Marks to Line.
Drag T to Path.
Fix the axis between -1.1 and 1.1, remember our python code made the circles max size 1.
Add ID to colour, Sort the colour descending on Rank. (This is because we want Level 1 at the back, i.e the world. Level 2 of continents to sit in front, and then Level 3 of countries to be on top.)
You can then change the marks card to be polygon if you want the circles to be filled!
As further steps, I added a few more calculations 4a,5a,5b to the workbook to show how you can make the most of layering functionality to create some pretty cool alternative versions of the chart. They cover off how to make some of the circles lines and some as polygons. Download the workbook to see.
There we have it our finished packed circle!
As always, Let me know how you get on with this one. I can be reached on Twitter, @_CJMayes.