0

I have the following dataframe:

     Color      Level     Proportion
-------------------------------------
0     Blue          1            0.1
1     Blue          2            0.3
2     Blue          3            0.6
3      Red          1            0.2
4      Red          2            0.5
5      Red          3            0.3

Here I have 2 color categories, where each color category has 3 levels, and each entry has a proportion, which sum to 1 for each color category. I want to make a stacked bar chart from this dataframe that has 2 stacked bars, one for each color category. Within each of those stacked bars will be the proportion for each level, all summing to 1. So while the bars will be "stacked" different, the bars as complete bars will be the same length of 1.

I have tried this:

df.plot(kind='bar', stacked=True)

I then get this stacked bar chart, which is not what I want:

enter image description here

I want 2 stacked bars, and so a stacked bar for "Blue" and a stacked bar for "Red", where these bars are "stacked" by the proportions, with the colors of these stacks corresponding to each level. And so both of these bars would be of length 1 along the x-axis, which would be labelled "proportion". How can I fix my code to create this stacked bar chart?

0

2 Answers 2

2

Make a pivot and then plot it:

df.pivot(index = 'Color', columns = 'Level', values = 'Proportion')
df.plot(kind = 'bar', stacked = True)

Edit: Cleaner legend

Sign up to request clarification or add additional context in comments.

Comments

1

You could create a Seaborn sns.histplot using the proportion as weights and the level as hue:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

df = pd.DataFrame({'Color': ['Blue'] * 3 + ['Red'] * 3,
                   'Level': [1, 2, 3] * 2,
                   'Proportion': [.1, .3, .6, .2, .5, .3]})
sns.set_style('white')
ax = sns.histplot(data=df, x='Color', weights='Proportion', hue='Level', multiple='stack', palette='flare', shrink=0.75)
ax.set_ylabel('Proportion')
for bars in ax.containers:
    ax.bar_label(bars, label_type='center', fmt='%.2f')
sns.move_legend(ax, loc='upper left', bbox_to_anchor=(1, 0.97))
sns.despine()
plt.tight_layout()
plt.show()

sns.histplot with weights

2 Comments

Hello, this works great and is totally what I was looking for! Thank you! Do you know if there is a simple way to convert this chart to have these stacked bars going horizontally from left to right? This would mean that the x-axis would be "Proportion", and the y-axis would be "Color", where the y-axis labels would just be "Blue" and "Red". I should have mentioned this in my post.
You can replace x= by y=, i.e. sns.histplot(data=df, y='Color', ...) for horizontal bars. You'll also need to replace ax.set_ylabel('Proportion') by ax.set_xlabel('Proportion').

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.