Python Matplotlib figure title overlaps axes label when using twiny

223,361

Solution 1

I'm not sure whether it is a new feature in later versions of matplotlib, but at least for 1.3.1, this is simply:

plt.title(figure_title, y=1.08)

This also works for plt.suptitle(), but not (yet) for plt.xlabel(), etc.

Solution 2

Forget using plt.title and place the text directly with plt.text. An over-exaggerated example is given below:

import pylab as plt

fig = plt.figure(figsize=(5,10))

figure_title = "Normal title"
ax1  = plt.subplot(1,2,1)

plt.title(figure_title, fontsize = 20)
plt.plot([1,2,3],[1,4,9])

figure_title = "Raised title"
ax2  = plt.subplot(1,2,2)

plt.text(0.5, 1.08, figure_title,
         horizontalalignment='center',
         fontsize=20,
         transform = ax2.transAxes)
plt.plot([1,2,3],[1,4,9])

plt.show()

enter image description here

Solution 3

I was having an issue with the x-label overlapping a subplot title; this worked for me:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 1)
ax[0].scatter(...)
ax[1].scatter(...)
plt.tight_layout()
.
.
.
plt.show()

before

enter image description here

after

enter image description here

reference:

Solution 4

ax.set_title('My Title\n', fontsize="15", color="red")
plt.imshow(myfile, origin="upper")

If you put '\n' right after your title string, the plot is drawn just below the title. That might be a fast solution too.

Solution 5

You can use pad for this case:

ax.set_title("whatever", pad=20)
Share:
223,361

Related videos on Youtube

Magic_Matt_Man
Author by

Magic_Matt_Man

Updated on July 08, 2022

Comments

  • Magic_Matt_Man
    Magic_Matt_Man almost 2 years

    I am trying to plot two separate quantities on the same graph using twiny as follows:

    fig = figure()
    ax = fig.add_subplot(111)
    ax.plot(T, r, 'b-', T, R, 'r-', T, r_geo, 'g-')
    ax.set_yscale('log')
    ax.annotate('Approx. sea level', xy=(Planet.T_day*1.3,(Planet.R)/1000), xytext=(Planet.T_day*1.3, Planet.R/1000))
    ax.annotate('Geostat. orbit', xy=(Planet.T_day*1.3, r_geo[0]), xytext=(Planet.T_day*1.3, r_geo[0]))
    ax.set_xlabel('Rotational period (hrs)')
    ax.set_ylabel('Orbital radius (km), logarithmic')
    ax.set_title('Orbital charts for ' + Planet.N, horizontalalignment='center', verticalalignment='top')
    
    
    ax2 = ax.twiny()
    ax2.plot(v,r,'k-')
    ax2.set_xlabel('Linear speed (ms-1)')
    
    show()
    

    and the data is presented fine, but I am having the problem that the figure title is overlapping with the axes labels on the secondary x axis so that it's barely legible (I wanted to post a picture example here, but I don't have a high enough rep yet).

    I'd like to know if there's a straightforward way to just shift the title directly up a few tens of pixels, so that the chart looks prettier.

    • Hooked
      Hooked over 11 years
      Welcome to Stack Overflow! If you link to an imgur posting of your picture a higher rep user will embed the image in your post for you.
    • Amelio Vazquez-Reina
      Amelio Vazquez-Reina over 9 years
      @Magic -- Would you reconsider what answer to accept for this question? Matplotlib has added a builtin mechanism to handle this precise need (the most voted answer below)
  • Hooked
    Hooked about 10 years
    @user815423426 yes, tight_layout still doesn't seem to play nicely with non-standard placements. Perhaps you could make a bug report?
  • Felix Hoffmann
    Felix Hoffmann about 10 years
    For labels you can set the argument labelpad, see here.
  • Joe Kington
    Joe Kington over 9 years
    For what it's worth, it's not a new feature. title has taken x and y arguments for a very long time (as long as I can remember, at any rate).
  • Yu Shen
    Yu Shen over 9 years
    plt.set_title('title string', y = 1.08) works for me.
  • junkaholik
    junkaholik about 9 years
    I found a work around when using tight_layout, at least when you save your plot using figure.savefig(). If title = plt.title(...) then you can specify to frame the plot tightly around the title using the option bbox_extra_artists : figure.savefig(filename, bbox_extra_artists=(title), bbox_inches='tight')
  • kon psych
    kon psych almost 7 years
    It would be more helpful if someone explained what units 1.08 is and what are the defaults. My understanding is that default is 1
  • John Cummings
    John Cummings over 6 years
    @konpsych I agree, the default is actually 0 according to the Text object docs but I'm not sure what units are.
  • herrlich10
    herrlich10 over 6 years
    @JohnCummings It seems that the default value is y=1 and the units is "axes fraction", i.e., y=0.5 means the title is in the middle of the axes, and y=0 means the title is just above the bottom of the axes.
  • John Cummings
    John Cummings over 6 years
    @herrlich10 thank you for the information on the units - where did you find that detail? Also, the only default I see for y is y=0 in the Text object docs that I linked to. Where did you find y=1 as the default value?
  • herrlich10
    herrlich10 over 6 years
    @JohnCummings It's in the source code of _AxesBase class. Search for "self.title" in the file.
  • Henrik
    Henrik almost 3 years
    This works when iterating through axes too.