Bagaimana cara menampilkan nilai bar pada setiap bar dengan pyplot.barh ()?


106

Saya membuat plot batang, bagaimana cara menampilkan nilai batang pada setiap batang?

Plot saat ini:

masukkan deskripsi gambar di sini

Apa yang saya coba dapatkan:

masukkan deskripsi gambar di sini

Kode saya:

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

Jawaban:


173

Menambahkan:

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

hasil:

masukkan deskripsi gambar di sini

Nilai y vadalah lokasi x dan nilai stringnya ax.text, dan diagram batang memiliki metrik 1 untuk setiap batang, jadi pencacahannya iadalah lokasi y.


11
mungkin ganti gunakan va = 'center', daripada "i + .25" untuk perataan horizontal
mathause

11
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
João Cartucho

Bagaimana cara menyembunyikan keluaran teks di notebook jupyter? ";" pada akhirnya tidak berhasil.
Ralf Hundewadt

Jika saya ingin mencetak NEIGHBORHOOD di atas bilah dan sama untuk semua bilah alas, alih-alih di sebelah kiri, apa yang perlu dilakukan. mencoba dan mencari di banyak tempat tetapi tidak ada petunjuk sampai sekarang.
Rishi Bansal

@RalfHundewadt baru saja memberi plt.show()klausa di bagian akhir. Misalnya: df.plot(); plt.show()
Jairo Alves

36

Saya perhatikan kode contoh api berisi contoh barchart dengan nilai bar yang ditampilkan di setiap bar:

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

keluaran:

masukkan deskripsi gambar di sini

FYI Berapa satuan variabel tinggi dalam "barh" dari matplotlib? (hingga saat ini, tidak ada cara mudah untuk mengatur ketinggian tetap untuk setiap batang)


1
Sepertinya get_x () membulatkan angka ke atas meskipun x asli memiliki tempat desimal. Bagaimana Anda mendapatkan lebih banyak tempat desimal untuk ditampilkan?
ru111

1
terlambat ke pesta tetapi untuk orang lain yang menggunakan ini menggunakan tinggi + 0,1 bukan 1,05 * tinggi dalam fungsi label otomatis menciptakan celah yang konsisten antara bilah dan teks
jnPy

19

Bagi siapa pun yang ingin memiliki label di dasar batang, cukup bagi v dengan nilai label seperti ini:

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

(catatan: Saya menambahkan 100 jadi tidak mutlak di bagian bawah)

Untuk mendapatkan hasil seperti ini: masukkan deskripsi gambar di sini


Tentunya v == labels[i]dan baris ketiga dan keempat bisa begitu saja 101, v?
It'sNotALie.

14

Saya tahu ini utas lama, tetapi saya mendarat di sini beberapa kali melalui Google dan berpikir belum ada jawaban yang benar-benar memuaskan. Coba gunakan salah satu fungsi berikut:

EDIT : Karena saya mendapatkan beberapa suka di utas lama ini, saya ingin membagikan solusi yang diperbarui juga (pada dasarnya menggabungkan dua fungsi saya sebelumnya dan secara otomatis memutuskan apakah itu plot bar atau hbar):

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)

Sekarang Anda dapat menggunakannya untuk plot batang biasa:

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)

atau untuk plot batang horizontal:

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)

14

Gunakan plt.text () untuk meletakkan teks di plot.

Contoh:

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

Ini akan menunjukkan gambar sebagai:

diagram batang dengan nilai di atas


Pokoknya menggeser teks sedikit ke kiri?
S. Ramjit

1
@ S.Ramjitplt.text(x=index , y =data+1 , s=f"{data}" , fontdict=dict(fontsize=20), va='center')
theGtknerd

10

Untuk orang panda:

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)];

Itu dia. Alternatifnya, bagi mereka yang lebih suka melakukan applyperulangan dengan enumerate:

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

Juga, ax.patchesakan memberi Anda bar yang akan Anda dapatkan ax.bar(...). Jika Anda ingin menerapkan fungsi @SaturnFromTitan atau teknik orang lain.


Harap periksa apakah i, v tidak terbalik. Mungkin seharusnya begitu[ax.text(i, v, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
Jairo Alves

@JairoAlves ini adalah plot batang horizontal dan v mewakili lokasi pada sumbu x, jadi seharusnya benar. Silakan lihat juga jawaban yang diterima.
tozCSS

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

1

Saya membutuhkan label batang juga, perhatikan bahwa sumbu y saya memiliki tampilan yang diperbesar menggunakan batas pada sumbu y. Penghitungan default untuk meletakkan label di atas bilah masih berfungsi menggunakan ketinggian (use_global_coordinate = False dalam contoh). Tetapi saya ingin menunjukkan bahwa label juga dapat diletakkan di bagian bawah grafik dalam tampilan yang diperbesar menggunakan koordinat global di matplotlib 3.0.2 . Semoga membantu seseorang.

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

Contoh keluaran


0

Saya mencoba melakukan ini dengan batang plot bertumpuk. Kode yang berhasil untuk saya adalah.

# 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')

0

Periksa link ini Galeri Matplotlib Ini adalah bagaimana saya menggunakan potongan kode autolabel.

    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()
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.