2015-12-03 23 views
7

TL'DR, i grafici a barre verticali sono mostrati in modo convenzionale - le cose si allineano da sinistra a destra. Tuttavia, quando viene convertito in un grafico a barre orizzontali (da bar a barh), tutto è capovolto. Ad esempio, per un grafico a barre raggruppato, non solo l'ordine della barra raggruppata è sbagliato, anche l'ordine di ogni gruppo è sbagliato.Matstotlib, il grafico a barre orizzontale (barh) è sottosopra

Per esempio, il grafico da http://dwheelerau.com/2014/05/28/pandas-data-analysis-new-zealanders-and-their-sheep/

enter image description here

Se si guarda da vicino, vi accorgerete che il il bar e la leggenda sono in ordine inverso - Manzo mostra in cima nella leggenda, ma in fondo in il grafo.

Come la demo più semplice, ho cambiato kind='bar',-kind='barh', da questo grafico https://plot.ly/pandas/bar-charts/#pandas-grouped-bar-chart e il risultato si presenta così: https://plot.ly/7/~xpt/

cioè le barre nel grafico a barre raggruppate orizzontale è ordinato a testa in giù.

Come ripararlo?

MODIFICA: @Ajean, in realtà non solo l'ordine della barra raggruppata è errato, anche l'ordine di ogni gruppo è sbagliato. Il grafico da Simple customization of matplotlib/pandas bar chart (labels, ticks, etc.) lo mostra chiaramente:

the order of the each group is wrong

possiamo vedere che l'ordine è non convenzionale troppo, perché la gente si aspetterebbe il grafico sia top-down, con "AAA" in alto, non il fondo .

Se si esegue la ricerca di "Excel capovolta", le persone si lamentano di questo in Excel in tutti i luoghi. Microsoft Excel ha una correzione, Matplotlib/Panda/Searborn/Ploty/etc ha una soluzione per questo?

+0

È possibile passare manualmente le maniglie in 'plt.legend' e ordinarle come si desidera. – DilithiumMatrix

+0

Nah, il problema non è la leggenda, dai un'occhiata a https://plot.ly/7/~xpt/, A, B, C, D è nell'ordine corretto. È la barra che è nell'ordine sbagliato. – xpt

+2

Hmmm .... Io non penso che questo sia un * bug * di per sé, tanto quanto un problema di convenzione. Le barre sono generalmente elencate in ordine crescente (vale a dire il primo elemento è "0", il secondo elemento è "1", ecc.). E nel caso qui esposto "bottom-up" ("up" significa "superiore"), ha senso che le prime barre si trovino in fondo a ciascun gruppo. Il problema è, penso, che la * convenzione * per una legenda sia "dall'alto in basso" piuttosto che "dal basso verso l'alto". Se vuoi davvero invertirlo, probabilmente cambiare la convenzione delle leggende sarebbe più facile. – Ajean

risposta

7

Credo che l'ordine errato congiunto di gruppi e sottogruppi si riduce a una singola funzione: che l'asse y aumenta verso l'alto, come in una trama normale. Provare a invertire il y asse di tuoi assi come in questo esempio panda-less:

import numpy as np 
import matplotlib.pyplot as plt 

x=range(5) 
y=np.random.randn(5) 

#plot1: bar 
plt.figure() 
plt.bar(x,y) 

#plot2: barh, wrong order 
plt.figure() 
plt.barh(x,y) 

#plot3: barh with correct order: top-down y axis 
plt.figure() 
plt.barh(x,y) 
plt.gca().invert_yaxis() 
+0

No, difficilmente lo farà. Finirai per invertire l'ordine degli anni: 1994-2012 al suo ordine inverso. –

+0

@CTZhu ma questo è un po 'il punto, non è vero? Se in una trama 'bar' 1994-> 2012 va da sinistra a destra, quindi per un' barh' si potrebbe volere lo stesso ordine dall'alto verso il basso. La modifica dell'OP che dice "è in realtà non solo l'ordine della barra raggruppata è sbagliata, anche l'ordine di ogni gruppo è sbagliato" mi ha suggerito che questa è una soluzione valida. Se viene e mi dice che non lo è, cancellerò la risposta. –

+0

@AndrasDeak, Sì, Andras, è esattamente quello che volevo. Potresti inserire una soluzione di panda per favore? [Questo] (https://gist.github.com/suntong/0e04741f28d999eafc04) è il massimo che posso andare io stesso. Parti da lì se vuoi. Grazie. – xpt

0

io ritengo che ciò è un problema, cioè, la posizione y delle barre non vengono assegnati correttamente. La patch è tuttavia relativamente semplice:

Questo è solo un ordine corretto di barre, e questo è chiamato ..., l'ordine giusto. Tutto ciò che non è l'ordine giusto, è quindi un ordine buggy. : P

In [63]: 

print df 
     Total_beef_cattle Total_dairy_cattle Total_sheep Total_deer \ 
1994   0.000000   0.000000  0.000000 0.000000 
2002   -11.025827   34.444950 -20.002034 33.858009 
2003   -8.344764   32.882482 -20.041908 37.229441 
2004   -11.895128   34.207998 -20.609926 42.707754 
2005   -12.366101   32.506699 -19.379727 38.499840 

     Total_pigs Total_horses 
1994 0.000000  0.000000 
2002 -19.100637  11.811093 
2003 -10.766476  18.504488 
2004 -8.072078  13.376472 
2005 -19.230733 -100.000000 
In [64]: 

ax = df.plot(kind='barh', sort_columns=True) 

#Get the actual bars 
bars = [item for item in ax.get_children() if isinstance(item, matplotlib.patches.Rectangle)] 
bars = bars[:df.size] 

#Reset the y positions for each bar 
bars_y = [plt.getp(item, 'y') for item in bars] 
for B, Y in zip(bars, np.flipud(np.array(bars_y).reshape(df.shape[::-1])).ravel()): 
    B.set_y(Y) 

enter image description here

0

correzione generale è semplice:

handles, labels = axis.get_legend_handles_labels() 
# reverse to keep order consistent 
axis.legend(reversed(handles), reversed(labels), loc='upper left') 
4

credo che la soluzione più semplice per questo problema è quello di invertire la dataframe panda prima della stampa.Per esempio:

df = df.iloc[::-1] 
df.plot.barh(stacked=True); 

A mio parere questo è un bug nella funzione di panda Barh. Almeno gli utenti dovrebbero essere in grado di passare un argomento come reverse_order = True ecc.

+1

Questa dovrebbe essere la risposta accettata. – dangom

Problemi correlati