72

The following screenshot shows my x-axis.

enter image description here

I added some labels and rotated them by 90 degrees in order to better read them. However, pyplot truncates the bottom such that I'm not able to completely read the labels. How do I extend the bottom margin in order to see the complete labels?

nbro
  • 15,395
  • 32
  • 113
  • 196
toom
  • 12,864
  • 27
  • 89
  • 128

6 Answers6

89

Two retroactive ways:

fig, ax = plt.subplots()
# ...
fig.tight_layout()

Or

fig.subplots_adjust(bottom=0.2) # or whatever

Here's a subplots_adjust example: http://matplotlib.org/examples/pylab_examples/subplots_adjust.html

(but I prefer tight_layout)

Paul H
  • 65,268
  • 20
  • 159
  • 136
  • 2
    You can also tell pass `tight_layout=True` to `subplots` which sa the same effect. – tacaswell Jan 11 '15 at 00:32
  • Is there a way to do this *without* using ``tight_layout`` nor ``subplots``? I.e. if one just creates a figure and adds a plot via ``plt.plot(...)``. The reason I am asking is because I am trying to create multiple plots for a movie and the title and axis labels wobble around if ``subplots`` and/or ``tight_layout`` are used. Any help would be appreciated. – Wolpertinger Jan 12 '18 at 08:22
  • 1
    @Wolpertinger: `fig = plt.figure(); fig.add_axes(...);` https://matplotlib.org/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure.add_axes – Paul H Jan 12 '18 at 15:00
  • `subplots_adjust` partially worked for me, to add some space at the top of a figure where the legend was otherwise cut: `top=0.75` had an insufficient effect, `top=1.5`, strangely, seemed to have no effect. `tigh_layout` did not seem to have any effect in this particular case. – bli Jan 31 '18 at 11:26
26

A quick one-line solution that has worked for me is to use pyplot's auto tight_layout method directly, available in Matplotlib v1.1 onwards:

plt.tight_layout()

This can be invoked immediately before you show the plot (plt.show()), but after your manipulations on the axes (e.g. ticklabel rotations, etc).

This convenience method avoids manipulating individual figures of subplots.

Where plt is the standard pyplot from: import matplotlib.pyplot as plt

chinnychinchin
  • 5,564
  • 2
  • 21
  • 18
  • 3
    Good answer. It's worth noting that the comment "but after your manipulations" is crucial. Otherwise, your title may get cut off like it did with me. – Jules Dec 06 '19 at 01:19
15
fig.savefig('name.png', bbox_inches='tight')

works best for me, since it doesn't reduce the plot size compared to

fig.tight_layout()
Marcel
  • 285
  • 2
  • 10
10

Subplot-adjust did not work for me, since the whole figure would just resize with the labels still out of bounds.

A workaround I found was to keep the y-axis always a certain margin over the highest or minimum y-values:

x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,y1 - 100 ,y2 + 100))
rainer
  • 3,295
  • 5
  • 34
  • 50
  • 2
    This is the only solution here that worked for me. – Josh Mar 03 '21 at 22:44
  • The axis function specifies the viewport of the axes, so it's not clear why ``plt.axis()`` would help with labels that are outside of the axes... It would seem more logical to expect something from ``plt.figure()`` – PatrickT Jan 15 '22 at 03:49
1
fig, ax = plt.subplots(tight_layout=True)
Youjun Hu
  • 991
  • 6
  • 18
0

This is rather complicated, but it gives a general and neat solution.

import numpy as np
value1 = 3

xvalues = [0, 1, 2, 3, 4]
line1 = [2.0, 3.0, 2.0, 5.0, 4.0]
stdev1 = [0.1, 0.2, 0.1, 0.4, 0.3]

line2 = [1.7, 3.1, 2.5, 4.8, 4.2]
stdev2 = [0.12, 0.18, 0.12, 0.3, 0.35]

max_times = [max(line1+stdev1),max(line2+stdev2)]
min_times = [min(line1+stdev1),min(line2+stdev2)]

font_size = 25

max_total = max(max_times)
min_total = min(min_times)

max_minus_min = max_total - min_total

step_size = max_minus_min/10
head_space = (step_size*3) 


plt.figure(figsize=(15, 15))
plt.errorbar(xvalues, line1, yerr=stdev1, fmt='', color='b')

plt.errorbar(xvalues, line2, yerr=stdev2, fmt='', color='r')
plt.xlabel("xvalues", fontsize=font_size)
plt.ylabel("lines 1 and 2 Test "+str(value1), fontsize=font_size)
plt.title("Let's leave space for the legend Experiment"+ str(value1), fontsize=font_size)
plt.legend(("Line1", "Line2"), loc="upper left", fontsize=font_size)
plt.tick_params(labelsize=font_size)
plt.yticks(np.arange(min_total, max_total+head_space, step=step_size) )
plt.grid()
plt.tight_layout()

Result: Plot with headspace for the legend, big enough font, gridlines.

Vince Hall
  • 46
  • 1
  • 6