Maddy6
Maddy6

Reputation: 417

Stacked Bar Chart is not working properly using matplotlib

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

Upvotes: 0

Views: 2597

Answers (1)

JohanC
JohanC

Reputation: 80509

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

Upvotes: 1

Related Questions