Annoter les barres avec des valeurs sur les graphiques à barres Pandas


89

Je cherchais un moyen d'annoter mes barres dans un graphique à barres Pandas avec les valeurs numériques arrondies de mon DataFrame.

>>> df=pd.DataFrame({'A':np.random.rand(2),'B':np.random.rand(2)},index=['value1','value2'] )         
>>> df
                 A         B
  value1  0.440922  0.911800
  value2  0.588242  0.797366

J'aimerais obtenir quelque chose comme ça:

exemple d'annotation de graphique à barres

J'ai essayé avec cet exemple de code, mais les annotations sont toutes centrées sur les x ticks:

>>> ax = df.plot(kind='bar') 
>>> for idx, label in enumerate(list(df.index)): 
        for acc in df.columns:
            value = np.round(df.ix[idx][acc],decimals=2)
            ax.annotate(value,
                        (idx, value),
                         xytext=(0, 15), 
                         textcoords='offset points')

Tom a réussi, mais j'ai une solution plus complexe ici: stackoverflow.com/questions/19917587/…
Paul H

Réponses:


149

Vous l'obtenez directement à partir des patchs des axes:

for p in ax.patches:
    ax.annotate(str(p.get_height()), (p.get_x() * 1.005, p.get_height() * 1.005))

Vous voudrez modifier le formatage de la chaîne et les décalages pour centrer les choses, peut-être utiliser la largeur de p.get_width(), mais cela devrait vous aider à démarrer. Cela peut ne pas fonctionner avec les graphiques à barres empilés, sauf si vous suivez les décalages quelque part.


29
Merci @TomAugsPurger, ce qui suit a fonctionné: for p in ax.patches: ax.annotate(np.round(p.get_height(),decimals=2), (p.get_x()+p.get_width()/2., p.get_height()), ha='center', va='center', xytext=(0, 10), textcoords='offset points')
leroygr

2
Autre question: comment géreriez-vous les barres avec des valeurs négatives? Avec le code ci-dessus, les étiquettes sont toujours avec des coordonnées positives, même si la valeur de la barre est négative.
leroygr

1
Existe-t-il une solution similaire pour les barres horizontales: kind = barh?
Nickpick

4
J'ai trouvé que cela fonctionnait pour barh:ax.annotate(str(p.get_width()), (p.get_x() + p.get_width(), p.get_y()), xytext=(5, 10), textcoords='offset points')
Kamil Sindi

2
Merci @capitalistpug. J'ai trouvé que l'ajout d'un alignement horizontal améliorait encore le vôtre. ax.annotate(str(int(p.get_width())), (p.get_x() + p.get_width(), p.get_y()), xytext=(-2, 4), textcoords='offset points', horizontalalignment='right') +1
DaveL17

31

Solution qui gère également les valeurs négatives avec un exemple de formatage flottant.

Il faut encore peaufiner les compensations.

df=pd.DataFrame({'A':np.random.rand(2)-1,'B':np.random.rand(2)},index=['val1','val2'] )
ax = df.plot(kind='bar', color=['r','b']) 
x_offset = -0.03
y_offset = 0.02
for p in ax.patches:
    b = p.get_bbox()
    val = "{:+.2f}".format(b.y1 + b.y0)        
    ax.annotate(val, ((b.x0 + b.x1)/2 + x_offset, b.y1 + y_offset))

graphique à barres étiqueté valeur


0

La hache nous donne la taille de la boîte.

x_position=##define a value
y_position=##define a value
for patch in ax.patches:
    b= patch.get_bbox()
    y_value=b.y1-b.y0
    ax.annotate(y_value, "x_position" , "y_position"))
plt.show()

pour plus de clarté ::
Bbox (x0 = 3,75, y0 = 0,0, x1 = 4,25, y1 = 868,0)
Bbox (x0 = 4,75, y0 = 0,0, x1 = 5,25, y1 = 868,0)
Bbox (x0 = 5,75, y0 = 0,0 , x1 = 6,25, y1 = 1092,0)
Bbox (x0 = 6,75, y0 = 0,0, x1 = 7,25, y1 = 756,0)
Bbox (x0 = 7,75, y0 = 0,0, x1 = 8,25, y1 = 756,0)
Bbox (x0 = 8,75 , y0 = 0,0, x1 = 9,25, y1 = 588,0)
Bbox (x0 = 3,75, y0 = 868,0, x1 = 4,25, y1 = 3724,0)
Bbox (x0 = 4,75, y0 = 868,0, x1 = 5,25, y1 = 3528,0)
Bbox (x0 = 5,75, y0 = 1092,0, x1 = 6,25, y1 = 3948,0)
Bbox (x0 = 6,75, y0 = 756,0, x1 = 7,25, y1 = 2884,0)
Bbox (x0 = 7,75, y0 = 756,0, x1 = 8,25, y1 = 3024,0)
Bbox (x0 = 0,75, y0 = 4004,0, x1 = 1,25, y1 = 4396,0)
Bbox (x0 = 1,75, y0 = 3668,0, x1 = 2,25, y1 = 4060,0)
Bbox (x0 = 2,75, y0 = 3864,0, x1 = 3,25, y1 = 4060,0)

c'est la sortie de patch.get_bbox () dans mon programme.
nous pouvons extraire les détails de la boîte englobante à partir d'ici et manipuler pour nos besoins

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.