Trazar una barra usando matplotlib usando un diccionario

93

¿Hay alguna forma de trazar un diagrama de barras matplotlibutilizando datos directamente de un dictado?

Mi dictado se ve así:

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

Yo estaba esperando

fig = plt.figure(figsize=(5.5,3),dpi=300)
ax = fig.add_subplot(111)
bar = ax.bar(D,range(1,len(D)+1,1),0.5)

para trabajar, pero no lo hace.

Aquí está el error:

>>> ax.bar(D,range(1,len(D)+1,1),0.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 4904, in bar
    self.add_patch(r)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1570, in add_patch
    self._update_patch_limits(p)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1588, in _update_patch_limits
    xys = patch.get_patch_transform().transform(vertices)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 580, in get_patch_transform
    self._update_patch_transform()
  File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 576, in _update_patch_transform
    bbox = transforms.Bbox.from_bounds(x, y, width, height)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/transforms.py", line 786, in from_bounds
    return Bbox.from_extents(x0, y0, x0 + width, y0 + height)
TypeError: coercing to Unicode: need string or buffer, float found
otmezger
fuente
¿Puedes compartir específicamente lo que no funciona? ¿Obtienes una excepción? ¿Qué excepción? Comparta tanta información como sea posible.
Inbar Rose
@InbarRose lo siento, he actualizado la pregunta con el error que muestra ... algo relacionado con la cadena o el búfer ... No entiendo este mensaje de error.
otmezger
2
No está claro lo que quiere lograr, pero en ax.bar(D,range(1,len(D)+1,1),0.5)el primer argumento debe haber una lista de números, en su caso D.values().
adrianp
2
No es posible una sola línea para esto, al menos que yo sepa.
adrianp
1
Es posible que desee enviar una solicitud de función al sitio de github para esto, porque parece útil.
tacaswell

Respuestas:

154

Puede hacerlo en dos líneas trazando primero el gráfico de barras y luego configurando los ticks apropiados:

import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

plt.bar(range(len(D)), list(D.values()), align='center')
plt.xticks(range(len(D)), list(D.keys()))
# # for python 2.x:
# plt.bar(range(len(D)), D.values(), align='center')  # python 2.x
# plt.xticks(range(len(D)), D.keys())  # in python 2.x

plt.show()

Tenga en cuenta que la penúltima línea debe leerse plt.xticks(range(len(D)), list(D.keys()))en python3, porque D.keys()devuelve un generador, que matplotlib no puede usar directamente.

David Zwicker
fuente
2
por supuesto, puede envolver esas dos líneas en una función y luego se convierte en una línea;)
tacaswell
2
Si usa objetos de figuras y ejes, esax.set_xticklabels
Mark
2
¡Gracias! Pero tengo algunos problemas estéticos con plt.xticks, ¿podría decirnos cómo moverlos verticalmente desde horizontalmente?
Moldovean
2
¿Están alineados los pares clave-valor cuando el dictado no está ordenado?
ssm
2
Los dictados de Python no se pueden ordenar. En consecuencia, el orden es siempre arbitrario. Sin embargo, las claves y los valores siempre están alineados con el código anterior.
David Zwicker
37

Es un poco más simple de lo que sugieren la mayoría de las respuestas aquí:

import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(*zip(*D.items()))
plt.show()

ingrese la descripción de la imagen aquí

Importancia de ser ernesto
fuente
34

Para referencia futura, el código anterior no funciona con Python 3. Para Python 3, D.keys()es necesario convertirlo en una lista.

import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

plt.bar(range(len(D)), D.values(), align='center')
plt.xticks(range(len(D)), list(D.keys()))

plt.show()
Michael T
fuente
8

La mejor forma de implementarlo es usar matplotlib.pyplot.bar(range, height, tick_label)donde el rango proporciona valores escalares para el posicionamiento de la barra correspondiente en el gráfico. tick_labelhace el mismo trabajo que xticks(). También se puede reemplazar con un número entero y usar varios plt.bar(integer, height, tick_label). Para obtener información detallada, consulte la documentación .

import matplotlib.pyplot as plt

data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())

#tick_label does the some work as plt.xticks()
plt.bar(range(len(data)),values,tick_label=names)
plt.savefig('bar.png')
plt.show()

ingrese la descripción de la imagen aquí

Además, se puede generar el mismo gráfico sin usar range(). Pero el problema encontrado fue que tick_labelsimplemente funcionó para la última plt.bar()llamada. Por xticks()lo tanto, se utilizó para etiquetar:

data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())
plt.bar(0,values[0],tick_label=names[0])
plt.bar(1,values[1],tick_label=names[1])
plt.bar(2,values[2],tick_label=names[2])
plt.xticks(range(0,3),names)
plt.savefig('fruit.png')
plt.show()

ingrese la descripción de la imagen aquí

Swaraj Kumar
fuente
4

A menudo cargo el dictado en un DataFrame de pandas y luego uso la función de trazado del DataFrame.
Aquí está el resumen:

pandas.DataFrame(D, index=['quantity']).plot(kind='bar')

trama resultante

Anilbey
fuente
3

Por qué no solo:

import seaborn as sns

sns.barplot(list(D.keys()), list(D.values()))
rwilsker
fuente