4

How to properly give Annotations to Pandas Bar Charts?

I'm following Bar Chart Annotations with Pandas and MPL, but somehow I can't make it into my own code -- this is as far as I can go. What's wrong?

I've also found the following code from here:

def autolabel(rects):
    # attach some text labels
    for rect in rects:
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
                '%d' % int(height),
                ha='center', va='bottom')

autolabel(rects1)
autolabel(rects2)

But I don't how to apply that to my code either. Please help.

UPDATE:

Thank you @CT Zhu, for the answer. However, in your horizontal bars, you are still placing the text on top of bars, but I need the text show up within or along them, like this from my referenced article,

enter image description here

where s/he says,

"I am very parital to horizontal bar charts, as I really think they are easier to read, however, I understand that a lot of people would rather see this chart implemented in a regular bar chart. So, here is the code to do that; you will notice that a few things have changed in order to create the annotation"*

xpt
  • 20,363
  • 37
  • 127
  • 216

1 Answers1

2

It appears your autolabel function is expecting a list of patches, sssuming your plot only those bars as its patches, we could do:

df = pd.DataFrame({'score':np.random.randn(6),
                   'person':[x*3 for x in list('ABCDEF')]})

def autolabel(rects):
    x_pos = [rect.get_x() + rect.get_width()/2. for rect in rects]
    y_pos = [rect.get_y() + 1.05*rect.get_height() for rect in rects]
    #if height constant: hbars, vbars otherwise
    if (np.diff([plt.getp(item, 'width') for item in rects])==0).all():
        scores = [plt.getp(item, 'height') for item in rects]
    else:
        scores = [plt.getp(item, 'width') for item in rects]
    # attach some text labels
    for rect, x, y, s in zip(rects, x_pos, y_pos, scores):
        ax.text(x, 
                y,
                '%s'%s,
                ha='center', va='bottom')

ax = df.set_index(['person']).plot(kind='barh', figsize=(10,7), 
              color=['dodgerblue', 'slategray'], fontsize=13)

ax.set_alpha(0.8)
ax.set_title("BarH")#,fontsize=18)
autolabel(ax.patches)

enter image description here

ax = df.set_index(['person']).plot(kind='bar', figsize=(10,7), 
              color=['dodgerblue', 'slategray'], fontsize=13)

ax.set_alpha(0.8)
ax.set_title("Bar")#,fontsize=18)
autolabel(ax.patches)

enter image description here

CT Zhu
  • 52,648
  • 17
  • 120
  • 133
  • Thanks! Accordint to the aformentioned *Bar Chart Annotations with Pandas and MPL*, `autolabel` would be different for vertical and horizontal bars. Apparently, the code I copied is for vertical bars. Could you change it to horizontal bars, so that the text show up *within* or along the bar instead of on top of it please? Also, why the value are all `0.5`? I need to annotations with the real value of the `score`s. Thanks – xpt Dec 06 '15 at 06:40
  • See edit. That just requires determining if the plot is a bar plot or a barh plot. – CT Zhu Dec 06 '15 at 18:22
  • Thank you @CT Zhu, for the answer. I've updated my OP to further explain what I meant by *"within or along the bar"*. – xpt Dec 06 '15 at 21:31
  • Ok, I can settle with this. Thanks again @CT Zhu. – xpt Dec 07 '15 at 16:59