Tracer une barre en utilisant matplotlib en utilisant un dictionnaire

93

Existe-t-il un moyen de tracer un graphique à barres en matplotlibutilisant des données directement à partir d'un dict?

Mon dict ressemble à ceci:

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

je m'attendais à

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)

travailler, mais ce n’est pas le cas.

Voici l'erreur:

>>> 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
la source
Pouvez-vous partager spécifiquement ce qui ne fonctionne pas? Obtenez-vous une exception? Quelle exception? Partagez autant d'informations que possible.
Inbar Rose
@InbarRose désolé, j'ai mis à jour la question avec l'erreur qu'elle montre ... quelque chose concernant la chaîne ou le tampon ... Je ne comprends pas ce message d'erreur.
otmezger
2
Ce que vous voulez réaliser n'est pas clair, mais ax.bar(D,range(1,len(D)+1,1),0.5)le premier argument devrait contenir une liste de nombres, dans votre cas D.values().
adrianp
2
Un one-liner n'est pas possible pour cela, du moins à ma connaissance.
adrianp
1
Vous voudrez peut-être soumettre une demande de fonctionnalité au site github pour cela, car cela semble utile.
tacaswell

Réponses:

154

Vous pouvez le faire en deux lignes en traçant d'abord le graphique à barres, puis en définissant les graduations appropriées:

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

Notez que l'avant-dernière ligne doit être lue plt.xticks(range(len(D)), list(D.keys()))en python3, car D.keys()renvoie un générateur que matplotlib ne peut pas utiliser directement.

David Zwicker
la source
2
vous pouvez bien sûr envelopper ces deux lignes dans une fonction et ensuite cela devient une ligne unique;)
tacaswell
2
Si vous utilisez des objets de figure et d'axes, c'estax.set_xticklabels
Mark
2
Merci! Mais j'ai quelques problèmes esthétiques avec plt.xticks, pouvez-vous nous dire comment les déplacer verticalement depuis horizontalement.
moldave
2
les paires clé-valeur sont-elles alignées lorsque le dict n'est pas trié?
ssm
2
Les dicts Python ne peuvent pas être triés. Par conséquent, l'ordre est toujours arbitraire. Cependant, les clés et les valeurs sont toujours alignées sur le code ci-dessus.
David Zwicker
37

C'est un peu plus simple que la plupart des réponses ici suggèrent:

import matplotlib.pyplot as plt

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

entrez la description de l'image ici

ImportanceOfErnest
la source
34

Pour référence future, le code ci-dessus ne fonctionne pas avec Python 3. Pour Python 3, le D.keys()doit être converti en une liste.

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
la source
8

La meilleure façon de l'implémenter en utilisant matplotlib.pyplot.bar(range, height, tick_label)où la plage fournit des valeurs scalaires pour le positionnement de la barre correspondante dans le graphique. tick_labelfait le même travail que xticks(). On peut également le remplacer par un entier et utiliser multiple plt.bar(integer, height, tick_label). Pour des informations détaillées, veuillez consulter la documentation .

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

entrez la description de l'image ici

De plus, le même graphique peut être généré sans utiliser range(). Mais le problème rencontré était que cela tick_labelfonctionnait juste pour le dernier plt.bar()appel. Ainsi a xticks()été utilisé pour l'étiquetage:

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

entrez la description de l'image ici

Swaraj Kumar
la source
4

Je charge souvent le dict dans un DataFrame pandas puis j'utilise la fonction plot du DataFrame.
Voici le one-liner:

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

tracé résultant

anilbey
la source
3

Pourquoi pas simplement:

import seaborn as sns

sns.barplot(list(D.keys()), list(D.values()))
rwilsker
la source