Han Zhengzu - 1 year ago 81
Python Question

# Label stacked bar with autolabel function

### My project

For some reason, I want to generate a stacked bar figure which the number need to be set in the right of each section. An illustration figure is shown here:

Each section with its value and percentage as its label.

### MY attempt

Here is my solution for plotting stacked bar with autolabel function.

``````AMOUNT_LOOP = np.array([GM[0]+OM[0]+TEO[0],GM[1]+OM[1]+TEO[1],GM[2]+OM[2]+TEO[2]])

## data
GM =  np.array([ 26.24592078,  51.76195669,  38.8572158 ])
OM =  np.array([ 21.13405649,  12.71185216,  14.84377391])
TEO = np.array([ 0.52274901,  0.57721648,  0.52718344])

def autolabel(rects, ax):
(y_bottom, y_top) = ax.get_ylim()
y_height = y_top - y_bottom
for i,rect in enumerate(rects) :
height = rect.get_height()
label_position = height*0.5 + (y_height * 0.01)
label_ = "%2.1f" % (height/AMOUNT_LOOP[i]*100)
label  =label_+'%'
ax.text(rect.get_x()+1.05 + rect.get_width()/2., label_position-0.5,
'%s' % str(label),
ha='center', va='bottom')
l=plt.Line2D((rect.get_x()+1.15, rect.get_x()+1.3), (label_position-2.5, label_position), lw=0.75,color ='k')

cs = ['#a6cee3','#C2C4C6','#F9F2AA',]
fig, ax = plt.subplots()

y_pos = np.array([1,3.75,6.45])

rect1 = ax.bar(y_pos, GM, width = 1.2, color = cs[0], label = 'GM')
autolabel(rect1,ax)
rect2 = ax.bar(y_pos, OM, width = 1.2, bottom=GM, color = cs[1], label = 'OM')
autolabel(rect2,ax)
rect3 = ax.bar(y_pos, TEO, width = 1.2,    bottom=GM+OM,               color = cs[2], label = 'TEO')
autolabel(rect3,ax)
ax.set_xlim(0,8.5)
plt.show()
``````

The result shows like this:

### My question

So, the problem is my label height is not from the bottom line of its corresponding section. I want to generate a function that can detect the stacked position and add the height of the amount of underlying bar as the new Y position.

I have not thought about any solution.

Any advices or guide would be appreciate!

The following should do the trick:

``````import numpy as np
from matplotlib import pyplot as plt

## data
GM =  np.array([ 26.24592078,  51.76195669,  38.8572158 ])
OM =  np.array([ 21.13405649,  12.71185216,  14.84377391])
TEO = np.array([ 0.52274901,  0.57721648,  0.52718344])

def autolabel(rects, ax):
for rect in rects:

y_val = rect.get_y() + rect.get_height() - rect.get_height()/2

ax.text(rect.get_x()+1.05 + rect.get_width()/2., y_val,
str(rect.get_height()),
ha='center', va='bottom')

cs = ['#a6cee3','#C2C4C6','#F9F2AA',]
fig, ax = plt.subplots()

y_pos = np.array([1,3.75,6.45])

rect1 = ax.bar(y_pos, GM, width = 1.2, color = cs[0], label = 'GM')
autolabel(rect1, ax)

rect2 = ax.bar(y_pos, OM, width = 1.2, bottom=GM, color = cs[1], label = 'OM')
autolabel(rect2, ax)

rect3 = ax.bar(y_pos, TEO, width = 1.2,    bottom=GM+OM,               color = cs[2], label = 'TEO')
autolabel(rect3, ax)
ax.set_xlim(0,8.5)
plt.show()
``````

Calling `rect.get_y() + rect.get_height()` gets the y value of each bar. `get_y` being the base and `get_height` being the height. `- rect.get_height()/2` to get the centre of each bar.

Here is example image

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download