stacked bar plot using matplotlib stacked bar plot using matplotlib python python

stacked bar plot using matplotlib


You need the bottom of each dataset to be the sum of all the datasets that came before. you may also need to convert the datasets to numpy arrays to add them together.

p1 = plt.bar(ind, dataset[1], width, color='r')p2 = plt.bar(ind, dataset[2], width, bottom=dataset[1], color='b')p3 = plt.bar(ind, dataset[3], width,              bottom=np.array(dataset[1])+np.array(dataset[2]), color='g')p4 = plt.bar(ind, dataset[4], width,             bottom=np.array(dataset[1])+np.array(dataset[2])+np.array(dataset[3]),             color='c')

enter image description here

Alternatively, you could convert them to numpy arrays before you start plotting.

dataset1 = np.array(dataset[1])dataset2 = np.array(dataset[2])dataset3 = np.array(dataset[3])dataset4 = np.array(dataset[4])p1 = plt.bar(ind, dataset1, width, color='r')p2 = plt.bar(ind, dataset2, width, bottom=dataset1, color='b')p3 = plt.bar(ind, dataset3, width, bottom=dataset1+dataset2, color='g')p4 = plt.bar(ind, dataset4, width, bottom=dataset1+dataset2+dataset3,             color='c')

Or finally if you want to avoid converting to numpy arrays, you could use a list comprehension:

p1 = plt.bar(ind, dataset[1], width, color='r')p2 = plt.bar(ind, dataset[2], width, bottom=dataset[1], color='b')p3 = plt.bar(ind, dataset[3], width,             bottom=[sum(x) for x in zip(dataset[1],dataset[2])], color='g')p4 = plt.bar(ind, dataset[4], width,             bottom=[sum(x) for x in zip(dataset[1],dataset[2],dataset[3])],             color='c')


I found this such a pain that I wrote a function to do it. I'm sharing it in the hope that others find it useful:

import numpy as npimport matplotlib.pyplot as pltdef plot_stacked_bar(data, series_labels, category_labels=None,                      show_values=False, value_format="{}", y_label=None,                      colors=None, grid=True, reverse=False):    """Plots a stacked bar chart with the data and labels provided.    Keyword arguments:    data            -- 2-dimensional numpy array or nested list                       containing data for each series in rows    series_labels   -- list of series labels (these appear in                       the legend)    category_labels -- list of category labels (these appear                       on the x-axis)    show_values     -- If True then numeric value labels will                        be shown on each bar    value_format    -- Format string for numeric value labels                       (default is "{}")    y_label         -- Label for y-axis (str)    colors          -- List of color labels    grid            -- If True display grid    reverse         -- If True reverse the order that the                       series are displayed (left-to-right                       or right-to-left)    """    ny = len(data[0])    ind = list(range(ny))    axes = []    cum_size = np.zeros(ny)    data = np.array(data)    if reverse:        data = np.flip(data, axis=1)        category_labels = reversed(category_labels)    for i, row_data in enumerate(data):        color = colors[i] if colors is not None else None        axes.append(plt.bar(ind, row_data, bottom=cum_size,                             label=series_labels[i], color=color))        cum_size += row_data    if category_labels:        plt.xticks(ind, category_labels)    if y_label:        plt.ylabel(y_label)    plt.legend()    if grid:        plt.grid()    if show_values:        for axis in axes:            for bar in axis:                w, h = bar.get_width(), bar.get_height()                plt.text(bar.get_x() + w/2, bar.get_y() + h/2,                          value_format.format(h), ha="center",                          va="center")

Example:

plt.figure(figsize=(6, 4))series_labels = ['Series 1', 'Series 2']data = [    [0.2, 0.3, 0.35, 0.3],    [0.8, 0.7, 0.6, 0.5]]category_labels = ['Cat A', 'Cat B', 'Cat C', 'Cat D']plot_stacked_bar(    data,     series_labels,     category_labels=category_labels,     show_values=True,     value_format="{:.1f}",    colors=['tab:orange', 'tab:green'],    y_label="Quantity (units)")plt.savefig('bar.png')plt.show()

stacked bar plot example


This is probably your most convenient solution if you are willing to use Pandas:

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt    X_AXIS = ('60.0', '65.0', '70.0', '75.0', '80.0', '85.0', '90.0', '95.0', '100.0', '105.0', '110.0', '115.0', '120.0', '125.0', '130.0', '135.0', '140.0', '145.0', '150.0', '155.0', '160.0', '165.0', '170.0', '175.0', '180.0', '185.0', '190.0', '195.0', '200.0')index = pd.Index(X_AXIS, name='test')data = {'a': (0.0, 25.0, 48.94, 83.02, 66.67, 66.67, 70.97, 84.62, 93.33, 85.0, 92.86, 93.75, 95.0, 100.0, 100.0, 100.0, 100.0, 80.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0),        'b': (0.0, 50.0, 36.17, 11.32, 26.67, 33.33, 29.03, 15.38, 6.67, 15.0, 7.14, 6.25, 5.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),        'c': (0.0, 12.5, 10.64, 3.77, 4.45, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),        'd': (100.0, 12.5, 4.26, 1.89, 2.22, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)}df = pd.DataFrame(data, index=index)ax = df.plot(kind='bar', stacked=True, figsize=(10, 6))ax.set_ylabel('foo')plt.legend(title='labels', bbox_to_anchor=(1.0, 1), loc='upper left')# plt.savefig('stacked.png')  # if neededplt.show()

enter image description here