¿Es posible anclar una anotación matplotlib a una coordenada de datos en el eje x, pero a una ubicación relativa en el eje y?

Tengo un gráfico donde me gustaría anotar una ubicación específica en el eje x con una flecha y una etiqueta:

  • La ubicación de la punta de la flecha debe especificarse exactamente en las coordenadas de los datos.
  • La flecha debe ser vertical, por lo tanto, la coordenada x del extremo romo de la flecha (y la etiqueta de texto) también se debe especificar exactamente en las coordenadas de datos.
  • Sin embargo, lo ideal sería poder especificar la posición y del extremo romo de la flecha en relación con el cuadro delimitador del eje, en lugar de los datos.

Mi solución de trabajo actual implica especificar las ubicaciones de la punta de la flecha y la etiqueta en las coordenadas de datos:

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) 

introduzca la descripción de la imagen aquí

Preferiría que la etiqueta permanezca en una posición constante en y, independientemente de cómo escale o mueva los ejes y. Puedo lograr el efecto deseado para una etiqueta de texto sin formato pasando una transformación xy combinada a 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) 

introduzca la descripción de la imagen aquí

Si reproduce esta figura y luego la desplaza o la escala, verá que el texto se mueve en x en relación con el cuadro de límite del eje, pero permanece en una posición fija en y. Por supuesto, esto todavía no me da la flecha, sin embargo. Esperaba poder usar el mismo enfoque con ax.annotate , pero esto no parece funcionar:

 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) 

La etiqueta y la flecha se colocan en y = 0.9 en coordenadas de datos, no en el 90% de la altura total del eje y:

introduzca la descripción de la imagen aquí

¿Hay una manera de especificar por separado los marcos de referencia para las transformaciones x e y aplicadas a un matplotlib.text.Annotation ?

Pase la transformación a los parámetros xycoords y textcoords lugar de al parámetro de transform . Al igual que:

 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)