Can you visualise and measure distance travelled?

Kyle took inspiration from the 2026 FIFA World Cup for this week’s challenge, looking at how many miles each team need to travel between their base camp and the stadiums where their group matches are being held. He sourced some data which he provided for download.

Modelling the data

The data provided contained 3 sheets. Kyle gave some hints on how he’d used the data, but nothing specific, so I just related the sheets in the following way, to see whether this would be enough.

I related Schedule to Base Camp, but BEFORE I applied the relationship join condition, I pivoted the Schedule data (as Kyle had hinted this may be required). I did this by

  • Adding Base Camp to canvas
  • Then adding Schedule to canvas
  • Then clicking on the Team A and Team B columns in Schedule, and selecting Pivot
  • The renamed Pivot Names field heading to Team A | B
  • and renamed Pivot Values field heading to Team1 (I couldn’t call it Team as this field already exists in Base Camp)
  • I then created a relationship between Base Camp.Team and Schedule.Team1

The add Venues to the canvas a relate to Schedule on the Venue field.

Creating the Map with all locations

For the maps we need to work with spatial data, and need to define the location of each base camp and each venue. The data sets had longitude and latitude fields for both types of location, but for some reason, both the longitude fields were resolving as string fields. So I had to change these to geographic fields by the following steps

  • right click Base Camp > Longitude, and change data type > number (decimal)
  • then right click field again , geographic role > latitude
  • repeat same 2 steps for the Venues > Laitude (Venues) field.

Once done create fields

Base Location

MAKEPOINT([Latitude],[Longitude])

and

Venue Location

MAKEPOINT([Latitude (Venues)],[Longitude (Venues)])

Then create

Line

MAKELINE([Base Location],[Venue Location])

and then

Distance – Base to Venue

DISTANCE([Base Location], [Venue Location],’mi’)

On a new sheet, add Venue Location to Detail, and Venue to Detail. Change the mark type to circle. Adjust the map background layers so only the Base, County/Region Names and State/Province border options are selected (Map menu > background layers)

Create a parameter to store the name of the selected team we want to focus the data for

pTeam

string parameter defaulted to ‘Austria’

Create a field

Is Selected Team?

Team = [pTeam]

Add this to Colour and Size and adjust accordingly. Make sure the ‘true’ is listed first so that the marks for the selected team are ‘on top’ . This will require the Size to ‘be reversed’

Remove all text from the Tooltip

Drag Base Location onto the display and drop it when ‘Add a Marks Layer’ option appears, which will create a 2nd marks card

Drag this card to be beneath the Venues one. Change the mark type to circle. Add Team to Detail. Add Is Selected Team to Colour and Size. Add Training Site and City to Tooltip and update accordingly.

Then click on the context menu of the Venues marks card, and disable selection

Nowt drag Line on to the canvas to make another marks layer. Again move this marks card to the bottom of the list, so it’s beneath the Base Camp marks card. Add Team to Detail and Is Selected Team to Colour. Create a copy of Is Selected Team (right click field and duplicate to create Is Selected Team (copy)) and add this to Size and adjust. I found I needed a copy so I could have different sizes between the circles and the lines Add Training Site and Distance to Tooltip and update the Tooltip accordingly. Remove row & column dividers.

Creating the ‘Team specific’ map

The easiest way I found to do this initially, was just to duplicate the sheet with the above map, and then add Is Selected Team to the Filter shelf, and set to True. This gives us the display we need, but tooltips need changing.

Re-enable the Venues marks card. We’ll need to display information about the match on the venues tooltip, wihich includes details for the teams playing.

As we initially pivoted the data, this information is now across 2 rows, so we need to create fields to capture both the teams on each row. I used FIXED LoDs for this:

Team A

{FIXED [Match]:MIN(IF [Team A | B]=’Team A’ THEN [Team_1] END)}

Team B

{FIXED [Match]:MIN(IF [Team A | B]=’Team B’ THEN [Team_1] END)}

Add these to Tooltip, along with Training Site, Date, Time (Local) and Distance. Format the Date field to “Month, Day Year” format, and custom format the Time (Local) field to h:nn AMPM. The adjust tooltip to suit.

Now do similar to the Line marks card – add Match to the Detail shelf as a blue disaggregated discrete pill, and then add Team A, Team B, Venue, Date and Time(Local) to the Tooltip and update accordingly.

Create the Bar Chart

On a new sheet, add Is Selected Team and Team to Rows and Distance to Columns. Sort descending. Order so Is Selected Team : True is listed first.

Make the rows a little wider. Add Is Selected Team to Colour. Add Team to Label. Adjust Label so the team name is aligned left and coloured in white bold text. Adjust the Tooltip. Add a Reference line to the Distance axis to show per cell the value of the sum of the distance. Don’t show line or tooltip.

Format the reference line, so the numbers are aligned in bold font, middle right

Hide the Is Selected Team, Team and Distance headers & axis (right click pill > uncheck show header). Then remove all row/column dividers and gridline, axis rulers etc.

Finally create 2 fields

True

TRUE

False

FALSE

and add these to the Detail shelf (we’ll need them later to ensure the bar doesn’t highlight when we select values).

Creating the match cards

On a new sheet, add Is Selected Team to Filter and set to true.

We need to identify which match is match 1st, 2nd and 3rd. I did this using the dates, but in hindsight could have used the Match field which just contains an unique number per match… anyway…

Match 1 Date

{FIXED [Team_1] : MIN(Date)}

Match 3 Date

{FIXED [Team_1] : MAX(Date)}

Match No for Team

IF [Date] = [Match 1 Date] THEN ‘Match 1’
ELSEIF [Date] = [Match 3 Date] THEN ‘Match 3’
ELSE ‘Match 2’
END

Add Match No for Team to Filter and set to Match 1.

Chang the mark type to shape and set to use a transparent shape (see here for more details on this). Then add Match No for Team, Match, Venue, City (Venues), Distance, Date and Time (Local) to Label. Format the date and time field as you did above.

Create a field

Opponent

IIF([Team_1]=[Team A],[Team B],[Team A])

and add this to Label too. Then adjust the label as required, and align middle left. Don’t show tooltips.

Duplicate this sheet and change the filter to select Match 2 for match 2, and then repeat for Match 3 so you have 3 separate sheets for the matches.

Creating the ‘team’ sheet

On a new sheet, add Is Selected Team to Filter and set to True. Set the mark type to shape and use a transparent shape. Add Team, Distance, Training Site and City to Label and adjust and format accordingly, aligning left middle. Don’t show tooltips.

Building the dashboard and adding the interactivity

I set the background of the dashboard to dark grey and then used layout containers to organise the content, using padding and rounded corners to style as required. The layout of my dashboard is pictured below. It will take some time to get this layout just right, and you might find that in Desktop some text doesn’t display but will when published on Public.

Add a parameter dashboard action to change the team when the bar chart is clicked on

Set Team

on select of the bar chart sheet, set the pTeam parameter with the value from the Team field.

To prevent the selected bar from being ‘highlighted’ when clicked, add a dashboard filter action

Deselect Bar

On select of the bar chart on the dashboard, target the bar chart sheet directly, setting fields true = false.

And that should be it.! My published viz is here

Happy vizzin’!

Donna

Can you create a double-sided multi-row Stem-and-Leaf Plot?

After a couple of weeks off due to holiday, it was my turn to set the challenge. When browsing around for inspiration, I came across this stem & leaf Power BI WOW challenge by Meagan Longoria, which in turn was inspired by a Tableau WOW challenge set by Yusuke in 2024.

So I thought it would be fun to go ‘full circle’ and see if I could recreate Meagan’s challenge in Tableau, which builds on Yusuke’s challenge, as this requires the ‘leaves’ to be spread across multiple rows.

Defining the calculations

The data set provided contains a rows uniquely identified by a Row ID, and each row defines a Species of Iris and the Petal length, which is a decimal number in cm.

To build the stem and leaf chart, we need to first identify the Stem and then the Leaf. If the length is 4.6cm for example, then the stem is 4 and the leaf is 6.

Stem

INT([Petal length (cm)])

Format this to a number with 0 dp and move to the ‘dimensions’ section of the data pane (above the line).

Leaf

INT(ROUND(([Petal length (cm)] – [Stem])*10,0))

Again, format this to a number with 0 dp and move to the ‘dimensions’ section of the data pane (above the line).

Note – Originally my function was INT(([Petal length (cm)] – [Stem])*10), but I found in some occasions this wasn’t given me the right values eg 4.1 was reporting a Leaf of 0, due to the precision of the original number stored. Using the ROUND function to convert the number to have 0 dp resolved this.

Put all these fields into a table like below, so we can start to sense check the other calculations we’ll need.

The final chart will plot the ‘leaves’ as points on an X and Y axis. The central ‘spine’ of the chart is where X=0, and the leaves are the plotted with the position based on the Stem value and then which row and column the leaf is in. Records associated to the Iris-versicolor Species will be plotted on the left side (negatives) while the Iris-virginica Species will be plotted to the right (positives).

The leaves need to organised into rows of 10 per Stem, per Species, sorted by the Leaf value (smallest first). To manage this, we first need to understand how many leaves are associated with each Stem and Species, and give them a ‘counter’ (ie index) per Stem/Species cohort.

Leaf Index per Stem

/*
For each stem per species, index the leaves from 1 to however many there are in the cohort.
*/

INDEX()

Add this into the table, and adjust the table calculation so it is computing by Leaf and Row ID only and add a Custom Sort by Leaf ascending

We now want to identify which ‘row’ (per stem) the leaf will sit on based on it’s index number. If there’s more than 10 leaves per stem, then we need to plot on multiple rows, where the row count starts at 1. Dividing Leaf Index per Stem by 10 will help us do this, but as all leaves indexed from 1-10 need to be on the 1st row, we need to subtract 1 from the index before we divide. We can then convert to a whole number with the INT function, but as we want rows to start at 1, we then need to increment.

Leaf Row Number

INT(([Leaf Index per Stem]-1)/10) + 1

Eg

Leaf Index = 4 -> subtract 1 = 3 -> divide by 10 = 0.3 -> apply INT function = 0 -> add 1 = row 1

Leaf Index = 10 -> subtract 1 = 9 -> divide by 10 = 0.9 -> apply INT function = 0 -> add 1 = row 1

Leaf Index = 11 -> subtract 1 = 10 -> divide by 10 = 1.0 -> apply INT function = 1 -> add 1 = row 2

Add this into the table and apply/verify the table calculation settings are as above.

We then want to identify which column each leaf should be in, which should be a number between 1 and 10 for Iris-virginica and -1 to -10 for Iris-versicolor. We can use the modulo (%10) function for this, based on the Leaf Index per Stem value, to find the remainder if the index is divided by 10. Similarly to before, as all leaves indexed from 1-10 need to be in the equivalent numbered column, we first need to subtract 1 from the index before we find the remainder, but then we need to add 1 to the final result, to get the desired result.

Leaf Column Number

(([Leaf Index per Stem] -1)%10)+1

Eg

Leaf Index = 4 -> subtract 1 = 3 -> %10 =3 -> add 1 = column 4

Leaf Index = 10 -> subtract 1 = 9 -> %10 = 9 -> add 1 = column 10

Leaf Index = 11 -> subtract 1 = 10 -> %10 = 0 -> add 1 = column 1


Add this into the table and apply/verify the table calculation settings are as above.

Now we know the Stem and the leaf row and column position, we can define the actual X and Y points for each leaf.

X Axis

FLOAT(IIF(MIN([Species])=’Iris-versicolor’, -1 * [Leaf Column Number], [Leaf Column Number]))

This is essentially just taking the Leaf Column Number and making it negative for the Iris-versicolor Species. We’ve wrapped it in a FLOAT to make the number decimal, as we need the axis to be able to handle decimal values later on.

For the Y Axis, we’re going to plot the leaves on rows at intervals of 0.2 related to the stem position

Y Axis

MIN([Stem]) + (0.2 * [Leaf Row Number])

Add these into the table and apply/verify the table calculation settings are as above.

Building the viz

Now we have the core data we need, we can start to build the viz

On a new sheet, add Species, Row ID, Stem and Leaf to Detail. Then add X Axis to Columns and Y Axis to Rows. Adjust the tableau calculation settings as before (remembering to apply the custom sort too!)

Change the mark type to circle. Add Species to Colour and adjust as required, adding a coloured border. Set the sheet to Entire View. Increase the Size a bit, then move Leaf from Detail to Text. Align middle centre and bold and allow labels to overlap. Reverse the Y Axis.

Fix the Y-Axis from 2.5 to 7 and set the tick marks to occur at intervals of 1.

Format Petal length (cm) to be a number with 1 dp, then add to Tooltip and adjust accordingly.

Set the background of the worksheet to pale blue. Remove column gridlines. Set the row gridlines to be a pale blue. Remove zero lines, axis rules & tick marks.

To plot the Stem value, double click into the Columns and manually type MIN(0.0) to create a second axis. Remove all the fields except Stem from the marks card of this axis. Change the mark type to shape and use a transparent shape. Move Stem onto Text and align middle centre and increase font size and make it bold. Clear all the text from the Tooltip associated to this mark.

Make the chart dual axis and synchronise the axis. Then add a Reference Band to the X-Axis which plots at -0.5 to 0.5, formatted with a blue line and a pale yellow fill.

Finally, hide all the axes (uncheck show header) and remove row & column dividers.

Add to a dashboard, using containers to organise the content. Use a horizontal container above the main viz to add text fields to label the parts of the chart. Ensure the chart specific title, the label headings and the chart itself are in a vertical container which can then have formatting applied (border/ curved edges etc). My dashboard item hierarchy is shown below

My published viz is here.

Happy vizzin’!

Donna

Can you use layout containers

Lorna wanted us to practice layout containers this and also sprinkled in a bit of new functionality – rounded corners! As a result you’ll need to use Tableau Desktop v2026.1 to complete this challenge.

Lorna provided a starter workbook with all the required sheets – we had to build the dashboard.

Describing how to do this is tricky, so I’m going to show a picture of my item hierarchy, and then describe some key points.

Lorna challenged us to use no more than 11 containers. I have 12 as I’ve included my standard ‘footer’ in a horizontal container, which isn’t part of the solution. When working with containers, it’s often useful to add blank objects as placeholders to help ensure the layout. and while you add and position the actual objects. The blank objects then get deleted. Padding is very helpful to reposition objects and add whitespace, but getting the values right can take a bit of trial and error and lots of tweaking.

I have renamed all the containers and numbered them, so you can see the number there are. I’ve named them with an ‘h’ or ‘v’ prefix depending on whether the container is vertical or horizontal.

When dealing with tricky layouts, I always start with a floating container that is positioned at point 0,0 and has the height and width of the dashboard. In this case, this is the container labelled 1.vBase. When I add other containers/objects into this base container, they are set to be tiled. I remove the automatic ’tiled’ container that exists initially, and if any reappear as I’m adding objects, I delete them too.

To generate the bordered shadow effect around the Superstore Overview title, the 2.hHeader container has the following properties:

  • no border
  • background set to light grey
  • corners set to a radius of 5
  • outer padding all 0
  • inner padding all 0

The Superstore Overview title Text object that sits inside this container, then has the following properties

  • no border
  • background set to white
  • corner radius all 0
  • outer padding: left 5, top, bottom, right all 2
  • inner padding all 15

A similar principal is applied to the 11.hRightPane container and the Scatter plot object contained within. The 11.hRightPane container does additionally have a left outer padding of 5 and a bottom padding of 10.

The 4.vLeftPane container just has a right outer padding of 5. This along with the 5 left outer padding of the 11.hRightPane container above gives the 10 pixel spacing between the 2 columns of data in the main body of the chart. There will ultimately be 3 ‘KPI’ rows within this container, so the 4.vLeftPane should be set to distribute contents evenly (only apply once you’ve built all the rows as described below).

Each KPI ‘row’ is constructed in the following manner; I’ll describe the top row, but just repeat for the other rows:

5.hTopKPI-Outer has the following properties

  • no border
  • background of light grey
  • corner radius of 5 all round
  • outer padding all 0
  • inner padding all 0

The 6.hKPI-Inner then has the properties

  • no border
  • background is white
  • corner radius all 0
  • outer padding: left 5, top, bottom, right all 2
  • inner padding all 0

Having the 2 horizontal containers set up this way creates the bordered, shadowed effect.

The Total Sales CY vs PY sheet is then set to a fixed width of 140 and inner padding all round of 10.

The Sales % Change sheet is then set with a fixed width of 130, corner radius of 20 all round, and outer padding of left 15, top 80, right 15 and bottom 20. Note, I also reduced the label text on the sheet itself from 20 to 15 pt.

Finally the Sales over Time sheet is set to have inner padding of 15 all round.

Hopefully all this helps, though as mentioned, I can imagine they’ll be a bit of fiddling to get things right. My published viz is here.

Happy vizzin’!

Donna