Matplotlib: overlays with different scales?

So far, I have the following code:

colors = ('k','r','b') ax = [] for i in range(3): ax.append(plt.axes()) plt.plot(datamatrix[:,0],datamatrix[:,i],colors[i]+'o') ax[i].set(autoscale_on=True) 

With the autoscale_on=True option for each axis, I thought that each graph should have its own y axis boundaries, but it seems that they all have the same value (even if they have different axes). How to set them to scale to show the range of each datamatrix[:,i] (just an explicit .set_ylim() call?). And also, how can I create an offset y axis for a third variable ( datamatrix[:,2] ) that could be higher? Thanks to everyone.

+37
python matplotlib
Oct 11 '11 at 23:27
source share
3 answers

It sounds like what you want is subtitles ... What you are doing now doesn't make much sense (or I'm really confused by your piece of code, anyway ...).

Try something else like this:

 import matplotlib.pyplot as plt import numpy as np fig, axes = plt.subplots(nrows=3) colors = ('k', 'r', 'b') for ax, color in zip(axes, colors): data = np.random.random(1) * np.random.random(10) ax.plot(data, marker='o', linestyle='none', color=color) plt.show() 

enter image description here

Edit:

If you don't want to use subheadings, your code snippet makes more sense.

You are trying to add three axes directly above each other. Matplotlib recognizes that there is already a subtitle in that exactly the size and location in the drawing, and therefore it returns the same axis object every time. In other words, if you look at your ax list, you will see that it is still the same object.

If you really want to do this, you will need to reset fig._seen to an empty dict each time you add axes. You probably really don't want to do this.

Instead of putting three independent graphics on top of each other, take a look at using twinx .

eg.

 import matplotlib.pyplot as plt import numpy as np # To make things reproducible... np.random.seed(1977) fig, ax = plt.subplots() # Twin the x-axis twice to make independent y-axes. axes = [ax, ax.twinx(), ax.twinx()] # Make some space on the right side for the extra y-axis. fig.subplots_adjust(right=0.75) # Move the last y-axis spine over to the right by 20% of the width of the axes axes[-1].spines['right'].set_position(('axes', 1.2)) # 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. axes[-1].set_frame_on(True) axes[-1].patch.set_visible(False) # And finally we get to plot things... colors = ('Green', 'Red', 'Blue') for ax, color in zip(axes, colors): data = np.random.random(1) * np.random.random(10) ax.plot(data, marker='o', linestyle='none', color=color) ax.set_ylabel('%s Thing' % color, color=color) ax.tick_params(axis='y', colors=color) axes[0].set_xlabel('X-axis') plt.show() 

enter image description here

+91
Oct 12 2018-11-11T00:
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() 
+7
Jan 15 '15 at
source share

Thanks to Joe Kington's answer, I could come up with a solution for my requirement that all additional Y axes be on the left side of the graph.

I would still like to know how to do it right, because it is just work around:

 import matplotlib.pyplot as plt import numpy as np # To make things reproducible... np.random.seed(1977) fig, ax = plt.subplots() # Twin the x-axis twice to make independent y-axes. axes = [ax, ax.twinx(), ax.twinx()] # Make some space on the right side for the extra y-axis. fig.subplots_adjust(right=0.75) # Move the last y-axis spine over to the right by 20% of the width of the axes axes[1].spines['right'].set_position(('axes', -0.25)) axes[2].spines['right'].set_position(('axes', -0.5)) # 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. axes[-1].set_frame_on(True) axes[-1].patch.set_visible(False) # And finally we get to plot things... colors = ('Green', 'Red', 'Blue') intAxNo = 0 for ax, color in zip(axes, colors): intAxNo += 1 data = np.random.random(1) * np.random.random(10) ax.plot(data, marker='o', linestyle='none', color=color) if (intAxNo > 1): if (intAxNo == 2): ax.set_ylabel('%s Thing' % color, color=color, labelpad = -40 ) elif (intAxNo == 3): ax.set_ylabel('%s Thing' % color, color=color, labelpad = -45 ) ax.get_yaxis().set_tick_params(direction='out') else: ax.set_ylabel('%s Thing' % color, color=color, labelpad = +0 ) ax.tick_params(axis='y', colors=color) axes[0].set_xlabel('X-axis') plt.show() 

enter image description here

+3
Aug 08 '16 at 15:57
source share



All Articles