2013-01-11 23 views
28

Come tracciare più barre in matplotlib, quando ho provato a chiamare la funzione bar più volte, si sovrappongono e come si vede nella figura sottostante si può vedere solo il valore più alto rosso. Come posso tracciare le barre multiple con le date sugli assi x?python matplotlib multiple bars

Finora, ho provato questo:

import matplotlib.pyplot as plt 
    import datetime 

    x = [datetime.datetime(2011, 1, 4, 0, 0), 
     datetime.datetime(2011, 1, 5, 0, 0), 
     datetime.datetime(2011, 1, 6, 0, 0)] 
    y = [4, 9, 2] 
    z=[1,2,3] 
    k=[11,12,13] 

    ax = plt.subplot(111)![enter image description here][1] 
    ax.bar(x, y,width=0.5,color='b',align='center') 
    ax.bar(x, z,width=0.5,color='g',align='center') 
    ax.bar(x, k,width=0.5,color='r',align='center') 
    ax.xaxis_date() 

    plt.show() 

ho ottenuto questo: enter image description here

i risultati dovrebbero essere qualcosa di simile, ma con le date sugli assi e bar x sono uno accanto altro: enter image description here

+0

è necessario modificare i valori della x – jterrace

+0

Cosa vuoi dire? I valori X sono date ... –

risposta

38
import matplotlib.pyplot as plt 
from matplotlib.dates import date2num 
import datetime 

x = [datetime.datetime(2011, 1, 4, 0, 0), 
    datetime.datetime(2011, 1, 5, 0, 0), 
    datetime.datetime(2011, 1, 6, 0, 0)] 
x = date2num(x) 

y = [4, 9, 2] 
z=[1,2,3] 
k=[11,12,13] 

ax = plt.subplot(111) 
ax.bar(x-0.2, y,width=0.2,color='b',align='center') 
ax.bar(x, z,width=0.2,color='g',align='center') 
ax.bar(x+0.2, k,width=0.2,color='r',align='center') 
ax.xaxis_date() 

plt.show() 

enter image description here

Non so qual è il "valori y sono anche sovrapposti" significa, ha il seguente codice risolto il problema?

ax = plt.subplot(111) 
w = 0.3 
ax.bar(x-w, y,width=w,color='b',align='center') 
ax.bar(x, z,width=w,color='g',align='center') 
ax.bar(x+w, k,width=w,color='r',align='center') 
ax.xaxis_date() 
ax.autoscale(tight=True) 

plt.show() 

enter image description here

+0

Grazie, ma se ho 3 barre, sembra buono. Quando provo come 40 barre, incasina. Puoi aggiornare la tua soluzione per essere più scalabile? –

+0

Definisci "incasinato"?Le etichette X che si sovrappongono possono essere corrette usando 'autofmt_xdate()', che fa ruotare automaticamente le etichette. – jozzas

+0

Il problema non è la sovrapposizione delle etichette X, il fatto è che i valori y sono anch'essi sovrapposti. Come sistemarlo ? –

17

Il problema con l'utilizzo di date come valori x, è che se si vuole un grafico a barre come nella vostra seconda immagine, che stanno per essere sbagliato. Dovresti utilizzare un grafico a barre in pila (colori uno sopra l'altro) o raggruppare per data (una data "falsa" sull'asse x, in pratica solo raggruppando i punti dati).

import numpy as np 
import matplotlib.pyplot as plt 

N = 3 
ind = np.arange(N) # the x locations for the groups 
width = 0.27  # the width of the bars 

fig = plt.figure() 
ax = fig.add_subplot(111) 

yvals = [4, 9, 2] 
rects1 = ax.bar(ind, yvals, width, color='r') 
zvals = [1,2,3] 
rects2 = ax.bar(ind+width, zvals, width, color='g') 
kvals = [11,12,13] 
rects3 = ax.bar(ind+width*2, kvals, width, color='b') 

ax.set_ylabel('Scores') 
ax.set_xticks(ind+width) 
ax.set_xticklabels(('2011-Jan-4', '2011-Jan-5', '2011-Jan-6')) 
ax.legend((rects1[0], rects2[0], rects3[0]), ('y', 'z', 'k')) 

def autolabel(rects): 
    for rect in rects: 
     h = rect.get_height() 
     ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h), 
       ha='center', va='bottom') 

autolabel(rects1) 
autolabel(rects2) 
autolabel(rects3) 

plt.show() 

enter image description here

+0

se voglio mostrare come 100 giorni sugli assi x, come li calchi? –

+0

Si potrebbe facilmente generare le date richieste con 'datetime64' di numpy: ad es. Un mese vale: 'np.arange ('2012-02', '2012-03', dtype = 'datetime64 [D]')'. Potrebbe essere necessario riflettere più a fondo sul modo migliore per rappresentare questi dati se si dispone di 40 set di dati (come per un altro commento) che coprono più di 100 giorni. – jozzas

+0

puoi aggiornare il tuo codice con la soluzione proposta? –

0

In alternativa è possibile utilizzare una struttura di dati 2D e lasciate matplotlib gestire il vostro spaziatura delle colonne:

import numpy as np 
import matplotlib.pyplot as plt 

x = np.random.randn(1000, 3) 
bins = np.arange(-4.5, 4.5, 1) 
colors = ['red', 'tan', 'lime'] 

plt.hist(x, bins=bins, color=colors, label=colors) 
plt.legend() 
plt.xticks(bins + 0.5, ['bin ' + str(int(x)) for x in (bins + 0.5)]) 
plt.show() 

Aggiunta rwidth = 1 sta per eliminare ogni spazio tra le sbarre.

enter image description here

Source