Matplotlib: etiqueta del eje y con múltiples colores.

Me preguntaba cuál sería la mejor manera de hacer una etiqueta y donde cada palabra en la etiqueta puede ser de un color diferente.

La razón por la que me gustaría esto es porque haré trazados que contendrán curvas (Campos eléctricos y Campos de potencial vectorial). Estas curvas serán de diferentes colores y me gustaría mostrarlas en las tags. El siguiente es un ejemplo simplificado, utilizando una publicación anterior ( Matplotlib varios colores en tags de marca ) para acercarse. Esta publicación funciona bien para el eje x, sin embargo, no espacia / ordena el eje y correctamente.

Otra publicación tenía una pregunta similar ( coloreado parcial del texto en matplotlib ), pero la primera respuesta ya no funcionó en absoluto y la segunda respuesta hace que guarde el archivo como un archivo .ps.

Mi código de ejemplo es

import numpy as np import matplotlib.pyplot as plt from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker ax = plt.subplot(111) x = np.linspace(0,10,10) y1 = x y2 = x**2 ax.plot(x,y1,color='r',label='data1') ax.plot(x,y2,color='b',label='data2') ax.set_xticks([]) # empty xticklabels ax.set_yticks([]) # empty xticklabels # x-axis label xbox1 = TextArea("Data1-x ", textprops=dict(color="r", size=15)) xbox2 = TextArea("and ", textprops=dict(color="k", size=15)) xbox3 = TextArea("Data2-x ", textprops=dict(color="b", size=15)) xbox = HPacker(children=[xbox1, xbox2, xbox3], align="center", pad=0, sep=5) anchored_xbox = AnchoredOffsetbox(loc=3, child=xbox, pad=0., frameon=False, bbox_to_anchor=(0.3, -0.07), bbox_transform=ax.transAxes, borderpad=0.) # y-axis label ybox1 = TextArea("Data1-y ", textprops=dict(color="r", size=15,rotation='vertical')) ybox2 = TextArea("and ", textprops=dict(color="k", size=15,rotation='vertical')) ybox3 = TextArea("Data2-y ", textprops=dict(color="b", size=15,rotation='vertical')) ybox = VPacker(children=[ybox1, ybox2, ybox3], align="center", pad=0, sep=5) anchored_ybox = AnchoredOffsetbox(loc=8, child=ybox, pad=0., frameon=False, bbox_to_anchor=(-0.08, 0.4), bbox_transform=ax.transAxes, borderpad=0.) ax.add_artist(anchored_xbox) ax.add_artist(anchored_ybox) plt.legend() plt.show() 

Imagen de ejemplo

¡Gracias por la ayuda!

Estabas casi allí. Solo necesita especificar la alineación del texto usando ha = ‘left’, va = ‘bottom’. (Y voltear el orden de los objetos TextArea pasados ​​a VPacker).

 import numpy as np import matplotlib.pyplot as plt from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker ax = plt.subplot(111) x = np.linspace(0,10,10) y1 = x y2 = x**2 ax.plot(x,y1,color='r',label='data1') ax.plot(x,y2,color='b',label='data2') ybox1 = TextArea("Data2-y ", textprops=dict(color="r", size=15,rotation=90,ha='left',va='bottom')) ybox2 = TextArea("and ", textprops=dict(color="k", size=15,rotation=90,ha='left',va='bottom')) ybox3 = TextArea("Data1-y ", textprops=dict(color="b", size=15,rotation=90,ha='left',va='bottom')) ybox = VPacker(children=[ybox1, ybox2, ybox3],align="bottom", pad=0, sep=5) anchored_ybox = AnchoredOffsetbox(loc=8, child=ybox, pad=0., frameon=False, bbox_to_anchor=(-0.08, 0.4), bbox_transform=ax.transAxes, borderpad=0.) ax.add_artist(anchored_ybox) plt.legend() plt.show() 

introduzca la descripción de la imagen aquí

Mejor aún, aquí hay una función que hace que las tags utilicen una lista arbitraria de cadenas y colores:

 import numpy as np import matplotlib.pyplot as plt def multicolor_ylabel(ax,list_of_strings,list_of_colors,axis='x',anchorpad=0,**kw): """this function creates axes labels with multiple colors ax specifies the axes object where the labels should be drawn list_of_strings is a list of all of the text items list_if_colors is a corresponding list of colors for the strings axis='x', 'y', or 'both' and specifies which label(s) should be drawn""" from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker # x-axis label if axis=='x' or axis=='both': boxes = [TextArea(text, textprops=dict(color=color, ha='left',va='bottom',**kw)) for text,color in zip(list_of_strings,list_of_colors) ] xbox = HPacker(children=boxes,align="center",pad=0, sep=5) anchored_xbox = AnchoredOffsetbox(loc=3, child=xbox, pad=anchorpad,frameon=False,bbox_to_anchor=(0.2, -0.09), bbox_transform=ax.transAxes, borderpad=0.) ax.add_artist(anchored_xbox) # y-axis label if axis=='y' or axis=='both': boxes = [TextArea(text, textprops=dict(color=color, ha='left',va='bottom',rotation=90,**kw)) for text,color in zip(list_of_strings[::-1],list_of_colors) ] ybox = VPacker(children=boxes,align="center", pad=0, sep=5) anchored_ybox = AnchoredOffsetbox(loc=3, child=ybox, pad=anchorpad, frameon=False, bbox_to_anchor=(-0.10, 0.2), bbox_transform=ax.transAxes, borderpad=0.) ax.add_artist(anchored_ybox) ax = plt.subplot(111) x = np.linspace(0,10,1000) y1 = np.sin(x) y2 = np.sin(2*x) ax.plot(x,y1,color='r') ax.plot(x,y2,color='b') multicolor_ylabel(ax,('Line1','and','Line2','with','extra','colors!'),('r','k','b','k','m','g'),axis='both',size=15,weight='bold') plt.show() 

Todavía se necesita un poco de manipulación con las posiciones en la palabra clave “bbox_to_anchor”.

introduzca la descripción de la imagen aquí