Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I plot multiple X or Y axes in matplotlib?

Tags:

I'm currently using matplotlib to plot a measurement against 2 or 3 other measurements (sometimes categorical) on the x-axis. Currently, I am grouping the data on the x-axis into tuples and sorting them before plotting... the result looks something like the left image below. What I would like to do is to plot the data with multiple x-axes as you see in the right image. The grouping of the "treatment" x-axis labels would be icing on the cake.

alt text

like image 800
Adam Fraser Avatar asked Oct 12 '10 18:10

Adam Fraser


People also ask

How do I plot multiple Y-axis in matplotlib?

Create multiple y axes with a shared x axis. This is done by creating a twinx axes, turning all spines but the right one invisible and offset its position using set_position . Note that this approach uses matplotlib.

How do I make multiple axes in matplotlib?

We will use the add_axes() method of matplotlib module to add multiple axes to a figure.

How do I plot multiple things in matplotlib?

In Matplotlib, we can draw multiple graphs in a single plot in two ways. One is by using subplot() function and other by superimposition of second graph on the first i.e, all graphs will appear on the same plot.


1 Answers

First off, cool question! It's definitely possible with matplotlib >= 1.0.0. (The new spines functionality allows it)

It requires a fair bit of voodoo, though... My example is far from perfect, but hopefully it makes some sense:

import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl  def main():     #-- Generate some data ----------------------------------------------------     nx = 10     x = np.linspace(0, 2*np.pi, 10)     y = 2 * np.sin(x)      groups = [('GroupA', (x[0], x[nx//3])),               ('GroupB', (x[-2*nx//3], x[2*nx//3])),               ('GroupC', (x[-nx//3], x[-1]))]      #-- Plot the results ------------------------------------------------------     fig = plt.figure()     ax = fig.add_subplot(111)      # Give ourselves a bit more room at the bottom     plt.subplots_adjust(bottom=0.2)      ax.plot(x,y, 'k^')      # Drop the bottom spine by 40 pts     ax.spines['bottom'].set_position(('outward', 40))      # Make a second bottom spine in the position of the original bottom spine     make_second_bottom_spine(label='Treatment')      # Annotate the groups     for name, xspan in groups:         annotate_group(name, xspan)      plt.xlabel('Dose')     plt.ylabel('Response')     plt.title('Experimental Data')      plt.show()   def annotate_group(name, xspan, ax=None):     """Annotates a span of the x-axis"""     def annotate(ax, name, left, right, y, pad):         arrow = ax.annotate(name,                 xy=(left, y), xycoords='data',                 xytext=(right, y-pad), textcoords='data',                 annotation_clip=False, verticalalignment='top',                 horizontalalignment='center', linespacing=2.0,                 arrowprops=dict(arrowstyle='-', shrinkA=0, shrinkB=0,                         connectionstyle='angle,angleB=90,angleA=0,rad=5')                 )         return arrow     if ax is None:         ax = plt.gca()     ymin = ax.get_ylim()[0]     ypad = 0.01 * np.ptp(ax.get_ylim())     xcenter = np.mean(xspan)     left_arrow = annotate(ax, name, xspan[0], xcenter, ymin, ypad)     right_arrow = annotate(ax, name, xspan[1], xcenter, ymin, ypad)     return left_arrow, right_arrow  def make_second_bottom_spine(ax=None, label=None, offset=0, labeloffset=20):     """Makes a second bottom spine"""     if ax is None:         ax = plt.gca()     second_bottom = mpl.spines.Spine(ax, 'bottom', ax.spines['bottom']._path)     second_bottom.set_position(('outward', offset))     ax.spines['second_bottom'] = second_bottom      if label is not None:         # Make a new xlabel         ax.annotate(label,                  xy=(0.5, 0), xycoords='axes fraction',                  xytext=(0, -labeloffset), textcoords='offset points',                  verticalalignment='top', horizontalalignment='center')  if __name__ == '__main__':     main() 

Two bottom spines in a matplotlib plot

like image 66
Joe Kington Avatar answered Sep 19 '22 19:09

Joe Kington