Ejes multiples en matplotlib con diferentes escalas.

¿Cómo se pueden implementar múltiples escalas en Matplotlib? No estoy hablando de los ejes primario y secundario trazados contra el mismo eje x, sino algo parecido a muchas tendencias que tienen diferentes escalas trazadas en el mismo eje y y que se pueden identificar por sus colores.

Por ejemplo, si tengo la trend1 ([0,1,2,3,4]) y la trend2 ([5000,6000,7000,8000,9000]) para trazar en función del tiempo y quiero que las dos tendencias sean de colores diferentes y en el eje Y, diferentes escalas, ¿cómo puedo lograr esto con Matplotlib?

Cuando miré Matplotlib, dicen que no tienen esto por ahora, aunque definitivamente está en su lista de deseos. ¿Hay alguna forma de hacer que esto suceda?

¿Existen otras herramientas de trazado para python que puedan hacer que esto suceda?

Si entiendo la pregunta, puede interesarle este ejemplo en la galería de Matplotlib.

introduzca la descripción de la imagen aquí

El comentario de Yann anterior proporciona un ejemplo similar.


Editar – Enlace arriba arreglado. Código correspondiente copiado de la galería de matplotlib:

 from mpl_toolkits.axes_grid1 import host_subplot import mpl_toolkits.axisartist as AA import matplotlib.pyplot as plt host = host_subplot(111, axes_class=AA.Axes) plt.subplots_adjust(right=0.75) par1 = host.twinx() par2 = host.twinx() offset = 60 new_fixed_axis = par2.get_grid_helper().new_fixed_axis par2.axis["right"] = new_fixed_axis(loc="right", axes=par2, offset=(offset, 0)) par2.axis["right"].toggle(all=True) host.set_xlim(0, 2) host.set_ylim(0, 2) host.set_xlabel("Distance") host.set_ylabel("Density") par1.set_ylabel("Temperature") par2.set_ylabel("Velocity") p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature") p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity") par1.set_ylim(0, 4) par2.set_ylim(1, 65) host.legend() host.axis["left"].label.set_color(p1.get_color()) par1.axis["right"].label.set_color(p2.get_color()) par2.axis["right"].label.set_color(p3.get_color()) plt.draw() plt.show() #plt.savefig("Test") 

Si desea hacer trazados muy rápidos con el eje Y secundario, entonces es mucho más fácil usar la función de envoltura de Pandas y solo 2 líneas de código. Simplemente trace su primera columna y luego trace la segunda, pero con el parámetro secondary_y=True , así:

 df.A.plot(label="Points", legend=True) df.B.plot(secondary_y=True, label="Comments", legend=True) 

Esto se vería como a continuación:

introduzca la descripción de la imagen aquí

Puedes hacer algunas cosas más también. Echa un vistazo a Pandas ploting doc .

Como la respuesta de Steve Tjoa siempre aparece primero y casi sola cuando busco varios ejes y en Google, decidí agregar una versión ligeramente modificada de su respuesta. Este es el enfoque de este ejemplo matplotlib .

Razones:

  • Sus módulos a veces me fallan en circunstancias desconocidas y errores crípticos internos.
  • No me gusta cargar módulos exóticos que no conozco ( mpl_toolkits.axisartist , mpl_toolkits.axes_grid1 ).
  • El código a continuación contiene comandos más explícitos de problemas con los que la gente suele tropezar (como leyenda única para varios ejes, usando viridis, …) en lugar de un comportamiento implícito.

Trama

 import matplotlib.pyplot as plt fig = plt.figure() host = fig.add_subplot(111) par1 = host.twinx() par2 = host.twinx() host.set_xlim(0, 2) host.set_ylim(0, 2) par1.set_ylim(0, 4) par2.set_ylim(1, 65) host.set_xlabel("Distance") host.set_ylabel("Density") par1.set_ylabel("Temperature") par2.set_ylabel("Velocity") color1 = plt.cm.viridis(0) color2 = plt.cm.viridis(0.5) color3 = plt.cm.viridis(.9) p1, = host.plot([0, 1, 2], [0, 1, 2], color=color1,label="Density") p2, = par1.plot([0, 1, 2], [0, 3, 2], color=color2, label="Temperature") p3, = par2.plot([0, 1, 2], [50, 30, 15], color=color3, label="Velocity") lns = [p1, p2, p3] host.legend(handles=lns, loc='best') # right, left, top, bottom par2.spines['right'].set_position(('outward', 60)) # no x-ticks par2.xaxis.set_ticks([]) # Sometimes handy, same for xaxis #par2.yaxis.set_ticks_position('right') host.yaxis.label.set_color(p1.get_color()) par1.yaxis.label.set_color(p2.get_color()) par2.yaxis.label.set_color(p3.get_color()) plt.savefig("pyplot_multiple_y-axis.png", bbox_inches='tight') 

Arranque algo rápido para trazar varios ejes y compartiendo un eje x usando la respuesta de @ joe-kington : introduzca la descripción de la imagen aquí

 # d = Pandas Dataframe, # ys = [ [cols in the same y], [cols in the same y], [cols in the same y], .. ] def chart(d,ys): from itertools import cycle fig, ax = plt.subplots() axes = [ax] for y in ys[1:]: # Twin the x-axis twice to make independent y-axes. axes.append(ax.twinx()) extra_ys = len(axes[2:]) # Make some space on the right side for the extra y-axes. if extra_ys>0: temp = 0.85 if extra_ys<=2: temp = 0.75 elif extra_ys<=4: temp = 0.6 if extra_ys>5: print 'you are being ridiculous' fig.subplots_adjust(right=temp) right_additive = (0.98-temp)/float(extra_ys) # Move the last y-axis spine over to the right by x% of the width of the axes i = 1. for ax in axes[2:]: ax.spines['right'].set_position(('axes', 1.+right_additive*i)) ax.set_frame_on(True) ax.patch.set_visible(False) ax.yaxis.set_major_formatter(matplotlib.ticker.OldScalarFormatter()) i +=1. # To make the border of the right-most axis visible, we need to turn the frame # on. This hides the other plots, however, so we need to turn its fill off. cols = [] lines = [] line_styles = cycle(['-','-','-', '--', '-.', ':', '.', ',', 'o', 'v', '^', '<', '>', '1', '2', '3', '4', 's', 'p', '*', 'h', 'H', '+', 'x', 'D', 'd', '|', '_']) colors = cycle(matplotlib.rcParams['axes.color_cycle']) for ax,y in zip(axes,ys): ls=line_styles.next() if len(y)==1: col = y[0] cols.append(col) color = colors.next() lines.append(ax.plot(d[col],linestyle =ls,label = col,color=color)) ax.set_ylabel(col,color=color) #ax.tick_params(axis='y', colors=color) ax.spines['right'].set_color(color) else: for col in y: color = colors.next() lines.append(ax.plot(d[col],linestyle =ls,label = col,color=color)) cols.append(col) ax.set_ylabel(', '.join(y)) #ax.tick_params(axis='y') axes[0].set_xlabel(d.index.name) lns = lines[0] for l in lines[1:]: lns +=l labs = [l.get_label() for l in lns] axes[0].legend(lns, labs, loc=0) plt.show()