0

I am trying to plot 100% stacked bar chart but i am getting wrong output. The aligned and the percentages are all messed up.

100% Stacked Bar Chart

x = ["A","B","C","D"]
data1 = {'Price':[12,44,23,21]}
data2 = {'Cost':[15,40,10,15]}
data3 = {'Units':[22,12,23,15]}
y1 = pd.DataFrame(data1)
y2 = pd.DataFrame(data2)
y3 = pd.DataFrame(data3)
snum = y1['Price']+y2['Cost']+y3['Units']

y11 = y1['Price']/snum*100
y22 = y2['Cost']/snum*100
y33 = y3['Units']/snum*100

plt.figure(figsize=(4,3))

# stack bars
plt.bar(x, y11, label='y1')
plt.bar(x, y22 ,bottom=y11 ,label='y2')
plt.bar(x, y33 ,bottom=y11+y22+y33,label='y3')

for xpos, ypos, yval in zip(x, y11/2, y11):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")
for xpos, ypos, yval in zip(x, y11+y22/2, y22):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")
for xpos, ypos, yval in zip(x, y11+y22+y33/2, y33):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")
1
  • 1
    Maybe replace plt.bar(x, y33,bottom=y11+y22+y33,label='y3') by plt.bar(x, y33,bottom=y11+y22,label='y3') ? Commented Nov 20, 2019 at 8:25

1 Answer 1

1

By bottom=y11+y22+y33, the third bar will start at 100% and stick out. Just remove the +y33 to get the desired result.

Here is the adapted code, also with slightly different colors. If you give the edge the same color as the bar, you avoid some possible white line between them.(I also imported the libraries and added show().)

import pandas as pd
from matplotlib import pyplot as plt

x = ["A","B","C","D"]
data1 = {'Price':[12,44,23,21]}
data2 = {'Cost':[15,40,10,15]}
data3 = {'Units':[22,12,23,15]}
y1 = pd.DataFrame(data1)
y2 = pd.DataFrame(data2)
y3 = pd.DataFrame(data3)
snum = y1['Price']+y2['Cost']+y3['Units']

y11 = y1['Price']/snum*100
y22 = y2['Cost']/snum*100
y33 = y3['Units']/snum*100

plt.figure(figsize=(4,3))

# stack bars
plt.bar(x, y11, label='y1', color='#fbb4ae', edgecolor='#fbb4ae')
plt.bar(x, y22, bottom=y11, label='y2', color='#b3cde3', edgecolor='#b3cde3')
plt.bar(x, y33, bottom=y11+y22, label='y3', color='#ccebc5', edgecolor='#ccebc5')

for xpos, ypos, yval in zip(x, y11/2, y11):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")
for xpos, ypos, yval in zip(x, y11+y22/2, y22):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")
for xpos, ypos, yval in zip(x, y11+y22+y33/2, y33):
    plt.text(xpos, ypos, "%.1f"%yval, ha="center", va="center")

plt.show()

resulting plot

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

1 Comment

Edit: setting edgecolor to prevent white lines between bars.

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.