Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib subplots_adjust hspace so titles and xlabels don't overlap?

With, say, 3 rows of subplots in matplotlib, xlabels of one row can overlap the title of the next. One has to fiddle with pl.subplots_adjust(hspace), which is annoying.

Is there a recipe for hspace that prevents overlaps and works for any nrow?

""" matplotlib xlabels overlap titles ? """
import sys
import numpy as np
import pylab as pl

nrow = 3
hspace = .4  # of plot height, titles and xlabels both fall within this ??
exec "\n".join( sys.argv[1:] )  # nrow= ...

y = np.arange(10)
pl.subplots_adjust( hspace=hspace )

for jrow in range( 1, nrow+1 ):
    pl.subplot( nrow, 1, jrow )
    pl.plot( y**jrow )
    pl.title( 5 * ("title %d " % jrow) )
    pl.xlabel( 5 * ("xlabel %d " % jrow) )

pl.show()

My versions:

  • matplotlib 0.99.1.1,
  • Python 2.6.4,
  • Mac OSX 10.4.11,
  • backend: Qt4Agg (TkAgg => Exception in Tkinter callback)

(For many extra points, can anyone outline how matplotlib's packer / spacer works, along the lines of chapter 17 "the packer" in the Tcl/Tk book?)

like image 650
denis Avatar asked Mar 10 '10 15:03

denis


People also ask

How do you avoid overlapping plots in Matplotlib?

Dot Size. You can try to decrease marker size in your plot. This way they won't overlap and the patterns will be clearer.

How do I get rid of the gap between subplots?

We can use the plt. subplots_adjust() method to change the space between Matplotlib subplots. The parameters wspace and hspace specify the space reserved between Matplotlib subplots.

What does subplots () do in Matplotlib?

Subplots mean groups of axes that can exist in a single matplotlib figure. subplots() function in the matplotlib library, helps in creating multiple layouts of subplots. It provides control over all the individual plots that are created.


3 Answers

You can use plt.subplots_adjust to change the spacing between the subplots Link

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots
hspace = 0.2   # the amount of height reserved for white space between subplots
like image 153
CyanRook Avatar answered Oct 01 '22 03:10

CyanRook


The link posted by Jose has been updated and pylab now has a tight_layout() function that does this automatically (in matplotlib version 1.1.0).

http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.tight_layout

http://matplotlib.org/users/tight_layout_guide.html#plotting-guide-tight-layout

like image 43
kiyo Avatar answered Oct 01 '22 03:10

kiyo


I find this quite tricky, but there is some information on it here at the MatPlotLib FAQ. It is rather cumbersome, and requires finding out about what space individual elements (ticklabels) take up...

Update: The page states that the tight_layout() function is the easiest way to go, which attempts to automatically correct spacing.

Otherwise, it shows ways to acquire the sizes of various elements (eg. labels) so you can then correct the spacings/positions of your axes elements. Here is an example from the above FAQ page, which determines the width of a very wide y-axis label, and adjusts the axis width accordingly:

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
   bboxes = []
   for label in labels:
       bbox = label.get_window_extent()
       # the figure transform goes from relative coords->pixels and we
       # want the inverse of that
       bboxi = bbox.inverse_transformed(fig.transFigure)
       bboxes.append(bboxi)

   # this is the bbox that bounds all the bboxes, again in relative
   # figure coords
   bbox = mtransforms.Bbox.union(bboxes)
   if fig.subplotpars.left < bbox.width:
       # we need to move it over
       fig.subplots_adjust(left=1.1*bbox.width) # pad a little
       fig.canvas.draw()
   return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.show()
like image 20
Jose Avatar answered Oct 01 '22 04:10

Jose