Multiple axis in matplotlib with different scale

How can I use multiple scales in Matplotlib? I'm not talking about the primary and secondary axis, built on the same X axis, but something like many trends that have different scales, built on the same y axis and which can be identified by their colors.

For example, if I have trend1 ([0,1,2,3,4]) and trend2 ([5000,6000,7000,8000,9000]) to plot a time chart and want the two trends to be different colors and Y axis, different scales, how can I accomplish this with Matplotlib?

When I looked at Matplotlib, they say that they don’t have this yet, although this is definitely on their wish list. Is there any way to do this?

Are there any other python building tools that can do this?

+59
python matplotlib
Feb 01 '12 at 20:50
source share
4 answers

If I understand the question, you might be interested in this example in the Matplotlib gallery.

enter image description here

Yann's remark above gives a similar example.




Edit - The link above is fixed. The corresponding code is copied from the Matplotlib gallery:

 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") 
+88
Feb 01 2018-12-21T00:
source share

if you want to make very fast graphics with a secondary Y axis, then it is much easier to use the Pandas wrapper function and only 2 lines of code. Just write down your first column, and then build the second, but with secondary_y=True , for example:

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

It looks something like this:

enter image description here

You can do a few more things. See Pandas drawing doc .

+42
Jul 03 '14 at 0:09
source share

Since Steve Tjoah's answer always appears first and is mostly lonely when I search for several Y axes on Google, I decided to add a slightly modified version of his answer. This is the approach from this matplotlib example .

Causes:

  • Its modules sometimes fail for me under unknown circumstances and mysterious intern errors.
  • I don’t like loading exotic modules that I don’t know ( mpl_toolkits.axisartist , mpl_toolkits.axes_grid1 ).
  • The code below contains more explicit problem commands that people often stumble over (for example, one legend for multiple axes using viridis, ...) rather than implicit behavior.

Plot

 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') 
+35
Aug 28 '17 at 18:11
source share

Download something quickly to draw several y axes separating the x axis using @ joe-kington's : enter image description here

 # 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() 
+18
Jan 15 '15 at 14:45
source share



All Articles