2015-05-18 6 views
7

Ho un grafico dove desidero annotare una posizione specifica sul asse x con una freccia e un'etichetta:È possibile ancorare un'annotazione matplotlib a una coordinata di dati nell'asse x, ma a una posizione relativa nell'asse y?

  • La posizione della punta della freccia deve specificare esattamente in coordinate dati .
  • La freccia deve essere verticale, pertanto anche la coordinata x dell'estremità smussata della freccia (e l'etichetta di testo) deve essere specificata esattamente nelle coordinate dei dati.
  • Tuttavia, preferirei essere in grado di specificare la posizione y della fine smussata della freccia rispetto al riquadro di delimitazione dell'asse, piuttosto che i dati.

La mia soluzione di lavoro corrente coinvolge specificando le posizioni sia della punta della freccia e l'etichetta nei dati coordinate:

import numpy as np 
from matplotlib import pyplot as plt 
from matplotlib.transforms import blended_transform_factory 


x = np.random.randn(10000) 
r = 3 
label = 'foo' 
arrowprops = dict(fc='r', ec='k') 

def make_example_plot(): 
    fig, ax = plt.subplots(1, 1) 
    ax.hold(True) 
    counts, edges, patches = ax.hist(x) 
    return fig, ax 

fig, ax = make_example_plot() 
lo, hi = ax.get_ylim() 
ax.annotate(label, xy=(r, 0), xycoords='data', 
      xytext=(r, hi * 1.1), textcoords='data', fontsize='xx-large', 
      ha='center', va='center', color='r', arrowprops=arrowprops) 
ax.set_ylim(0, hi * 1.3) 

enter image description here

preferirei avere il soggiorno etichetta in una posizione costante in y indipendentemente da come ridimensiono o pan i y-axes. Posso ottenere l'effetto desiderato per un'etichetta di testo facendo passare una trasformazione xy miscelati per ax.text:

fig, ax = make_example_plot() 
tform = blended_transform_factory(ax.transData, ax.transAxes) 
ax.text(r, 0.9, label, fontsize='xx-large', color='r', transform=tform) 

enter image description here

Se riprodurre questa figura poi pan o una scala, si vedrà che il testo si muove in x rispetto al riquadro di delimitazione dell'asse, ma rimane in una posizione fissa in y. Certamente questo non mi dà ancora la freccia, comunque. Speravo che ho potuto utilizzare lo stesso approccio con ax.annotate, ma questo non sembra funzionare:

fig, ax = make_example_plot() 
tform = blended_transform_factory(ax.transData, ax.transAxes) 
ax.annotate(label, xy=(r, 0), xycoords='data', transform=tform, 
      xytext=(r, 0.9), textcoords='data', fontsize='xx-large', 
      ha='center', va='center', color='r', arrowprops=arrowprops) 

L'etichetta e la freccia sono posti a y = 0.9 in coordinate di dati, non al 90% dell'altezza totale del asse y:

enter image description here

c'è un modo per specificare separatamente i quadri di riferimento per la xey trasformazioni applicate a un matplotlib.text.Annotation?

risposta

7

Passare la trasformazione ai parametri xycoords e textcoords anziché al parametro transform. Così:

fig, ax = make_example_plot() 
tform = blended_transform_factory(ax.transData, ax.transAxes) 
ax.annotate(label, xy=(r, 0), xycoords=tform, 
      xytext=(r, 0.9), textcoords=tform, fontsize='xx-large', 
      ha='center', va='center', color='r', arrowprops=arrowprops) 
+0

Molto bello! L'opzione per passare direttamente una trasformazione per gli argomenti 'xycoords =' e 'textcoords =' non sembra essere menzionata nella documentazione. –

+0

Non è molto ovvio in effetti. In [pyplot.annotation] (http://matplotlib.org/1.4.0/api/pyplot_api.html#matplotlib.pyplot.annotate) c'è la seguente osservazione: _ "È possibile utilizzare un'istanza di Transform o Artist. Annotare gli assi per maggiori dettagli "_. Questo porta a [Usare Complesso Coordinate con Annotazione] (http://matplotlib.org/1.4.0/users/annotations_guide.html#using-complex-coordinate-with-annotation), che fornisce alcuni buoni esempi. – titusjan

+1

Wow, la documentazione potrebbe davvero fare qualche chiarimento ... –

Problemi correlati