¿Cómo puedo hacer que las tags xtick de una gráfica sean dibujos simples usando matplotlib?

En lugar de que las palabras o los números sean las tags de marca del eje x, quiero dibujar un dibujo simple (hecho de líneas y círculos) como la etiqueta de cada marca x es posible? Si es así, ¿cuál es la mejor manera de hacerlo en matplotlib?

Quitaría las tags de tick y reemplazaría el texto con parches . Aquí hay un breve ejemplo de cómo realizar esta tarea:

import matplotlib.pyplot as plt import matplotlib.patches as patches # define where to put symbols vertically TICKYPOS = -.6 fig = plt.figure() ax = fig.add_subplot(111) ax.plot(range(10)) # set ticks where your images will be ax.get_xaxis().set_ticks([2,4,6,8]) # remove tick labels ax.get_xaxis().set_ticklabels([]) # add a series of patches to serve as tick labels ax.add_patch(patches.Circle((2,TICKYPOS),radius=.2, fill=True,clip_on=False)) ax.add_patch(patches.Circle((4,TICKYPOS),radius=.2, fill=False,clip_on=False)) ax.add_patch(patches.Rectangle((6-.1,TICKYPOS-.05),.2,.2, fill=True,clip_on=False)) ax.add_patch(patches.Rectangle((8-.1,TICKYPOS-.05),.2,.2, fill=False,clip_on=False)) 

Esto da como resultado la siguiente figura:

introduzca la descripción de la imagen aquí

Es clave establecer clip_on en False , de lo contrario no se mostrarán los patches fuera de los ejes. Las coordenadas y los tamaños (radio, ancho, altura, etc.) de los parches dependerán de dónde estén sus ejes en la figura. Por ejemplo, si está considerando hacer esto con subplots, deberá ser sensible a la ubicación de los parches para no superponerse con ningún otro eje. Puede valer la pena su tiempo investigando Transformaciones y definiendo las posiciones y tamaños en otra unidad (Ejes, Figura o pantalla).

Si tiene archivos de imagen específicos que desea usar para los símbolos, puede usar la clase BboxImage para crear artistas que se agregarán a los ejes en lugar de parches. Por ejemplo, hice un icono simple con el siguiente script:

 import matplotlib.pyplot as plt fig = plt.figure(figsize=(1,1),dpi=400) ax = fig.add_axes([0,0,1,1],frameon=False) ax.set_axis_off() ax.plot(range(10),linewidth=32) ax.plot(range(9,-1,-1),linewidth=32) fig.savefig('thumb.png') 

produciendo esta imagen:

introduzca la descripción de la imagen aquí

Luego creé una BboxImage en la ubicación donde quiero la etiqueta de marca y del tamaño que quiero:

 lowerCorner = ax.transData.transform((.8,TICKYPOS-.2)) upperCorner = ax.transData.transform((1.2,TICKYPOS+.2)) bbox_image = BboxImage(Bbox([lowerCorner[0], lowerCorner[1], upperCorner[0], upperCorner[1], ]), norm = None, origin=None, clip_on=False, ) 

Noté cómo utilicé la transformación de transData para convertir de unidades de datos a unidades de datos, que se requieren en la definición de Bbox .

Ahora leo la imagen usando la rutina imread , y establezco sus resultados (una matriz numpy) a los datos de bbox_image y agrego el artista a los ejes:

 bbox_image.set_data(imread('thumb.png')) ax.add_artist(bbox_image) 

Esto da como resultado una figura actualizada: introduzca la descripción de la imagen aquí

Si usa imágenes directamente, asegúrese de importar las clases y métodos requeridos:

 from matplotlib.image import BboxImage,imread from matplotlib.transforms import Bbox 

La otra respuesta tiene algunos inconvenientes porque utiliza coordenadas estáticas. Por lo tanto, no funcionará al cambiar el tamaño de la figura o al hacer zoom y desplazar el gráfico.

Una mejor opción es definir directamente las posiciones en los sistemas de coordenadas elegidos. Para el xaxis tiene sentido usar coordenadas de datos para la posición x y coordenadas de los ejes para la posición y.

El uso de matplotlib.offsetbox es hace esto bastante simple. Lo siguiente ubicaría un cuadro con un círculo y un cuadro con una imagen en las coordenadas (-5,0) y (5,0) respectivamente, y los desplazará un poco hacia abajo, de modo que se verán como si fueran marcas de verificación.

 import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.offsetbox import (DrawingArea, OffsetImage,AnnotationBbox) fig, ax = plt.subplots() ax.plot([-10,10], [1,3]) # Annotate the 1st position with a circle patch da = DrawingArea(20, 20, 10, 10) p = mpatches.Circle((0, 0), 10) da.add_artist(p) ab = AnnotationBbox(da, (-5,0), xybox=(0, -7), xycoords=("data", "axes fraction"), box_alignment=(.5, 1), boxcoords="offset points", bboxprops={"edgecolor" : "none"}) ax.add_artist(ab) # Annotate the 2nd position with an image arr_img = plt.imread("http://sofes.miximages.com/python/FmX9n.png", format='png') imagebox = OffsetImage(arr_img, zoom=0.2) imagebox.image.axes = ax ab = AnnotationBbox(imagebox, (5,0), xybox=(0, -7), xycoords=("data", "axes fraction"), boxcoords="offset points", box_alignment=(.5, 1), bboxprops={"edgecolor" : "none"}) ax.add_artist(ab) plt.show() 

introduzca la descripción de la imagen aquí


Tenga en cuenta que muchas formas existen como símbolos Unicode, de modo que uno puede simplemente establecer las marcas de verificación con esos símbolos. Para obtener una solución de este tipo, consulte ¿Cómo usar una forma de color como vetas en matplotlib o en el mar?