2016-03-03 20 views
6

Ho una trama istogramma che potrebbe essere replicata con la MWE di seguito:Etichettatura un bidone matplotlib istogramma con una freccia

import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sns 
import numpy as np 

pd.Series(np.random.normal(0, 100, 1000)).plot(kind='hist', bins=50) 

che crea una trama simile a questo:

example histogram

Come sarebbe Vado quindi a etichettare il cestino con una freccia per un dato intero?

Ad esempio si veda sotto, in cui una freccia etichette scomparto contenente il numero intero 300.

example with bin of integer labelled

EDIT: devo aggiungere idealmente le coordinate y della freccia devono essere impostate automaticamente l'altezza del bar è etichettatura - se possibile!

risposta

4

è possibile utilizzare annotate per aggiungere una freccia:

import pandas as pd 
import matplotlib.pyplot as plt 
#import seaborn as sns 
import numpy as np 

fig, ax = plt.subplots() 
series = pd.Series(np.random.normal(0, 100, 1000)) 
series.plot(kind='hist', bins=50, ax=ax) 
ax.annotate("", 
      xy=(300, 5), xycoords='data', 
      xytext=(300, 20), textcoords='data', 
      arrowprops=dict(arrowstyle="->", 
          connectionstyle="arc3"), 
      ) 

In questo esempio, ho aggiunto una freccia che va da coordinate (300, 20) a (300, 5).

Al fine di scalare automaticamente la freccia per il valore nel cestino, è possibile utilizzare matplotlib hist per tracciare l'istogramma e ottenere i valori indietro e quindi utilizzare NumPy where per trovare quale bin corrisponde alla posizione desiderata.

import pandas as pd 
import matplotlib.pyplot as plt 
#import seaborn as sns 
import numpy as np 

nbins = 50 
labeled_bin = 200 

fig, ax = plt.subplots() 

series = pd.Series(np.random.normal(0, 100, 1000)) 

## plot the histogram and return the bin position and values 
ybins, xbins, _ = ax.hist(series, bins=nbins) 

## find out in which bin belongs the position where you want the label 
ind_bin = np.where(xbins >= labeled_bin)[0] 
if len(ind_bin) > 0 and ind_bin[0] > 0: 
    ## get position and value of the bin 
    x_bin = xbins[ind_bin[0]-1]/2. + xbins[ind_bin[0]]/2. 
    y_bin = ybins[ind_bin[0]-1] 
    ## add the arrow 
    ax.annotate("", 
       xy=(x_bin, y_bin + 5), xycoords='data', 
       xytext=(x_bin, y_bin + 20), textcoords='data', 
       arrowprops=dict(arrowstyle="->", 
           connectionstyle="arc3"), 
           ) 
else: 
    print "Labeled bin is outside range" 
+0

Grazie per la risposta, di ampliare ulteriormente questa domanda è si possibile impostare automaticamente la posizione y della freccia in base all'altezza del cestino? – BML91

+0

@ BML91 Sì, è possibile ... fammi modificare la mia risposta –

+0

@ BML91 Vedi la mia modifica :-) –

2

@Julien Spronck ha mostrato il modo migliore, penso. In alternativa, è anche possibile utilizzare arrow; il codice di esempio può essere trovato sotto. La coordinata y viene determinata automaticamente calcolando quanti elementi ci sono in un certo bin (con una certa tolleranza che puoi definire tu stesso). Puoi giocare con i parametri (lunghezza della freccia, lunghezza della freccia). Ecco il codice:

import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sns 
import numpy as np 

mySer = pd.Series(np.random.normal(0, 100, 1000)) 
mySer.plot(kind='hist', bins=50) 

# that is where you want to add the arrow 
ind = 200 
# determine how many elements you have in the bin (with a certain tolerance) 
n = len(mySer[(mySer > ind*0.95) & (mySer < ind*1.05)]) 

# define length of the arrow 
lenArrow = 10 
lenHead = 2 
wiArrow = 5 
plt.arrow(ind, n+lenArrow+lenHead, 0, -lenArrow, head_width=wiArrow+3, head_length=lenHead, width=wiArrow, fc='k', ec='k') 

plt.show() 

Questo vi dà il seguente output (per 200 anziché 300 come nel tuo esempio):

enter image description here