Search code examples
pythonmatplotlibstacked-bar-chart

How can the colors in a bar of a stacked bar chart be individually specified?


I am making a "class prediction error" plot, wherein a model attempts to classify data into one of two classes. The plot shows the fraction of each class that is made up of the correct class and another class.

So, for the classes of signal and background, of those data classified as signal, most are correct, but some data are actually background, and of those data classified as background, most are correct, but some data are actually signal. Now, this means that I want to plot one bar for signal and to have signal (red) making up most of the bar and background (blue) making up the minority of the bar, and I want to plot one other bar for background and to have background (blue) making up most of the bar and signal (red) making up the minority of the bar.

I have the following code, but the order of the colors in the second bar (background) needs to be swapped. How might this be done? (I am also thinking of the possibility of having more than two classes.)

import matplotlib
import matplotlib.pyplot as plt

%matplotlib inline
plt.rcParams["figure.figsize"] = [10, 10]

cc0 = 39695 # classified correctly background
ci0 = 18595 # classified incorrectly background
cc1 = 38801 # classified correctly signal
ci1 = 19556 # classified incorrectly signal

fractions_correct   = (cc0, cc1)
fractions_incorrect = (ci0, ci1)
width = 0.9
ind   = np.arange(2)
p1    = plt.bar(ind, fractions_correct, width, color='red')
p2    = plt.bar(ind, fractions_incorrect, width, bottom=fractions_correct, color='blue')

plt.xlabel('classification by model')
plt.ylabel('class case abundances')
plt.xticks(ind, ('signal', 'background'))
plt.yticks([])
plt.legend((p2[0], p1[0]), ('background', 'signal'), loc='center left', bbox_to_anchor=(1, 0.5));
plt.show()

Solution

  • You can pass color a list of parameter if the length of the list matches the number of bars.

        color=["red","blue"]
        p1    = plt.bar(ind, fractions_correct, width, color=color)
        color=["blue","red"]
        p2 = plt.bar(ind, fractions_incorrect, width, bottom=fractions_correct, color=color)