Cómo mostrar el valor en barras horizontales

7 minutos de lectura

Avatar de usuario de Franck Dernoncourt
franck dernoncourt

Generé un gráfico de barras, ¿cómo puedo mostrar el valor de la barra en cada barra?

Parcela actual:

ingrese la descripción de la imagen aquí

Lo que estoy tratando de conseguir:

ingrese la descripción de la imagen aquí

Mi código:

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

avatar de usuario de cphlewis
cphlewis

Actualización: ¡ahora hay un método incorporado para esto! Desplácese hacia abajo un par de respuestas a “Nuevo en matplotlib 3.4.0”.

Si no puede actualizar tanto, no se necesita mucho código. Agregar:

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

resultado:

ingrese la descripción de la imagen aquí

Los valores de y v son tanto la ubicación x como los valores de cadena para ax.texty convenientemente el gráfico de barras tiene una métrica de 1 para cada barra, por lo que la enumeración i es la ubicación y.

  • tal vez reemplace use va = ‘center’, en lugar de “i + .25” para la alineación horizontal

    – Mathause

    26/09/2017 a las 16:40

  • plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')

    – Joao Cartucho

    18 de abril de 2018 a las 11:41


  • ¿Cómo puedo suprimir la salida de texto en un cuaderno jupyter? “;” al final no funciona.

    – Ralf Hundewadt

    17 de julio de 2019 a las 14:58

  • Si quiero imprimir BARRIO en la parte superior de la barra y lo mismo para todas las barras de baove, en lugar de a la izquierda, lo que hay que hacer. Probé y busqué en muchos lugares, pero no tengo ni idea hasta ahora.

    –Rishi Bansal

    19 de julio de 2019 a las 10:55


  • @RalfHundewadt acaba de poner un plt.show() cláusula al final. Por ejemplo: df.plot(); plt.show()

    –Jairo Alves

    14 oct 2019 a las 18:51

avatar de usuario de tdy
tdy

Nuevo en matplotlib 3.4.0

Ahora hay un incorporado Axes.bar_label método auxiliar para autoetiquetar barras:

fig, ax = plt.subplots()
bars = ax.barh(indexes, values)

ax.bar_label(bars)

Tenga en cuenta que para los gráficos de barras agrupadas/apiladas, habrá varios contenedores de barras, a los que se puede acceder a través de ax.containers:

for bars in ax.containers:
    ax.bar_label(bars)

Más detalles:

  • Cómo agregar separadores de miles (comas) a las etiquetas
  • Cómo aplicar f-strings a las etiquetas
  • Cómo agregar espaciado a las etiquetas

Cómo mostrar el valor en barras horizontales

  • ¡Por fin está ahí! ¡Una buena razón para actualizar a matplotlib 3.4.0!

    – ilija139

    19 de diciembre de 2022 a las 9:53

Avatar de usuario de Franck Dernoncourt
franck dernoncourt

Me he dado cuenta codigo de ejemplo api contiene un ejemplo de gráfico de barras con el valor de la barra que se muestra en cada barra:

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

producción:

ingrese la descripción de la imagen aquí

FYI ¿Cuál es la unidad de variable de altura en “barh” de matplotlib? (a partir de ahora, no hay una manera fácil de establecer una altura fija para cada barra)

Avatar de usuario de Anirvan Sen
anirvan sen

Usar plt.text() para poner texto en la trama.

Ejemplo:

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

Esto mostrará la figura como:

gráfico de barras con valores en la parte superior

Para cualquiera que quiera tener su etiqueta en la base de sus bares solo dividir v por el valor de la etiqueta como esto:

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

(nota: agregué 100 para que no estuviera absolutamente en la parte inferior)

Para obtener un resultado como este:
ingrese la descripción de la imagen aquí

Sé que es un hilo antiguo, pero llegué aquí varias veces a través de Google y creo que ninguna respuesta dada es realmente satisfactoria todavía. Intente usar una de las siguientes funciones:

EDITAR: Como estoy recibiendo algunos Me gusta en este hilo antiguo, también quiero compartir una solución actualizada (básicamente juntando mis dos funciones anteriores y decidiendo automáticamente si se trata de un diagrama de barra o 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)

Ahora puede usarlos para diagramas de barras regulares:

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)

o para gráficos de barras horizontales:

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)

Avatar de usuario de tozCSS
tozCSS

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

Eso es todo. Alternativamente, para aquellos que prefieren apply sobre bucle con enumerar:

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

También, ax.patches te dará las barras que obtendrías con ax.bar(...). En caso de querer aplicar las funciones de @SaturnFromTitan o técnicas de otros.

¿Ha sido útil esta solución?