Wie wird der Wert des Balkens auf jedem Balken mit pyplot.barh () angezeigt?

104

Ich habe ein Balkendiagramm erstellt. Wie kann ich den Wert des Balkens auf jedem Balken anzeigen?

Aktuelle Handlung:

Geben Sie hier die Bildbeschreibung ein

Was ich versuche zu bekommen:

Geben Sie hier die Bildbeschreibung ein

Mein Code:

import os
import numpy as np
import matplotlib.pyplot as plt

x = [u'INFO', u'CUISINE', u'TYPE_OF_PLACE', u'DRINK', u'PLACE', u'MEAL_TIME', u'DISH', u'NEIGHBOURHOOD']
y = [160, 167, 137, 18, 120, 36, 155, 130]

fig, ax = plt.subplots()    
width = 0.75 # the width of the bars 
ind = np.arange(len(y))  # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('title')
plt.xlabel('x')
plt.ylabel('y')      
#plt.show()
plt.savefig(os.path.join('test.png'), dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
Franck Dernoncourt
quelle

Antworten:

172

Hinzufügen:

for i, v in enumerate(y):
    ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Die y-Werte vsind sowohl die x-Position als auch die Zeichenfolgenwerte für ax.text, und das Balkendiagramm hat zweckmäßigerweise eine Metrik von 1 für jeden Balken, sodass die Aufzählung idie y-Position ist.

cphlewis
quelle
11
Ersetzen Sie möglicherweise va = 'center' anstelle von "i + .25" für die horizontale Ausrichtung
mathause
11
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
João Cartucho
Wie kann ich die Textausgabe in einem Jupyter-Notizbuch unterdrücken? ";" am Ende funktioniert nicht.
Ralf Hundewadt
Wenn ich NACHBARSCHAFT oben auf der Leiste drucken möchte und für alle Baove-Leisten gleich links, was zu tun ist. versuchte und suchte viele Orte, aber bis jetzt keine Ahnung.
Rishi Bansal
@RalfHundewadt nur eine plt.show()Klausel am Ende setzen. Zum Beispiel: df.plot(); plt.show()
Jairo Alves
35

Ich habe festgestellt, dass der API-Beispielcode ein Beispiel für ein Balkendiagramm enthält, wobei der Wert des Balkens auf jedem Balken angezeigt wird:

"""
========
Barchart
========

A bar plot with errorbars and height labels on individual bars
"""
import numpy as np
import matplotlib.pyplot as plt

N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)

ind = np.arange(N)  # the x locations for the groups
width = 0.35       # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std)

women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std)

# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))

ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))


def autolabel(rects):
    """
    Attach a text label above each bar displaying its height
    """
    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)

plt.show()

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Zu Ihrer Information: Was ist die Höheneinheit, die in "barh" von matplotlib variabel ist? (Ab sofort gibt es keine einfache Möglichkeit, für jeden Balken eine feste Höhe festzulegen.)

Franck Dernoncourt
quelle
1
Es scheint, als ob get_x () die Zahl aufrundet, selbst wenn das ursprüngliche x Dezimalstellen hat. Wie können mehr Dezimalstellen angezeigt werden?
Ru111
1
Verspätet zur Party, aber für alle anderen, die dies mit height + 0.1 anstelle von 1.05 * height in der Autolabel-Funktion verwenden, entsteht eine konsistente Lücke zwischen Balken und Text
jnPy
19

Für alle, die ihr Etikett an der Basis ihrer Balken haben möchten, teilen Sie v einfach durch den Wert des Etiketts wie folgt:

for i, v in enumerate(labels):
    axes.text(i-.25, 
              v/labels[i]+100, 
              labels[i], 
              fontsize=18, 
              color=label_color_list[i])

(Hinweis: Ich habe 100 hinzugefügt, es war also nicht ganz unten)

So erhalten Sie ein Ergebnis: Geben Sie hier die Bildbeschreibung ein

Skromak
quelle
Sicher v == labels[i]und so könnte die dritte und vierte Zeile einfach sein 101, v?
wahr.
14

Ich weiß, dass es ein alter Thread ist, aber ich bin mehrmals über Google hier gelandet und denke, dass noch keine Antwort wirklich zufriedenstellend ist. Versuchen Sie es mit einer der folgenden Funktionen:

BEARBEITEN : Da ich einige Likes für diesen alten Thread bekomme, möchte ich auch eine aktualisierte Lösung teilen (im Grunde genommen meine beiden vorherigen Funktionen zusammenfügen und automatisch entscheiden, ob es sich um einen Bar- oder einen Hbar-Plot handelt):

def label_bars(ax, bars, text_format, **kwargs):
    """
    Attaches a label on every bar of a regular or horizontal bar chart
    """
    ys = [bar.get_y() for bar in bars]
    y_is_constant = all(y == ys[0] for y in ys)  # -> regular bar chart, since all all bars start on the same y level (0)

    if y_is_constant:
        _label_bar(ax, bars, text_format, **kwargs)
    else:
        _label_barh(ax, bars, text_format, **kwargs)


def _label_bar(ax, bars, text_format, **kwargs):
    """
    Attach a text label to each bar displaying its y value
    """
    max_y_value = ax.get_ylim()[1]
    inside_distance = max_y_value * 0.05
    outside_distance = max_y_value * 0.01

    for bar in bars:
        text = text_format.format(bar.get_height())
        text_x = bar.get_x() + bar.get_width() / 2

        is_inside = bar.get_height() >= max_y_value * 0.15
        if is_inside:
            color = "white"
            text_y = bar.get_height() - inside_distance
        else:
            color = "black"
            text_y = bar.get_height() + outside_distance

        ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)


def _label_barh(ax, bars, text_format, **kwargs):
    """
    Attach a text label to each bar displaying its y value
    Note: label always outside. otherwise it's too hard to control as numbers can be very long
    """
    max_x_value = ax.get_xlim()[1]
    distance = max_x_value * 0.0025

    for bar in bars:
        text = text_format.format(bar.get_width())

        text_x = bar.get_width() + distance
        text_y = bar.get_y() + bar.get_height() / 2

        ax.text(text_x, text_y, text, va='center', **kwargs)

Jetzt können Sie sie für normale Balkendiagramme verwenden:

fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}"  # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)

oder für horizontale Balkendiagramme:

fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}"  # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
SaturnFromTitan
quelle
14

Verwenden Sie plt.text () , um Text in das Diagramm einzufügen .

Beispiel:

import matplotlib.pyplot as plt
N = 5
menMeans = (20, 35, 30, 35, 27)
ind = np.arange(N)

#Creating a figure with some fig size
fig, ax = plt.subplots(figsize = (10,5))
ax.bar(ind,menMeans,width=0.4)
#Now the trick is here.
#plt.text() , you need to give (x,y) location , where you want to put the numbers,
#So here index will give you x pos and data+1 will provide a little gap in y axis.
for index,data in enumerate(menMeans):
    plt.text(x=index , y =data+1 , s=f"{data}" , fontdict=dict(fontsize=20))
plt.tight_layout()
plt.show()

Dies zeigt die Figur als:

Balkendiagramm mit Werten oben

Anirvan Sen.
quelle
Wie auch immer, um den Text etwas nach links zu verschieben?
Ramjit
1
@ S.Ramjitplt.text(x=index , y =data+1 , s=f"{data}" , fontdict=dict(fontsize=20), va='center')
theGtknerd
10

Für Pandas:

ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];

Das ist es. Alternativ für diejenigen, die es vorziehen, eine applySchleife mit Aufzählung zu erstellen:

it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));

Außerdem erhalten ax.patchesSie die Bars, mit denen Sie bekommen würden ax.bar(...). Falls Sie die Funktionen von @SaturnFromTitan oder Techniken anderer anwenden möchten.

tozCSS
quelle
Bitte überprüfen Sie, ob i, v nicht invertiert sind. Vielleicht sollte es sein[ax.text(i, v, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
Jairo Alves
@JairoAlves Dies ist ein horizontales Balkendiagramm und v repräsentiert die Position auf der x-Achse, daher sollte es korrekt sein. Bitte beachten Sie auch die akzeptierte Antwort.
tozCSS
Beispiel mit Patches for p in ax.patches: ax.annotate(str(p.get_height()), (p.get_x() * 1.005, p.get_height() * 1.005))
Ichta
1

Ich brauchte auch die Balkenbeschriftungen. Beachten Sie, dass meine y-Achse eine vergrößerte Ansicht mit Einschränkungen auf der y-Achse hat. Die Standardberechnungen zum Platzieren der Beschriftungen oben auf der Leiste funktionieren weiterhin mit der Höhe (use_global_coordinate = False im Beispiel). Ich wollte jedoch zeigen, dass die Beschriftungen auch in der gezoomten Ansicht unter Verwendung globaler Koordinaten in matplotlib 3.0.2 am unteren Rand des Diagramms platziert werden können . Hoffe es hilft jemandem.

def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True

if use_global_coordinate:
    for i in data:        
        ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
                verticalalignment='center', transform=ax.transAxes,fontsize=8)
        c=c+1
else:
    for rect,i in zip(rects,data):
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')

Beispielausgabe

Haramoz
quelle
0

Ich habe versucht, dies mit gestapelten Plotleisten zu tun. Der Code, der für mich funktionierte, war.

# Code to plot. Notice the variable ax.
ax = df.groupby('target').count().T.plot.bar(stacked=True, figsize=(10, 6))
ax.legend(bbox_to_anchor=(1.1, 1.05))

# Loop to add on each bar a tag in position
for rect in ax.patches:
    height = rect.get_height()
    ypos = rect.get_y() + height/2
    ax.text(rect.get_x() + rect.get_width()/2., ypos,
            '%d' % int(height), ha='center', va='bottom')
Klaifer Garcia
quelle
0

Überprüfen Sie diesen Link Matplotlib Gallery So habe ich das Code-Snippet von Autolabel verwendet.

    def autolabel(rects):
    """Attach a text label above each bar in *rects*, displaying its height."""
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom')
        
temp = df_launch.groupby(['yr_mt','year','month'])['subs_trend'].agg(subs_count='sum').sort_values(['year','month']).reset_index()
_, ax = plt.subplots(1,1, figsize=(30,10))
bar = ax.bar(height=temp['subs_count'],x=temp['yr_mt'] ,color ='g')
autolabel(bar)

ax.set_title('Monthly Change in Subscribers from Launch Date')
ax.set_ylabel('Subscriber Count Change')
ax.set_xlabel('Time')
plt.show()
parth pandey
quelle