Stacked bar chart python

Stacked bar chart in matplotlib

Stacked bar charts represent the values which take different groups within other groups. For instance, consider that people living in five different cities (e.g., the groups, named ‘G1’ , ‘G2’ , ‘G3’ , ‘G4’ and ‘G5’ ) answered Yes or No to one question and the results (the count of Yes and No for each city) were stored into values1 and values2 variables.

This data can be represented in Python with the bar function from matplotlib making use of the bottom argument, which represents the Y coordinates used to draw the bottom of the bars, so you can stack several bars.

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1) ax.bar(groups, values2, bottom = values1) # plt.show()

Stacked bar plot with three subgroups

If you have to stack more than two subgroups you will need to pass the added values of the previous data to bottom , as in the example below.

import matplotlib.pyplot as plt import numpy as np # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] values3 = [15, 23, 12, 11, 15] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1) ax.bar(groups, values2, bottom = values1) ax.bar(groups, values3, bottom = np.add(values1, values2)) # plt.show()

Generalization with multiple subgroups

However, if you don’t want to stack the values manually of the stacked bar graph you can join the values into a numpy array and then use the following for loop:

import matplotlib.pyplot as plt import numpy as np # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values = np.array([[12, 19, 14, 27, 16], [21, 30, 15, 17, 20], [15, 23, 12, 11, 15], [2, 5, 1, 6, 8]]) fig, ax = plt.subplots() # Stacked bar chart with loop for i in range(values.shape[0]): ax.bar(groups, values[i], bottom = np.sum(values[:i], axis = 0)) # plt.show()

The width argument controls the width of the bars. The default value is 0.8.

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] width = 0.25 fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, width = width) ax.bar(groups, values2, width = width, bottom = values1) # plt.show()

You can add error bars to the stacked bar plot with the yerr argument. You will need to input the standard deviation for each subgroup. Note that you can customize the color of the error bars with ecolor and the size of the caps with capsize .

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] values1_std = [2, 1, 3, 0.5, 2] values2_std = [1, 4, 0.25, 0.75, 1] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, yerr = values1_std, ecolor = 'red') ax.bar(groups, values2, yerr = values2_std, ecolor = 'green', bottom = values1) # plt.show()

Color customization

The color of the bars for each subgroup can be customized through the color argument. Note that you can also customize the transparency of the colors with alpha .

Читайте также:  Css selector not tag

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, color = "#024b7a", alpha = 0.5) ax.bar(groups, values2, bottom = values1, color = "#44a5c2", alpha = 0.5) # plt.show()

In addition, you can modify the border color and width of the bars with edgecolor and linewidth , respectively.

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, color = "#44a5c2", edgecolor = "black", linewidth = 2) ax.bar(groups, values2, bottom = values1, color = "#ffae49", edgecolor = "black", linewidth = 2) # plt.show()

Adding a legend for the subgroups

You can set a label for each subgroup with the label argument. Then, you can make use of the legend function to add the legend to the plot, as in the example below.

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, label = "Yes") ax.bar(groups, values2, bottom = values1, label = "No") ax.legend() ax.set_ylabel('Number of answers') # plt.show()

Stacked bar chart with labels

You can display the numerical values for each bar within the stack with the text function from matplotlib. In order to add them, you can use a for loop like the following:

import matplotlib.pyplot as plt # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, label = "Yes") ax.bar(groups, values2, bottom = values1, label = "No") # Labels for bar in ax.patches: ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() / 2 + bar.get_y(), round(bar.get_height()), ha = 'center', color = 'w', weight = 'bold', size = 10) ax.legend() ax.set_ylabel('Number of answers') # plt.show()

Total value labels

Alternatively, you can add labels representing the total value for each group or bar. For this purpose, you will need to add the values and then use a for loop to loop through each label, as in the following example.

import matplotlib.pyplot as plt import numpy as np # Data groups = ['G1', 'G2', 'G3', 'G4', 'G5'] values1 = [12, 19, 14, 27, 16] values2 = [21, 30, 15, 17, 20] fig, ax = plt.subplots() # Stacked bar chart ax.bar(groups, values1, label = "Yes") ax.bar(groups, values2, bottom = values1, label = "No") # Sum of values total_values = np.add(values1, values2) # Total values labels for i, total in enumerate(total_values): ax.text(i, total + 0.5, round(total), ha = 'center', weight = 'bold', color = 'black') ax.legend() ax.set_ylabel('Number of answers') plt.show()

Источник

Stacked bar chart#

This is an example of creating a stacked bar plot using bar .

Number of penguins with above average body mass

import matplotlib.pyplot as plt import numpy as np # data from https://allisonhorst.github.io/palmerpenguins/ species = ( "Adelie\n $\\mu=$3700.66g", "Chinstrap\n $\\mu=$3733.09g", "Gentoo\n $\\mu=5076.02g$", ) weight_counts =  "Below": np.array([70, 31, 58]), "Above": np.array([82, 37, 66]), > width = 0.5 fig, ax = plt.subplots() bottom = np.zeros(3) for boolean, weight_count in weight_counts.items(): p = ax.bar(species, weight_count, width, label=boolean, bottom=bottom) bottom += weight_count ax.set_title("Number of penguins with above average body mass") ax.legend(loc="upper right") plt.show() 

Источник

Stacked Bar Charts with Labels in Matplotlib

 Profile Image

This post will go through a few examples of creating stacked bar charts using Matplotlib. We’ll look at some styling tweaks (like choosing custom colors) as well as go through how to add labels to the bars, both the totals and sub-totals for each bar.

And be sure to check out our related post on creating stacked bar charts using several python libraries beyond Matplotlib, like Seaborn and Altair.

Simple Stacked Bar Chart

The general idea for creating stacked bar charts in Matplotlib is that you’ll plot one set of bars (the bottom), and then plot another set of bars on top, offset by the height of the previous bars, so the bottom of the second set starts at the top of the first set. Sound confusing? It’s really not, so let’s get into it.

Let’s first get some data to work with.

import seaborn as sns tips = sns.load_dataset('tips') # Let's massage the data a bit to be aggregated by day of week, with # columns for each gender. We could leave it in long format as well ( # with gender as values in a single column). agg_tips = tips.groupby(['day', 'sex'])['tip'].sum().unstack().fillna(0) agg_tips 

Now let’s create our first chart. We want to know the total amount tipped by day of week, split out by gender.

from matplotlib import pyplot as plt fig, ax = plt.subplots() # First plot the 'Male' bars for every day. ax.bar(agg_tips.index, agg_tips['Male'], label='Male') # Then plot the 'Female' bars on top, starting at the top of the 'Male' # bars. ax.bar(agg_tips.index, agg_tips['Female'], bottom=agg_tips['Male'], label='Female') ax.set_title('Tips by Day and Gender') ax.legend() 

As you can see, it’s pretty simple. We first plot tips that males gave and then plot tips that females gave, but give an additional bottom argument to tell Matplotlib where to start the bars (which happens to be the values of the previous bars; in this case male tips).

The above code generates this lovely plot:

stacked bar chart using matplotlib

Customizing the Stacked Bar Chart

The problem with the above code is that it starts to get very verbose, and quite repetitive, if we have more than a few layers in our stacked bars. So let’s make it a bit more DRY.

import numpy as np from matplotlib import pyplot as plt fig, ax = plt.subplots() # Initialize the bottom at zero for the first set of bars. bottom = np.zeros(len(agg_tips)) # Plot each layer of the bar, adding each bar to the "bottom" so # the next bar starts higher. for i, col in enumerate(agg_tips.columns): ax.bar(agg_tips.index, agg_tips[col], bottom=bottom, label=col) bottom += np.array(agg_tips[col]) ax.set_title('Tips by Day and Gender') ax.legend() 

This gives the exact same output as above, but is much nicer because we can apply it to any stacked bar need now, and it can handle as many layers as you need.

It’s also pretty flexible; for example, if we want to use custom colors we can easily do that:

fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar(agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) ax.set_title('Tips by Day and Gender') ax.legend() 

stacked bar chart with custom colors

Adding Labels to the Bars

It’s often nice to add value labels to the bars in a bar chart. With a stacked bar chart, it’s a bit trickier, because you could add a total label or a label for each sub-bar within the stack. We’ll show you how to do both.

Adding a Total Label

We’ll do the same thing as above, but add a step where we compute the totals for each day of the week and then use ax.text() to add those above each bar.

fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar( agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) # Sum up the rows of our data to get the total value of each bar. totals = agg_tips.sum(axis=1) # Set an offset that is used to bump the label up a bit above the bar. y_offset = 4 # Add labels to each bar. for i, total in enumerate(totals): ax.text(totals.index[i], total + y_offset, round(total), ha='center', weight='bold') ax.set_title('Tips by Day and Gender') ax.legend() 

stacked bar chart with total labels

Adding both Sub-Bar and Total Labels

Now let’s do the same thing again, but this time, add annotations for each sub-bar in the stack. The method here is a bit different; we can actually get the patches or bars that we’ve already plotted, read their values, and then add those values as text annotations at the right location.

fig, ax = plt.subplots() colors = ['#24b1d1', '#ae24d1'] bottom = np.zeros(len(agg_tips)) for i, col in enumerate(agg_tips.columns): ax.bar( agg_tips.index, agg_tips[col], bottom=bottom, label=col, color=colors[i]) bottom += np.array(agg_tips[col]) totals = agg_tips.sum(axis=1) y_offset = 4 for i, total in enumerate(totals): ax.text(totals.index[i], total + y_offset, round(total), ha='center', weight='bold') # Let's put the annotations inside the bars themselves by using a # negative offset. y_offset = -15 # For each patch (basically each rectangle within the bar), add a label. for bar in ax.patches: ax.text( # Put the text in the middle of each bar. get_x returns the start # so we add half the width to get to the middle. bar.get_x() + bar.get_width() / 2, # Vertically, add the height of the bar to the start of the bar, # along with the offset. bar.get_height() + bar.get_y() + y_offset, # This is actual value we'll show. round(bar.get_height()), # Center the labels and style them a bit. ha='center', color='w', weight='bold', size=8 ) ax.set_title('Tips by Day and Gender') ax.legend() 

stacked bar chart with all labels

Looks good. Thanks for reading and hopefully this helps get you on your way in creating annotated stacked bar charts in Matplotlib.

Источник

Оцените статью