I’ve remembered this conversation when I was working on this week’s #makeovermonday about the Digital Economy and Society Index in the European Union (click to play with the interactive version on Tableau Public):

When I was working on this viz I had to admit to myself that LODs couldn’t do for me what I needed to execute my idea for this viz.

I had the idea of a small multiple radar chart in a grid map and wanted to use the technique Ellen Blackburn described in her blogpost. For the European grid map I once more used the technique I described in one of my previous blogposts (*“Get rid of the grid”*).

While it is hard to compare the different radar charts over countries I had the idea to incorporate a reference radar chart which can be selected by using a parameter. With this reference radar chart I would be able to compare all five indicators at once and the regional pattern (notice how much more yellow there is in southern and south-eastern countries when using one of top countries like Denmark) would become even clearer.

To be able to plot the reference radar chart I doubled the data (*I eventually even tripled the data to bring in the reference rings in the third layer, but that’s not relevant for my main problem here*) and brought in a field [Layer] to identify each copy of my data.

My x,y-coordinates were finally calculated like this (*I calculated x & y in these formulas like Ellen described in her blogpost using relative scores*):

For the radar charts:

For the circles on my second axis:

So again: my idea for the second layer was to create a reference radar chart that can be selected by using a parameter.

My first impulse was to use a fixed-LOD:

But this lead me to the following values (*I reduced the number of countries only for this example*):

Notice the values in the last column: my fixed-LOD is fixing the values for the selected country (Denmark) but is averaging the values for all other countries for each indicator. This is not what I needed. *(If anybody knows a way to achieve this with LODs, please let me know!)*

So I had to try it with table calculations…

…resulting in these values (again look at the last column):

How nice! This calc is showing exactly what it should show: the value of the first country for each indicator.

So I just had to bring my selected country to the top of this table by using this calculation for sorting.

Best thing: this sorting-calc can be incorporated directly into the table calculation (*I have never used this feature before!*):

Now I have the values from the selected country for all countries and each indicator! That’s it!

Think I might start using table calculations more often.

Thanks Ann!

]]>

Then rebuild my kinked bar chart!

Interactive Version: Tableau Public

]]>The “normal” way to create such a small multiple chart is to blend the data with a secondary data source for the geographical coding (I used Matt Chambers hex map file) and to put columns on columns and rows on rows. Quite easy.

Unfortunately you can’t make a hex map out of this because Tableau doesn’t allow your shapes to leave the borders of the cells within the grid. So this might be the closest hex mapish thing you can achieve using this technique:

Looks not even close like a proper hex map. So how can this be achieved?

The answer is: *Get rid of the grid! *

And this takes just a few steps:

The first step I did was to join the #makeovermonday-data with my hex map data.

I needed some calculations on my x-axis, therefore I first normalized the years from the data. This brought me a **1** for the first year in the data and a **16** for the last year.

Next step is to calculate the x-axis:

This calculation is “unstacking” my line charts horizontally. It is a similar technique like the one Ludovic and I used in our Boris Becker viz and described in this blogpost.

I added a parameter [Gap Column] to be able to play with the exact positioning of my charts at a later stage.

The same thing had to be done for the y-axis:

Again this calculation is unstacking the line charts, in this case vertically:

Looks nice!

For the hexagon shape I calculated one single point in the middle of each line chart…

…and brought this in on a secondary axis, created a dual axis, chose shape from the marks card, and changed the shape to a hexagon.

Last step was the positioning of the line charts using my parameters:

That’s it! (+labelling, formatting, tooltips, reference lines etc.)

Hope you enjoyed reading and that you’ll find own use cases for this!

]]>The first step to create such bump trees is to build the tournament trees. In this post we want to share the steps and the process we went through to do this.

For our visualization we used Jeff Sackmann’s huge database (find the data here).

Let’s have a look at the data and at one randomly chosen tournament:

Most tennis tournaments are organized as **single-elimination tournaments**.

What does this mean?

Look at the draw_size in column D: it is 32, meaning that there are 32 players in the tournament. Then look at match_num in column G: the maximum match_num is 31. You need 31 matches to play-off 31 losers and the remaining lucky one who wins the tournament. This rule is valid for all draw-sizes.

To create our tournament trees we first needed to do some data prep. Notice in the data, that each record has a winner and a loser. In our tournament tree we wanted to display both player types individually, therefore we had to pivot the data and got a field [Player Type]. Based on [Player Type] we were then able to calculate a [Player Id] and a [Player Name].

We also densified the data to get curved lines in our trees using this model:

This step added the field [Position Type] to our data and plotted 49 points for each record to get enough points to plot the shape of the curve.

That means for example: after data prep we had for each draw size 128 tournament the following number of records:

127 x 2 (Player Type) x 49 (Position Type) = 12,446 records

When we started working on the model to calculate the tournament trees, we quite soon realized that the whole flow and every position for every player id was in the match_num.

The challenge was to convert this first draft into a scalable algorithm.

And that’s the result:

So let’s walk through this model step by step:

First of all, the positioning is depending on the different rounds of a tournament:

To calculate [Round Id] you first need the total number of rounds [Nb Round].

In a single-elimination and exponential tournament structure the number of games per round grows exponentially: 1 game in the final, 2 games in the semis, 4 games in the quarter-finals, etc. That’s why you can use the logarithm to calculate [Nb Round].

*In a 128 draw size e. g.: 127 (max. Match Num) + 1 = 128 players => 2^7 => 7 rounds.*

The [Round Id] for every match then can be calculated based on [Nb Rounds] and [Match Num].

We will need [Round Id] and [Nb Round] for the positioning on the x-axis and the y-axis.

The position of a player in the tree is depending on three factors, on [position.Round], [position.Match] and [position.Player].

[position.Round] can be calculated based on [Nb Round] and [Round ID]:

To calculate [position.Match] we first need a Match Id by round [Match ID.Round] that can be calculated based on [Match Num], [Nb Round], and [Round ID]:

This enabled us to calculate the position for each Match:

The positioning of a player is depending on the round where a match takes place. For the **first round** we can position the players randomly. Thus we chose the [Player Id] and built an if-statement calculating a 0 for the player with the lower Id and a 1 for the other.

The positioning of a player in the **next rounds** is determined by the positioning in the first round. This position can be taken from the [Match Num] by calculating the minimum [Match Num] for every player as [Min_Match Id.Player]:

To have a consistent tournament tree a player with a lower [Match Num] in the first round always has to come first.

Based on this we were finally able to calculate [position.Player]:

[position] finally is just the sum of [position.Round], [position.Match], and [position.Player].

Resulting in these exemplary values:

Based on [position], [position_next], and [Sigmoid] we were now able to calculate the Y-values for our tournament trees.

[position_next] is telling our two lines for each player of a match where to go:

Using ‘AVG’ lets the lines end centrally between the two players.

Last step to calculate the Y-values is to bring in the Sigmoid function:

Bringing it all together is calculating our Y-values.

Based on the [Round Id] and our [Position Type] (this densification thing) we can calculate the positioning on the x-axis.

If we had only [Position Type] on columns, our flows for the different rounds would all be stacked on top of each other:

To ‘unstack’ our flows, we have to multiply them by [Round Id] and by the amplitude between maximum and minimum [Position Type] which is 12 in our case (6 – (-6)):

We also added a parameter [Gap for Text] to bring in some space between the flows for our labels.

Here you can see densification at work:

That’s it! Works perfect for all 16/32/64/128 draw sizes in single-elimination & exponential tournaments!

We hope you enjoyed reading and find own use cases for this! You can find the workbook on Tableau Public.

*Ludovic & Klaus*

]]>

As a guest host you are allowed to select the dataset. Since I am a sucker for winter sports in general and alpine skiing in specific and I love both, going skiing by myself and watching alpine skiing on TV, I was very happy when I discovered the large FIS (Fédération Internationale de Ski) database at fis-ski.com.

In this database you can find results of all disciplines organized by the FIS. Due to my love for alpine skiing I eventually focused on this discipline only (*the database also includes cross-country skiing, ski jumping and other disciplines*) and scraped the data for all races of the **World Cup** since it was established in 1967. The World Cup is a series of races in different competitions (Downhill, Super G, Giant-Slalom, Slalom, Combined/Alpine Combined) where the best racer of a season wins a so-called Crystal Globe, a small Crystal Globe for the winner of a competition (e. g. Slalom) and a big Crystal Globe for the overall winner.

- The results for the above-mentioned races include durations in seconds (for example the total race-time or differences between the racers within a race). In Tableau you can transform this duration in a date time with the following simple formula:

*datetime([*duration*]/86400)*

You can then change the date format in the default properties to a custom format

*hm:ss.00*

to display for example a duration of*105.23 seconds*as a datetime like this:*01:45.23*

- If you want to focus on specific athletes make sure that you include all data for this athlete because there might be little differences in the spelling of an athlete’s name.
- The disciplines Combined/Alpine Combined haven’t been included yet, therefore you can’t calculate the big Crystal Globe winner at this moment.
- You can find the data on data.world (Link) or you can use the below mentioned workbook that includes the same data.

The vizzing challenge is to create a visualization based on this dataset. It’s up to you if you want to focus on a certain athlete, a certain season, a certain competition or certain nations, like I did in a visualization on alpine skiing at the Paralympic Winter Games earlier this year.

For those unfamiliar with alpine skiing and the FIS World Cup I’ve prepared a workbook on Tableau Public, that can be used to explore the data and to find stories in it.

Click the dashboards to play with the interactive version on Tableau Public.

*Number of events by discipline*

*Crystal Globe winners by season*

*Wins & Podiums*

*Results by race*

*Venues by Region*

I hope you will enjoy this challenge. If you have any questions don’t hesitate to shoot me a message here in the comments section or on Twitter.

Please publish your visualization(s) on data.world and on Twitter including the hashtag #sportsvizsunday and tagging me (@ProfDrKSchulte), Simon Beaumont (@SimonBeaumont04), Spencer Baucke (@JSBaucke) and James Smith (@sportschord) to get feedback.

*Happy vizzing!
Klaus*

They follow a very structured setup:

- Define criteria
- Weight criteria
- Assess alternatives based on the defined criteria (e. g. on a scale from 1-10)
- Calculate part-scores ( 2. x 3. )
- Calculate overall score ( ∑ 4. )

Now imagine a use case where your defined criteria from step 1 can be assessed in step 3 **based on data**:

- You want to calculate a customer score based on criteria like recency, frequency or monetary ratio (like in the RFM-Model)
- You want to build an investment portfolio on criteria like rating, fund volume, performance, etc.
- You search a location for a new plant or new markets to invest in based on economic data

The only thing left to do in this case is to weight the criteria (step 2) and to calculate the scores (step 4+5). And this is something that can be easily done in **Tableau**! Such a data-driven scoring-model is something I have already created in several real-world projects.

Let me explain you how to set it up based on my #makeovermonday visualization from week 09/2018 (*click the image to play with the interactive version on Tableau Public; I used the same approach in my winning #IronViz on the Big Mac Index*):

My analysis is searching for new markets in Africa to invest in based on the criteria *freedom to trade*, *legal system*, *regulation*, *size of government* and *sound money* (**step 1**). These criteria are taken from Fraser Institute’s World Economic Freedom Index (https://www.fraserinstitute.org/economic-freedom).

While Fraser Institute weights all criteria equally to calculate its world economic freedom index I wanted the user of my dashboard to play with the weight of the criteria to see how this affects their (in this case fictive) investment decision.

I therefore created five parameters (one for each criterion) like this one for the criterion *freedom to trade*:

This parameter can be used to evaluate the importance of a certain criterion from 0-10. (*There are also more advanced methods to weight criteria but I will not dwell on that in this blog post.*)

Based on these five parameters I was able to calculate a relative weight of a criterion; all relative weights sum up to 100%.

Then I created 5 BANs to show the relative weight of each criterion and showed the parameter control.

Users of the dashboard are now able to change the parameter resulting in different weights for the criteria and changing investment advices based on the weighted index from this formula:

So, just some basic math that leads to a nice **actionable** dashboard that will for sure put a smile on your audience’s faces

I hope you enjoyed reading and that you will find own use cases for this!

]]>What I like most about these challenges is that I have to stretch myself a lot. Yes, I’m still failing sometimes to implement all these evil tricks by Ann, Rody or Luke, but I really feel that I learn a lot. And there have already been cases, where I could take this new knowledge and create other/own use cases, like for example in last week’s post on synchronized scrolling or in this post on Dynamic Labeling & Axis Hierachies.

**So what’s the problem with labels and axis hierarchies?**

When you use for example a date on columns, Tableau allows the user of your dashboard to drill this date dimension up and down.

*Profit by Month:*

*Profit by Quarter:*

Now look at the axis label: For the case that you use a custom label (you changed the label of your axis by ‘edit axis’) Tableau isn’t able to change the label based on the selected hierarchy level anymore. It labels the axis “MONTH of Order Date” statically.

There is a way to deal with this problem by using parameters, like described in this blogpost found in the Tableau Community Forum by Rahul Singh.

In this post I want to share a way to label a viz by the chosen hierarchy level dynamically *without* using a parameter, meaning that it is still possible to use the little “+” and “-” for drilling.

This can be done in the axis label by using the default label, I used the sheet title to create this:

If you want to recreate this, these are the steps:

Basically it is just one calculated field/string calculation you need. To create this you have to explore your hierarchy first to know about the number of levels in your hierarchy. In my case I had year/quarter/month/week/day. Then I’m counting the number of elements on each hierarchy level by using the ‘datediff’ formula (I could have also used LODs to do the same) to compare the result with size(), that is counting the rows in my partition. I also wanted the hierarchy level to be displayed in capital letters, therefore I used the upper() formula.

Make sure that size() is computed in the right direction, in my case across the table.

All you have to do then is to insert this calculated field and the measure name (in this case a parameter) in your title!

That’s it!

Hope you enjoyed this post and that you will find use cases for this!

]]>When I was thinking about this new finding I remembered a discussion on twitter where some guys discussed their need for synchronized scrolling in multiple sheets on their business dashboards. There is also an idea in the Tableau Community Forum to implement this as a standard feature in upcoming Tableau versions with already lots of votes.

I used my new knowledge about the index-formula to create a workaround for such a synchronized scrolling like in this example (click to play with the interactive version on Tableau Public).

*(There are for sure better ways to visualize Sales and Profit, so please take this visualization just as an example.)*

If you have two or multiple tables or graphs with the same granularity (imo the only case where synchronized scrolling does make sense) und you feel the need for this, just implement the following few formulas in your viz:

and make them discrete.

Make sure that Index Columns is computed **across** the table and Index Row **down** the table.

Create two parameters like this one:

Note: It has to be a range-parameter to get the little arrows for controlling the parameter.

That’s the trick: with this custom scroll control you don’t actually scroll but filter rows and columns out of the viz.

Create two boolean calculations to filter the viz on Index Column and/or Index Rows:

Make again sure that the filter Index Columns is computed **across** the table and the filter Index Row is cumputed **down** the table. Both boolean calcs have to be ‘true’.

Create the dashboard. For the real look and feel make sure that your tables or vizzes have same widths and heights. I hid the headers for the index-dimensions and customized the parameter not showing the readout box.

That’s it.

A quite simple approach, I wouldn’t be surprised if it has been ‘invented’ before (but haven’t searched for it).

Hope you enjoyed reading and find use cases for this!

]]>With the ‘zoom in/out’-parameter on the left side you can vary the size of the bounding boxes and because of the automatic adjusting that tableau does with its maps it looks like you are zooming in and out. If I would fix the maps (see again last week’s post on bounding boxes) a change of the parameter would only change the size of the boxes in the view.

In this post I want to share the steps I went through to build this visualization.

I had the idea to look at centers of global capital cities, mainly because it is so easy in Tableau to identify the geographical centers:

- Import a list with country and city in Tableau
- Create a view with generated latitude and longitude
- Export the worksheet as a cross tab to Excel

As described in last week’s post it needs five points to draw a bounding box. Therefore, I quintupled the data and identified each partition as my point order. That’s all data preparation you need (and even this step could have been done in Tableau).

I could then construct my bounding box around my city centers with ∆ lon as width, ∆ lat as height and some basic math:

But then it got tricky. An early version of my viz looked something like this:

All boxes are sized differently. What is going on here?

I’m not a spatial expert and it took me some time to figure it out. As described in 3. I wanted to add or subtract a lat/lon to my center lat/lon. Unfortunately, a distance expressed in lat/lon is depending on where you are located on the globe (therefore the different sizes of the boxes, the cities are spread around the world).

Source: Wikipedia

This is due to the distance between two longitudes. While the distance between two latitudes is (more or less) constant (111.12 km), the distance between to longitudes has its maximum amplitude at the equator (where it is also 111.12 km) and is zero at the poles.

The distance between two longitudes can be calculated like this:

Distance = 1 nautical mile * 60 * cos(Latitude)

*Distance at the equator = 1,852 m * 60 * cos(0) = 111,120 m (or 111.12 km) with cos(0)=1*

The distance at a latitude of 45 degrees would for example be

*1,852 m * 60 * cos(45) = 78,573.7 m *

That means: a distance expressed in longitude has different lengths around the globe, depending on the latitude. To kill this effect, I just had to normalize the ∆ lon with the cosine of the latitude which I calculated in Tableau with the following formula:

So far so good.

In an early version I was now able to create two parameters for height and width (expressed in lat and lon) and to draw the boxes, but then I felt it would be cool to have only one parameter expressing the size of the box (s) in square kilometer. Therefore I had to calculate height (x) and width (y) within Tableau.

To do so it needed the following two equations:

(1) s = x * y

(2) f = y/x *with f=format of the box (e. g. 16:9, 4:3 or 1:1)*

I could then calculate height and width in meter based on my parameters Square Kilometers, format and lat/lon per 100 m:

resulting in these two calculated fields:

The last step before creating the view was to calculate the longitudes and latitudes for each partition of my data.

For the latitudes:

For the longitudes:

To create the viz I went through similar steps like described in my previous post.

For the second axis I chose circles from the marks card to place my label with the following formula:

That’s it (+ a little bit of formatting)!

Hope you enjoyed this post and you’ll find own use cases for this technique!

]]>While I was happy to support such an amazing and important project I was also happy to work on my mapping skills because this #makeovermonday was all about mapping. Most of the work I put into this viz went into a tiny little part: an overview map which is highlighting the selected country with a so-called bounding box.

The basic idea of a bounding box is to identify the minimum and maximum longitude and latitude and connect these points with a rectangle.

I first identified the four min-/max-points out of the provided data but then realized that the resulting boxes were partly very small because of only few events in these countries. A quick google search led me to GitHub where I found the data for all countries.

I imported the data to excel and labeled the min/max longitude/latitude:

To draw a bounding box on my map it just needed to calculate the four corners of the rectangle (and a fifth to close the loop):

Well, that was quickly done in excel:

The rest was just bringing my bounding box data to Tableau, linking my bounding box data and the #makeovermonday data on ‘country’ in Tableau and creating the viz:

I set opacity to 20%.

I wanted to use a parameter to filter my countries in my detailed map, that’s why I used this parameter to filter my bounding boxes too.

A nice way to give orientation to the user of your dashboard.

I hope you enjoyed this post and you’ll find own use cases for bounding boxes!

Feedback would be highly appreciated!

]]>