instalar - matplotlib python 3
eje mĂșltiple en matplotlib con diferentes escalas (4)
¿Cómo se pueden implementar múltiples escalas en Matplotlib? No estoy hablando del eje primario y secundario trazados contra el mismo eje x, sino de muchas tendencias que tienen escalas diferentes trazadas en el mismo eje y que pueden identificarse por sus colores.
Por ejemplo, si tengo trend1 ([0,1,2,3,4])
y 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é en Matplotlib, dicen que no tienen esto por ahora aunque definitivamente está en su lista de deseos. ¿Hay alguna forma de que esto suceda?
¿Hay alguna otra herramienta de trazado para python que pueda hacer que esto suceda?
Arrancar algo rápido para trazar múltiples ejes y compartiendo un eje x usando @joe-kington''s respuesta de @joe-kington''s :
# 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()
Como la respuesta de Steve Tjoa siempre aparece primero y en su mayoría solo cuando busco múltiples 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 siguiente código contiene comandos más explícitos de problemas con los que la gente suele tropezar (como la leyenda única para ejes múltiples, usando viridis, ...) en lugar de comportamientos implícitos.
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'')
Si entiendo la pregunta, puede interesarte en este ejemplo en la galería de Matplotlib.
El comentario anterior de Yann proporciona un ejemplo similar.
Editar - Enlace arriba fijado. Código correspondiente copiado de la galería 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 quieres hacer gráficas muy rápidas con el eje Y secundario, entonces hay una manera mucho más fácil usando 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 más o menos a continuación:
También puedes hacer algunas cosas más. Echa un vistazo a Pandas conspirando doc .