Traccia una barra usando matplotlib usando un dizionario


93

Esiste un modo per tracciare un grafico a barre matplotlibutilizzando i dati direttamente da un dict?

Il mio dict ha questo aspetto:

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

stavo aspettando

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)

per funzionare, ma non lo fa.

Ecco l'errore:

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

Puoi condividere specificamente ciò che non funziona? Ottieni un'eccezione? Quale eccezione? Condividi quante più informazioni possibile.
Inbar Rose

@ InbarRose scusa, ho aggiornato la domanda con l'errore che mostra ... qualcosa che riguarda la stringa o il buffer ... Non capisco questo messaggio di errore.
otmezger

2
Non è chiaro cosa vuoi ottenere, ma nel ax.bar(D,range(1,len(D)+1,1),0.5)primo argomento dovrebbe esserci un elenco di numeri, nel tuo caso D.values().
adrianp

2
Una battuta non è possibile per questo, almeno per quanto ne so.
adrianp

1
Potresti voler inviare una richiesta di funzionalità al sito GitHub per questo, perché sembra utile.
tacaswell

Risposte:


154

Puoi farlo su due linee tracciando prima il grafico a barre e quindi impostando i segni di graduazione appropriati:

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

Nota che la penultima riga dovrebbe essere letta plt.xticks(range(len(D)), list(D.keys()))in python3, perché D.keys()restituisce un generatore, che matplotlib non può usare direttamente.


2
puoi ovviamente racchiudere queste due righe in una funzione e poi diventa una
riga

2
Se usi oggetti figura e assi, èax.set_xticklabels
Marco

2
Grazie! Ma ho alcuni problemi estetici con i plt. Trucchi, potresti dirci come spostarli verticalmente da orizzontalmente.
moldavo

2
le coppie chiave-valore sono allineate quando il dict non è ordinato?
ssm

2
I dict di Python non possono essere ordinati. Di conseguenza, l'ordine è sempre arbitrario. Tuttavia, le chiavi e i valori sono sempre allineati con il codice precedente.
David Zwicker

37

È un po 'più semplice di quanto la maggior parte delle risposte qui suggeriscano:

import matplotlib.pyplot as plt

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

inserisci qui la descrizione dell'immagine


34

Per riferimento futuro, il codice sopra non funziona con Python 3. Per Python 3, D.keys()deve essere convertito in un elenco.

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

8

Il modo migliore per implementarlo utilizzando matplotlib.pyplot.bar(range, height, tick_label)dove l'intervallo fornisce valori scalari per il posizionamento della barra corrispondente nel grafico. tick_labelfa lo stesso lavoro di xticks(). Si può anche sostituirlo con un numero intero e utilizzare più plt.bar(integer, height, tick_label). Per informazioni dettagliate fare riferimento alla documentazione .

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

inserisci qui la descrizione dell'immagine

Inoltre lo stesso grafico può essere generato senza utilizzare range(). Ma il problema riscontrato era quellotick_label funzionava solo per l'ultima plt.bar()chiamata. Quindi è xticks()stato utilizzato per l'etichettatura:

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

inserisci qui la descrizione dell'immagine


4

Spesso carico il dict in un DataFrame panda, quindi uso la funzione di trama del DataFrame.
Ecco la battuta:

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

trama risultante


3

Perché non solo:

import seaborn as sns

sns.barplot(list(D.keys()), list(D.values()))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.