Slicing odd colors - non-linear gradients in Tableau
Written by: András Szepesi
A case study of discovering a surprisingly useful hidden feature of gradient coloring in Tableau.
Tableau has a lot of coloring options, but even if you run out of them, there still might be some undiscovered territories.
I had to implement a traffic light system to indicate the performance of a few normalized metrics from 0% to 100%. Red below a certain percentage, then yellow for the middle part, then green above a certain higher percentage. Should not be an issue, a calculated field can do the trick: define the percentage thresholds in a calculation, throw it on color, there you go. However, I had to show multiple measures at the same time but unfortunately, Tableau won’t let you use [Measure Names]
or [Measure Values]
in calculated fields, so that won’t work.
[Measure Values]
and [Measure Names]
are not a real per se, they can’t be computed with. Tableau stares blankly at them with amnesia, and doesn’t care about where they come from, just sees the numbers themselves with no context, no memories. When Tableau refuses to calculate with them to do some coloring, you can try flipping the tables and use the colors to do the calculation instead.
Stepped Gradients
Since [Measure Values]
prohibits us from defining clear-cut categories for color coding, we can go a different route: use gradient coloring, usually used for continuous measures, but make them stepped in order to make them behave like categorical colors.
Gradient colors can be used with [Measure Values]
and the color will be calculated individually for each measure. Tableau even has a three-way ‘Temperature Diverging’ color scheme, which is perfect for the widely recognized red-yellow-green distinction of metrics. Paired with the ‘Stepped Color’ option I can turn my scorecards or charts into traffic lights. Stepped gradients are a great option when your measures have distinct thresholds defining the colors.
Stepped diverging color option solved some of my issues but in parallel created two new ones: I can’t change the color of the middle part and my red-yellow-green diverging color scheme must adhere to an even distribution, all of them are one third of the full width of the scale.
Custom Color Palettes
I can solve the first new issue with a custom color palette and replace the yellow middle color with anything, using the color's hex code. Custom colors are a great time saving tool as well and you can set them up in a few minutes, fiddling with the Preferences.tps file. If you have never tried creating custom colors, Tableau official documentation has a great article about this. In my specific case, I have added the following to Preferences.tps:
<?xml version='1.0'?>
<workbook>
<preferences>
<color-palette name="Custom Traffic Light Diverging Palette" type="ordered-diverging">
<color>#c5192d</color>
<color>#f7b825</color>
<color>#689e18</color>
</color-palette>
</preferences>
</workbook>
Note: make sure you always add your custom colors between<preferences>
and</preferences>
otherwise you will run into an error when opening Tableau. Additionally, when messing with the Preferences.tps, you unfortunately have to close and restart Tableau for your modifications to take effect, because the file is read only once on opening the application. Additionally, also described in the Tableau article, there are different types of color palettes, we are using theordered-diverging
type in this specific scenario.
With our recent addition to the Preferences.tps file, we have added a new color palette to the bottom of the diverging colors drop-down list and named it ‘Custom Traffic Light Diverging Palette’. This way, all three colors were defined by us, and the two colors on the ends can still be overwritten from Tableau’s interface if you want to customize your custom colors further.
Smearing
Still some issues to solve in this specific case: my traffic lights should have 4 different colors and they should not be even. They ought to look like this:
- 0% to 40% - red
- 40% to 70% - yellow
- 70% to 90% - blue
- above 90% - green
We are not there yet, but getting close. Tableau interprets ‘diverging’ very loosely and you can actually define more than 3 or 4 colors and still use them as diverging colors. I can feed it the seven colors of a rainbow for example:
<color-palette name="Rainbow Palette" type="ordered-diverging">
<color>#e81416</color>
<color>#ffa500</color>
<color>#faeb36</color>
<color>#79c314</color>
<color>#487de7</color>
<color>#4b369d</color>
<color>#70369d</color>
</color-palette>
Pretty, but not exactly what we need right now. However, if I can feed so many colors to a custom diverging palette, how about repeating the same colors a few times, to mess with the evenness of the spectrum? Let’s add microwave frequencies for fun (under the visible and infrared spectrum) represented as black (since we can’t see them) to our extended rainbow, and we get this:
<color-palette name="Rainbow Palette (with added Microwaves)" type="ordered-diverging">
<color>#000000</color>
<color>#000000</color>
<color>#000000</color>
<color>#000000</color>
<color>#000000</color>
<color>#e81416</color>
<color>#ffa500</color>
<color>#faeb36</color>
<color>#79c314</color>
<color>#487de7</color>
<color>#4b369d</color>
<color>#70369d</color>
</color-palette>
We’ve created a stepped gradient, where we introduced this skewed ratio of colors which is now theoretically very close to what we need in our 0-40-70-90-100 ratioed extended traffic light. I can basically consider the individual color lines in my custom color palette as 10% wide blocks and build a non-linear custom stepped gradient by repeating the same hex codes for the same colors. Then I choose 10 as my stepped color count and I should be done. 4 red blocks, 3 yellow blocks, 2 blue blocks and a green box adds up to 40%, 30%, 20%, 10% to get into 10 steps and 100%, in short:
Slicing the Wrong Way the Right Way
The method above won’t actually work.
In practice, if you feed the colors in as described above and choose 10 steps at the ‘Edit Color’ settings, you will get this:
It’s almost there, but it’s clear that our reds and blues are bleeding into the yellows. Solving this issue gets a little esoteric, because I am just guessing and blindly reverse engineering how Tableau might work, but I am pretty sure this happens because of the way Tableau slices the colors when making the steps.
You might have noticed even when we attached the black part to the rainbow, the colors were a bit off. When Tableau is slicing the color steps (the lines of hex codes) you are feeding it, it will not put them in the same brackets as pictured above, and creating the stepped gradient will not be perfect. I think, it works like this:
The first and the last slices (or last steps) are not sliced, I believe. The first hex code you put in your custom color list will be the first color shown in your stepped gradient, and the same is true for the last step. There’s no arguing about what color the ends are. However, all the other steps will be sliced by Tableau and the actual color of the slice is decided on where the slicing falls exactly and what colors the fresh cuts have. If you have 10 colors in your custom color list and will use 10 steps in your ‘Edit Colors’ window, Tableau’s cutting tool will fall exactly between two colors and it will blend the two hex codes together on the two sides of your cut.
By supplying more colors than the number of slices, we can avoid cuts falling exactly on the touching colors. With this method, one of the colors will ‘win’ over the other and Tableau can make a distinct step out of it. Figure 8 shows that steps 5 and 7 are the ones where bleeding occurs, but it would seem more logical for 5 and 8 or 4 and 7 to bleed, if coloring happens from left to right or right to left. For this reason, probably the actual mechanics behind the curtains are different to my interpretation, but the method of oversupplying the ‘weak’ color which had other colors bleed into it seems to work anyway.
The final custom color is the following:
<color-palette name="Test Stepped Palette Off" type="ordered-diverging">
<color>#c5192d</color>
<color>#c5192d</color>
<color>#c5192d</color>
<color>#c5192d</color>
<color>#f7b825</color>
<color>#f7b825</color>
<color>#f7b825</color>
<color>#f7b825</color> //this line was added to oversupply the yellows
<color>#85b7da</color>
<color>#85b7da</color>
<color>#689e18</color>
</color-palette>
With 11 lines of hex codes, yellow oversupplied by one, then sliced to 10 steps, we miraculously get what we were looking for:
Cautions
The scenario described above is very limited yet I believe it is very useful. It lets you color measures without creating new calculated fields and creating coloring categories. You are able to use as many measures as source as you wish. In this case here, I could divide my 100% long ruler into 10 steps, because I did not need more granularity. If your thresholds can be divided into 5% steps, you might still be okay by using 20 hex codes in your Preferences.tps, but if your thresholds fall into width segments only dividable by 1 or less percent steps, adding 100 or 1000 hex codes can be very hard to keep track of and probably would not yield great results and you will most likely need some simple script to write them for you and then do the adjustments.
Known Limitations
- best used with a small number of different colors with simple ratios
- always opening and closing Tableau to edit the Preferences.tps is fiddly at best
- the oversupplying of the weak colors is not a clearly understood concept and might be hard to extrapolate from it
- step coloring on values which fall exactly on the border of two colors, the value will be put in the right side of the two colors, in other words, in our example above, a value of exactly 0.9 will be green, not blue, so color bin is like a half-closed interval
[start,end)
, meaning start point is included, end point is excluded from the interval - you don’t need to oversupply custom hex codes all the time for some reason if your slicing works for the first time. I do not know the reason for this, but my 11 lines of hex codes work seamlessly for 10 steps, but somehow work for 11 steps as well but won’t work for 9. For now, trial and error is the best method.
- if you supply
n
lines of colors, your theoretical limit for a non-bleeding stepped linear gradient isn
. Fromn+1
, you will approach a continuous color gradient more and more and stepping without color bleeding is not possible anymore. Stepped color gradients undern
is possible butn-1
seem to be the optimal step number without introducing bleeding. For 10 hex codes, it worked for 6 and 7 steps only, for 11 hex codes it worked for 10 and 11 steps. - I ran some basic tests and tried the 11 hex codes - 10 steps method with 3 (sliced in a 40-20-40 ratio) and 5 (sliced in a 10-20-30-20-20 ratio) fake color categories, oversupplying the middle color by one, and both worked fine.
This whole method is clearly a little wonky but used carefully under the right circumstances and with a bit of mathematical luck it can save you some computing power and headaches especially when using [Measure Values]
as your input.
Happy slicing!