Building SVG Paths in Alteryx + Tableau

Background

Recently my family watched Disney’s Moana for the first time. We all really enjoyed the movie, especially my two young daughters. After the movie was over, my five-year-old noticed the spiral in the title on the movie case and asked me whether I could build it on the computer. I figured this was as good an opportunity as any to show her the power and possibilities of math. 

Thus, I started thinking through all the different ways this could be done. If nothing else, I thought it would be a fun enough challenge to try.

Use case … not so much

There is not much of a use case here, basically, I am taking SVG path coordinates and translating them into points for Tableau to render. Having said, that, showing my daughter that this can be built with math and the challenge it posed was enough for me. I doubt you will be using this technique in your day job (but let me know if you do!).

Attempt 1 (Math Only):

I started by researching spirals and all the different types (there are a lot and it is kind of awesome). I found the wiki page for Fermat’s spiral and via the eye ball test concluded that it appeared to be the base spiral leveraged to build what I was looking for. Using polar coordinates, creating the spiral is only a few simple equations coupled with data densification:

Here is the data source I loaded into Tableau:

Here are the functions built (also available in the embedded workbook below):

The above lead me to this result (note that I only took the blue spiral to 315 degrees when bringing the data into Tableau):

Not bad, definitely looks like the right spiral, but it doesn’t have the outline that will make the spiral result recognizable to my daughter.

Attempt 2

PNG -> SVG -> Alteryx Parsing -> Tableau Densification & Render

I wanted to get more exact on the re-build, to do this I need information of the image. What were the various coordinates being used to draw the out line of the shape? Ultimately, I found this image and leveraged pngtosvg.com to convert it into SVG.  In addition, I also found this Alteryx workflow by Niccolo Cirone and I was on my way with a new approach.

I did a little manual work to identify the specific SVG path I wanted and removed all the extra stuff I didn’t need. This made it easier to debug as I went. I put this data in the above workflow and crossed my fingers…

I quickly realized that I needed to augment the workflow to account for the curves and lines that I needed to draw. My image is not detailed enough to just plot the raw coordinate points of the SVG which the workflow seemed to provide.

I already have built curves in Tableau, so the thought was to do some data prep and copy the math from my other workbook. Here is the Alteryx workflow to prepare the data for densification and math in Tableau.

Here is the data output from the above flow:

I brought the above into Tableau, parsed the coordinates of the SVG paths and calculated the lines and/or Bezier curves (C = Cubic Bezier Curve, L = Line, M = Move To) within Tableau. Here is my result (see embedded workbook for detailed calculations):

I have the shape outline and my line version looks pretty good. But the problem with the polygon view is the “svg_path_id” pill.

moana9.png

With the densification I am doing, I am calculating each line and curve as a stand alone item and because of that I am required to have this pill on the detail shelf, which renders my 1 SVG as 34 separate polygons, and thus they do not quite fit the mold of the single SVG I am going for when viewing as polygon mark type.

I may be able to figure this out in Tableau, but also thought it would be fun to try and calculate the Bezier curves in Alteryx. So I went that route (if you have a fix for my problem above within Tableau, let me know, I will add it here).

Attempt 3

PNG -> SVG -> Alteryx Parsing, Densification & Calculations -> Tableau Render:

Using the below addition to the above workflow, I pushed all the calculations into Alteryx and created a single SVG level output for Tableau.

The nice thing here is I no longer had to do data densification in Tableau, the downside is that the Alteryx workflow is more complicated. This is ultimately a give and take really as I need to do the math somewhere.

I brought this dataset into Tableau, and dragged the following pills:

  • svg_id on detail
  • svg_record_id on path
  • BezierX on Columns
  • BezierY on Rows

And… viola!

Limitations

The Alteryx workflow will only handle single SVGs with M, C and/or L SVG Path elements. This can of course be expanded to other SVG elements like Q and A if the need arises.

Analyzing 538's March Madness Win Probabilities with Alteryx and Tableau

This post is a run through of the approach and some techniques utilized to build out the long form story visualization embedded at the bottom of this post.

Data Source:

First and foremost, the data source for this viz (as well as a great deal of inspiration) is the FiveThirtyEight (538) March Madness Predictions site (one of my favorites each year). You will note that the in-game probability line chart is also a re-make of 538’s work and not my original design.

I leveraged Alteryx to pull and parse the data for the analysis (see my workflow below). It just makes things so easy, I had to add this note to the post. There was one point in the project where I decided on a tweak something, it took me a matter of minutes to pull up my flow, add/remove a few tools and generate an updated set of files for Tableau, and everything just worked.

 

538 Analysis 0.png

Story:

The concept for the story comes from visually comparing these two games (and several others like them). As I followed the early rounds of the 2017 tournament and tracked the games via 538’s predictions site, it seemed, more often then not that Men’s tournament games were closer then the Women’s.

538 Analysis 1.png

As I continued to watch the tournaments and eyeball the difference in games between them, this seemed to often be the case. Once I was able to find the data for the 538 charts, I had pretty much sold myself on trying to do a comparison between the two tournaments to see what the actual numbers will tell us.

Viz:

After a few iterations, I realized that I needed to walk through how I was taking the detailed win prediction data and then aggregating it. This turned into the approach section at the top of the viz, shown below:

538 Analysis 2.png

Here we take a specific game's win probability by team and create four different views from this one set of data.

  1. A Line chart showing the two teams win probability throughout the game, a re-make of the 538 charts.
  2. Using Gantt bars to show the difference between the two win probabilities. Three easy steps in Tableau:
    1. Change the mark type to Gantt
    2. Remove the secondary axis pill
    3. Drag axis to size and change pill from team1_prob to –(team1_prob-team2_prob)
  3. Use a bar chart to show absolute difference with baseline at zero. Three steps:
    1. Change mark type to Bars
    2. Remove the secondary axis pill
    3. Change pill to ABS(team1_prob-team2_prob)
  4. Use a bar chart to show above transformed into close game index. One step:
    1. Change pill to 10-(10*ABS(team1_prob-team2_prob))

Bracket:

I wanted to take a look at seeding and how it potentially impacts how close games are. For example, the 1 seed vs 16 seed games will not be as closely contested as the 8 seed vs 9 seed games. I settled on trying to build a heat map view across the bracket, with seeding in tact. This would allow the user to follow seeding from the first round to the final four. For example, we can see the Women’s 1 seeded teams appear to dominate (e.g., close game index is very low) most of their games until the elite eight.

There are a lot of different ways you can go about building a bracket in Tableau and I am definitely not the first one to do it. For example, here is another March Madness viz that Corey Jones just shared a few days ago. With the bracket, one thing that came to me, it is a fixed ancestor tree. Each child has two parents, that is not going to change, two teams play, one loses, one wins. Back when I built my family tree in Tableau, I worked out the logic for the ancestor tree view. I could take that piece of work to create a bracket, then just map the results to the view. If I went that route (and didn’t change any formatting), the result would have looked like this.

Ultimately, I decided to go for a supporting tree structure that was closer to the brackets you are used to seeing (if you happen to follow either one of the tournaments). Here is where I landed with the bracket “heat map”.

This viz is not dynamic (but it could be!), it is built specifically for this bracket, with 32 nodes and the math was pre-calculated and node coordinates fed into Tableau. The main reason behind this? (1) It was easier to build it this way and (2) I don’t have any requirements to change this structure.

The bracket is a dual-axis with one axis for the bracket lines and a second for the hexagon points. The hexagon axis leverages an IF statement which only returns a value for nodes on the coordinates where we want them displayed. This field was also used to place the labels on the sheets above the brackets as well.

Trellis Panel:

You already know that I am a big fan of 538’s win probability line chart. I also wanted to have a chart for the teams scores as often the game was much closer in score than win probability. For example, you may have a heavy favorite down a few points early, but still have a win probability over 80% (with good reason). I think it is pretty interesting to compare the score of the game to the win prediction 538 calculated, thus really wanted to get the two graphs side by side.

Here I ran into some trouble with the data structure I have, trying to get the two graphs in my dynamic trellis and next to one another horizontally. This is the resulting view I came up with and below I walk through some steps on how to build it.

I realized when trying to force pills onto columns that I was going to need to do this all using a single pill. This is by no means a deal breaker, but does add some complexity. Then the same thing happened to me on the rows shelf, I realized I need to have a single scale for the two charts to work off.

For the columns issue, I took a page of out of Noah Salvaterra’s book from his Chord Diagram post. I decided to create an additional “copy” of the data (think union of your data), allowing me to create more layers in the single pill. Noah demonstrates having 5 layers in his post, I only need 2, so a much simpler piece of work for me. Here is an overview of how I got this to work and the corresponding formula below (hardcoded for now based on my specific y-axis scale, but doesn’t need to be).

Now that I have this done, I am left with the issue of rows needing to be on the same scale. For this I used percentage transformation (especially since win probability was already a percentage. The downside here is that you cannot show the axis to the user, you would either need to use mark labels or reference lines to assist with reading your graph. Upside is that vastly different scales can be displayed next to each other using the same axis.

Here are the calculations I leveraged, the steps are:

  • Calculate the maximum game score for team 1 and team 2 across the whole data (via Fixed LOD).
  • Find the maximum value between the two results above.
  • Use that maximum value of the denominator for the percentage transformation
  • If we are in copy 1 then use probability, if copy 2 use score percent transformed.

One Big Improvement:

One of the things that bugs me about the view is that the reader has to scroll and transition themselves from one graph to another. This is a situation where a little animation could have gone a long way. Imagine the approach section as a single view with transitions from one step to the next, ultimately transitioning into the summary below… More to come… possibly...

Lastly, thanks to Anya A'Hearn and Corey Jones for the feedback they provided on iterations of the visualization below.

Building towards d3.js “plugins” for Tableau

This post is a follow up to my Vizception post from a few months back. We are still building off the technique described in detail within that effort. Here we will look at two additional implementations leveraging the capabilities available within d3.js (thank you Mike Bostock!).

The first of the two implementations looks at leveraging d3.js mapping projections. Tamas Foldi and I presented this example during a recent Think Data Thursday. Here we will leverage the referenced d3.js code and adapt it for use with our Tableau integration method. This will allow us to build choropleth maps in Tableau with access to the d3 projection library which provides just a few more options in addition to your standard Web Mercator (the Tableau default).

Let’s take a look at the example, and then we can go through some details of how to make it happen. You can modify the view by changing the parameters provided.

click on the image above to interact directly with the map projections example

click on the image above to interact directly with the map projections example

Here are a few tweaks and modifications I made to the initial Vizception code base to make this work. First things first, we need to modify our Tableau event listener to work off of parameter change instead of mark selection. Here is that line of code, we are now calling the function “onParmChange” each time the user changes a Tableau parameter.

Next, within the function we are calling, we are going to do one of two things depending on which parameter the user has changed. This is executed with an if statement and by calling different functions based on the parameter name.

Each of those functions will either transition the opacity of the choropleth or the map projection based on the user selection (named accordingly).

We put this together along with mapping the getData() call to the d3.js visualization and we can leverage d3 map projections within our Tableau dashboards.

While I have only touched on a few snippets, the entire code for this example has been published to Github here.

Still with me? Let’s get into the second example, leveraging d3-brush to filter a dashboard. This is the simplest implementation I have shared thus far. As a result, I was able to spend a little more time on the “plugin” aspect of the deliverable. Assuming these files have been saved onto your Tableau Server, these are the two things that a Tableau dashboard developer will need to do to leverage this technique (e.g., no more hard-coded field names).

  • Drag a webpage object on their view with the correct URL. (See the caveat below, but for now the size of this object should be ~975px width and 75px height.)
  • Create two parameters
    • “xAxisField” – The name of the Date field to display on the X-Axis (also used for date range filtering).
    • “yAxisField” – The name of the measure to display on the Y-Axis.
  • Caveat – This is still fixed in size, with more work it could be built completely responsive, etc. to make it adaptable in any size dashboard vs one that is fixed in size. 

Let’s take a look at the result and then get into some of the details. You can modify the view by moving, shrinking or expanding the brush component (grey rectangle) of the d3 visualization.

click on the image above to interact directly with the brush example

click on the image above to interact directly with the brush example

Let’s look at the calls where we leverage the Tableau parameters to drive the d3.js visualization. Here we call getParametersAsync() and then store the resulting array into the variable “parms”. We loop through the array and look for our two specified parameters and also store their corresponding values into variables. We will later reference these variables for all arrays and manipulation associated with our getData() call at the bottom of the code snippet below.

Let’s also look at the modified “brushed” function from the d3.js code referenced above. We have changed this to leverage the Tableau JS API and apply the appropriate filter to the sheets in our dashboard upon being called. Here we leverage the applyRangeFilterAsync() call to apply the min/max date values of the brush to our dashboard.

While I have only touched on a few snippets, the entire code for this example has been published to Github here.

As you can see, we are inching closer and closer to this code being a stand alone plugin on Tableau Server. As I said in the Vizception post, I am really excited about all the possibilities this can open up and firmly believe that we are just scratching the surface with the above examples.

Telling a Story in Tableau

This short post is around trying to create an article like structure with in-line visualizations all within Tableau. Inspiration for this pulls from sites like 538 and polygraph as well as several authors from the Tableau Public community (like the one noted below, this recent VotD).

There have been many examples across the Tableau Public community showing the data storytelling capabilities of Tableau. These include leveraging additional JS libraries (via API/embed) like reveal.js (thank you Jeff Shaffer!), but others that caught my eye recently where examples of building out an entire story in a long form Tableau dashboard. Here is one example that Rob Radburn posted recently that got me thinking. Note: there are several others, this one by Rob is just a single recent example. 

I decided to see just how much work it is to do something like this, all within Tableau. The answer... not all that much. Like every tool, Tableau makes some hard things easy and some easy things hard. This type of visualization is a great example of the former and demonstrates the creativity that Tableau can empower it's Desktop users with. The viz story is just a simple collection of visualization sheets and text boxes, you can download the workbook to see how I went about laying out the story. The viz below is best viewed in landscape, hope you like it! 

3D "Printing" in Mapbox, Alteryx, and Tableau: "I've got big balls!"

3D "Printing" in Mapbox, Alteryx, and Tableau:  "I've got big balls!"

While starting to work on a new viz project, I came up with the idea to create empathy by putting the user inside of a 3D map with the data happening around them like a virtual reality movie.  Yes, the DataBlick crazy-town express train is starting to chug out of the station again.  This post shows some of my initial explorations into jumping in a viz.

Read More

Rose Curves in Tableau

Rose Curves in Tableau

I love when people get creative and come up with visuals like these, if you want to see more, check out Shirley Wu’s project with Nadieh Bremer at datasketch.es for starters. Techniques like these (or using things like the rose curve) to encode data will definitely require a more engaged user base. Readers will need to take some time to understand what each rose petal/shape is and then it will take them time to compare the petals across the visual. This type of technique is probably not the best choice to visualize your data when granular differences between your marks need to be analyzed by your reader.

Read More

Sensor vs. Simulated IED: Max's Science Fair Project using Tableau for Image Analysis

Sensor vs. Simulated IED:  Max's Science Fair Project using Tableau for Image Analysis

This is a post by Max, Anya's 12-year-old son.  It was his Science / Engineering Fair project where he used Tableau to visualize his results.  Thank you, Adam McCann and Merlijn Buit for your posts on color analysis that were used by Max for this project.

Each year many people die of bombs and other explosive devices. Some examples are the Boston Marathon and the recent bombing in Manhattan. In many modern wars, thousands of soldiers die due to IEDs (Improvised Explosive Devices). In my project, I will use an infrared sensor to find a cell phone (in place of an IED) in different temperature environments. Judging by how easy it is to see the cell phone, we can tell where infrared would work best, as well as where it would not work.  Using this information we can know when to use infrared sensors to save lives.

Read More

The 3D Tableau Full Monty

The 3D Tableau Full Monty

Recently DataBlick had a client project dealing with analyzing parts on a car during manufacturing and transport, and the client wanted something like Noah's Tesla.  We all want a Tesla, right?  Well, now you can have one (in Tableau at least).  In this post, I'll walk you through how to find a 3D model and get it into Tableau.  The next post will show how to trick it out a little bit as well as "explode" parts in a 3D tool before bringing them into Tableau so you can highlight and interact with them on your dashboard.

Read More

X, Y and a bit of Z - Cheater 3D Orthographic Views & Making everything "Spatial"

X, Y and a bit of Z - Cheater 3D Orthographic Views & Making everything "Spatial"

Anya must have pinged me 10 times over the course of the last week asking me questions about rendering 3d cars in Tableau. I figured it must have something to do with curing malaria. My reply was a bit ironic given the fact that I’ve done my own 3d car. I did it for fun though… I don’t like being told I can’t do stuff. it just doesn’t work as part of a production workbook. Well… from a performance standpoint maybe we will get there soon. But for now my suggestion was to pick a good angle and then drive a steamroller over it and just make it into polygons. I really should have seen the next question coming, but she asked how to do that. I was stumped. My best idea was, hire a graphic artist to trace it for you…

Last night she told me she solved it using QGIS… mind explosion! Of course! Why not use mapping software for this? Geography isn’t the only thing spatial. Why shouldn’t you use QGIS to map your car, your plane, the shelves of your supermarket, what have you. I always thought background images were misplaced in Tableau, I wonder if this is what they were thinking when they put it under maps. Latitude and Longitude are just a special name for x and y (or is it the other way around?). Why not hijack Tableau’s mapping capabilities and import your polygons as custom shapes?

I’ve gone to great lengths to hack multiple layers onto maps, so I was excited to hear multi-layered maps will be coming to Tableau, but this opens the door to hacking that feature into all sorts of things. Someone once told me that everything in Tableau is a scatterplot but I’m starting to think maybe everything should be a map. Oh… I am going to crash that Beta so hard!

Read More

#Data16 Twitter Network Project

#Data16 Twitter Network Project

For this year’s conference I undertook a project with Keith Helfrich to harvest tweets tagged with #data16.  We collected the tweets regularly throughout the week, and updated a view of high level summaries and detailed network visualizations.  This post details some of the highs and lows that we came across, and provides access to the workbook so you can do your own analysis and review as well. Please also be sure to check out Keith’s post on the same subject here.

Read More

On the topic of community: & being friends and mentors.

On the topic of community:  & being friends and mentors.

First - sign up and sign up for Emily Kunde's Mentor Match program, and have a chance to win an hour of help with either Allan or Anya as well as other prizes to be announced on Emily's site soon.  

This friendship started with a Tweet:  March 5th, 2014 Tweet to @AllanWalkerIT help…..!  ? "Since you are the king of Tableau Maps, I wanted to see if you had any suggestions?"  For over two years now, we have worked together on many collaborations.   We hope with a quick review of how we have expanded our skills by working together, you can learn from our take-aways and find friends and mentors to work with. 

Read More

Vizception: Viz in a viz & native d3.js integration on Tableau Server

Vizception: Viz in a viz & native d3.js integration on Tableau Server

We wanted to show a real example of how to bring more to Tableau Server without additional hardware or hosting needed. That’s right, no additional server purchase requisition requests needed. There are really too many use cases to count when it comes to this, the details herein are only the tip of the iceberg.

We had a few short discussions and landed on the following example. This includes not only native d3.js integration but also an example of viz in a viz (in a viz) on Tableau Server. As a starting point, we used the twitter network graphs that Keith Helfrich and I recently shared, which were showcased on the Tableau bloglast month.

Read More