BlandCorporation
BlandCorporation

Reputation: 1344

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()

Upvotes: 1

Views: 1688

Answers (2)

Yaakov Bressler
Yaakov Bressler

Reputation: 12018

The fastest solution to this would be to add a list of colors to be mapped to the plot:

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

A more comprehensive approach would be to change your approach for plotting, which I won't get into just yet because I don't know the scale of the problem you're trying to solve.

Upvotes: 1

Pete
Pete

Reputation: 81

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)

Upvotes: 2

Related Questions