Beautiful Bars: Scaled Gradient Fill on Bar Plots | by Brian Mattis | Jul, 2022


Using color to add meaning to your plots in matplotlib

Photo by Denise Chan on Unsplash

Bar plots are one of the most basic and useful ways to convey data to our audience. While there are more exciting plots like box plots, violin plots, and heat-maps, no plot is as universally understood by non-technical audiences like the bar plot.

On the flip-side, bar plots really are boring. They’re also very simplistic in that they don’t give the audience any intuition on whether the values shown are good, bad, or otherwise.

In this article, we’re going to start by spicing up the basic bar plot with gradient color fill to add a little flair. Then, we’re going to show you how to scale the gradient fill so that the individual bars don’t traverse the entire color range, naturally emphasizing the differences between values. After all, isn’t this usually the point we’re trying to convey with bar plots?

Finally, we’re going to see how to apply custom color maps where we can specifically define where the color changes, so we can illustrate where certain bars are indicating problems and further draw the audience’s eyes to the most important points. Let’s get started!

First, we’ll import the standard packages, as well as some ones specific to the gradient color maps we’ll be generating later on. Next, we’ll create a simple dataframe for our data, along with a very bland bar plot.

The most boring of bar plots… 😴

Now, simply changing the color of the bars isn’t hard ( ax.bar(df.a, df.b, color = 'orange') for example), but you didn’t come here for that, did you?

Basic Gradient Fill (for style, not substance)

To perform the fill, we going to create a basic bar plot and pass it into a custom function as a variable. From here, we’re going to pick it apart, bar by bar, and apply the ax.imshow() function to apply colormaps (cmaps for short).

One of the most challenging parts of using imshow() is setting up the first variable it needs (“X” in the documentation). Here, we want to progress through our selected color map linearly, so we’re going to create a linear array of 256 elements between 0 and 1 with np.linspace(). It’s important to note the .T in the linspace() code below — that sets up the gradient to be in the right orientation for a vertical gradient. Try taking it off and seeing what happens!

Next, we reestablish ax within the function so that we can extract the x and y limits of our total plot region. We extract those limits with get_xlim() and get_ylim(). Finally, we apply these with the ax.axis() function. Although it seems silly, these steps are necessary to tell matplotlib to not fill the entire plot area with our color map.

Finally, we step through each bar of our bar plot in a for loop. We first must set the bar’s facecolor() to “none”, otherwise the base color will be placed on top of the gradient fill we add. Alternatively, this line can be skipped if we increase the zorder in the imshow() function — but more on that later. We then extract the features of the bar, and then use imshow() to apply our gradient fill over that extent (the bar x, y coordinates).

Uniform gradient fill using default cmap

Advanced Gradient Fill

While the above plot certainly looks prettier, it certainly isn’t telling us anything about the data that we didn’t already know. When we’re showing bar plots, the highest points are usually more meaningful, good or bad. We really want to draw our audience’s eye to differences in the bar heights.

We can do this as a fairly simple upgrade to our previous function. Before we set the grad variable at the top, so all bars would traverse between 0 and 256 colors on the color map. To scale our colors, what we really want is for the largest bar to get the full color range, and the other bars to traverse a subset of that. To do this, we move the grad call into our bar for loop. Each time it is called, it generates an array of 256 numbers, but we modify the step size. So, for the largest bar, grad goes from 0 to 1 (with 256 steps), but for all other bars grad doesn’t make it to 1. The step size is scaled by the height of that particular bar ( h ), versus the height of the max bar ( max(ydata) ). To make this happen, you may have also noticed that we now pass in ydata as part of the function call. We’ve also passed in a cmap name, so we can choose our gradient cmap from the function call.

One more addition — in the imshow() function we have to turn off norm, otherwise it would undo our magic with grad and auto-scale it to be between 0 and 1 for all inputs.

We can try this with different color maps (cmaps) to see what best suits our data’s story:

Using ‘viridis’, ‘hot’ and ‘cool’ cmaps, respectively

In these plots we see that only the taller bars are able to reach certain colors. This helps drive our audience’s eye. The difference is subtle, but important. In the side-by-side comparison shown below, this new scaled gradient fill (left) only reaches into the purple color range on bars 3 and 5, giving them a higher gravity. In this case, we can make our audience think “is it bad if a bar gets to purple?”.

Comparing scaled gradient fill to unscaled gradient fill (Image by Author)

Refining The Plot

Before we share this plot with an audience, we need to do some general visual clean-up. We’re going to add grid lines as well as borders to our bars to keep them from blending into the background (since some colors maps can be pretty light). The only difference between this and traditional bar plots is that a little extra care has to be taken with zorder, which controls which elements are in-front of other elements. Since we do the bar coloring within a function, but after the bars are fundamentally generated, we add zorder like this:

Scaled gradients in ‘YlOrRd’
Scaled gradients in ‘viridis_r’

Fully Customized Gradients (extra credit)

Let’s get picky. What if we want our bars to change to a certain color at a certain value to better reflect when things need our audience’s attention. Do this, we need to construct custom color maps. I covered this in-depth in my last post, showing how to color maps work, and how to functionalize building color maps that transition between 3 colors. Even better, these functions enabled us to choose the colors, choose where the transitions happen, and how blended the transitions are. Rather than step through the code to make the cmaps shown below, I’ll jump to giving you a taste of how they can look on our gradient fill plots. I’ll use the same scaled gradient fill code above, but now just plug in custom cmaps.

In the code above, we choose to transition from the first to second color at 3.5 (with a blend of 1), and to transition to the third color at 5.5 (also with a blend of 1). The message we’re giving to our audience is that values above 3.5 should have some cause for concern and that values above 5.5 are outright dangerous. See if you get that same message just by looking at this plot:

3-level custom cmap applied to our bars

Summary

Bar plots are usually very vanilla, but we can use gradients fills to spice them up. Even better, we can use scaled gradients and custom scaled gradients to teach our audience how to interpret the data. The good news — you now have the tools to make beautiful (and meaningful!) bar plots. The bad news — standard bar plots will now look more plain and boring to you than ever before (scroll up to the first bar plot and cringe 😬).

Thanks for reading, and if you found this helpful, please follow me!

As always, the entire code walk-through notebook can be snagged from my github. Cheers, and happy coding out there.


Using color to add meaning to your plots in matplotlib

Photo by Denise Chan on Unsplash

Bar plots are one of the most basic and useful ways to convey data to our audience. While there are more exciting plots like box plots, violin plots, and heat-maps, no plot is as universally understood by non-technical audiences like the bar plot.

On the flip-side, bar plots really are boring. They’re also very simplistic in that they don’t give the audience any intuition on whether the values shown are good, bad, or otherwise.

In this article, we’re going to start by spicing up the basic bar plot with gradient color fill to add a little flair. Then, we’re going to show you how to scale the gradient fill so that the individual bars don’t traverse the entire color range, naturally emphasizing the differences between values. After all, isn’t this usually the point we’re trying to convey with bar plots?

Finally, we’re going to see how to apply custom color maps where we can specifically define where the color changes, so we can illustrate where certain bars are indicating problems and further draw the audience’s eyes to the most important points. Let’s get started!

First, we’ll import the standard packages, as well as some ones specific to the gradient color maps we’ll be generating later on. Next, we’ll create a simple dataframe for our data, along with a very bland bar plot.

The most boring of bar plots… 😴

Now, simply changing the color of the bars isn’t hard ( ax.bar(df.a, df.b, color = 'orange') for example), but you didn’t come here for that, did you?

Basic Gradient Fill (for style, not substance)

To perform the fill, we going to create a basic bar plot and pass it into a custom function as a variable. From here, we’re going to pick it apart, bar by bar, and apply the ax.imshow() function to apply colormaps (cmaps for short).

One of the most challenging parts of using imshow() is setting up the first variable it needs (“X” in the documentation). Here, we want to progress through our selected color map linearly, so we’re going to create a linear array of 256 elements between 0 and 1 with np.linspace(). It’s important to note the .T in the linspace() code below — that sets up the gradient to be in the right orientation for a vertical gradient. Try taking it off and seeing what happens!

Next, we reestablish ax within the function so that we can extract the x and y limits of our total plot region. We extract those limits with get_xlim() and get_ylim(). Finally, we apply these with the ax.axis() function. Although it seems silly, these steps are necessary to tell matplotlib to not fill the entire plot area with our color map.

Finally, we step through each bar of our bar plot in a for loop. We first must set the bar’s facecolor() to “none”, otherwise the base color will be placed on top of the gradient fill we add. Alternatively, this line can be skipped if we increase the zorder in the imshow() function — but more on that later. We then extract the features of the bar, and then use imshow() to apply our gradient fill over that extent (the bar x, y coordinates).

Uniform gradient fill using default cmap

Advanced Gradient Fill

While the above plot certainly looks prettier, it certainly isn’t telling us anything about the data that we didn’t already know. When we’re showing bar plots, the highest points are usually more meaningful, good or bad. We really want to draw our audience’s eye to differences in the bar heights.

We can do this as a fairly simple upgrade to our previous function. Before we set the grad variable at the top, so all bars would traverse between 0 and 256 colors on the color map. To scale our colors, what we really want is for the largest bar to get the full color range, and the other bars to traverse a subset of that. To do this, we move the grad call into our bar for loop. Each time it is called, it generates an array of 256 numbers, but we modify the step size. So, for the largest bar, grad goes from 0 to 1 (with 256 steps), but for all other bars grad doesn’t make it to 1. The step size is scaled by the height of that particular bar ( h ), versus the height of the max bar ( max(ydata) ). To make this happen, you may have also noticed that we now pass in ydata as part of the function call. We’ve also passed in a cmap name, so we can choose our gradient cmap from the function call.

One more addition — in the imshow() function we have to turn off norm, otherwise it would undo our magic with grad and auto-scale it to be between 0 and 1 for all inputs.

We can try this with different color maps (cmaps) to see what best suits our data’s story:

Using ‘viridis’, ‘hot’ and ‘cool’ cmaps, respectively

In these plots we see that only the taller bars are able to reach certain colors. This helps drive our audience’s eye. The difference is subtle, but important. In the side-by-side comparison shown below, this new scaled gradient fill (left) only reaches into the purple color range on bars 3 and 5, giving them a higher gravity. In this case, we can make our audience think “is it bad if a bar gets to purple?”.

Comparing scaled gradient fill to unscaled gradient fill (Image by Author)

Refining The Plot

Before we share this plot with an audience, we need to do some general visual clean-up. We’re going to add grid lines as well as borders to our bars to keep them from blending into the background (since some colors maps can be pretty light). The only difference between this and traditional bar plots is that a little extra care has to be taken with zorder, which controls which elements are in-front of other elements. Since we do the bar coloring within a function, but after the bars are fundamentally generated, we add zorder like this:

Scaled gradients in ‘YlOrRd’
Scaled gradients in ‘viridis_r’

Fully Customized Gradients (extra credit)

Let’s get picky. What if we want our bars to change to a certain color at a certain value to better reflect when things need our audience’s attention. Do this, we need to construct custom color maps. I covered this in-depth in my last post, showing how to color maps work, and how to functionalize building color maps that transition between 3 colors. Even better, these functions enabled us to choose the colors, choose where the transitions happen, and how blended the transitions are. Rather than step through the code to make the cmaps shown below, I’ll jump to giving you a taste of how they can look on our gradient fill plots. I’ll use the same scaled gradient fill code above, but now just plug in custom cmaps.

In the code above, we choose to transition from the first to second color at 3.5 (with a blend of 1), and to transition to the third color at 5.5 (also with a blend of 1). The message we’re giving to our audience is that values above 3.5 should have some cause for concern and that values above 5.5 are outright dangerous. See if you get that same message just by looking at this plot:

3-level custom cmap applied to our bars

Summary

Bar plots are usually very vanilla, but we can use gradients fills to spice them up. Even better, we can use scaled gradients and custom scaled gradients to teach our audience how to interpret the data. The good news — you now have the tools to make beautiful (and meaningful!) bar plots. The bad news — standard bar plots will now look more plain and boring to you than ever before (scroll up to the first bar plot and cringe 😬).

Thanks for reading, and if you found this helpful, please follow me!

As always, the entire code walk-through notebook can be snagged from my github. Cheers, and happy coding out there.

FOLLOW US ON GOOGLE NEWS

Read original article here

Denial of responsibility! Techno Blender is an automatic aggregator of the all world’s media. In each content, the hyperlink to the primary source is specified. All trademarks belong to their rightful owners, all materials to their authors. If you are the owner of the content and do not want us to publish your materials, please contact us by email – admin@technoblender.com. The content will be deleted within 24 hours.
artificial intelligencebarbarsBeautifulBrianfillGradientJullatest newsMattisPlotsScaledTechnology
Comments (0)
Add Comment