ChatGPT解决这个技术问题 Extra ChatGPT

How to add title to subplots in Matplotlib

I have one figure which contains many subplots.

fig = plt.figure(num=None, figsize=(26, 12), dpi=80, facecolor='w', edgecolor='k')
fig.canvas.set_window_title('Window Title')

# Returns the Axes instance
ax = fig.add_subplot(311) 
ax2 = fig.add_subplot(312) 
ax3 = fig.add_subplot(313) 

How do I add titles to the subplots?

fig.suptitle adds a title to all graphs and although ax.set_title() exists, the latter does not add any title to my subplots.

Thank you for your help.

Edit: Corrected typo about set_title(). Thanks Rutger Kassies


J
Jarad

ax.title.set_text('My Plot Title') seems to work too.

fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.title.set_text('First Plot')
ax2.title.set_text('Second Plot')
ax3.title.set_text('Third Plot')
ax4.title.set_text('Fourth Plot')
plt.show()

https://i.stack.imgur.com/dUp6p.png


For anyone having problems with the font size for a histogram, oddly enough reducing the number of bins let me increase it. Went from 500 to 100.
If you need to be able to specify the fontsize, use ax.set_title('title', fontsize=16) instead.
@TobiasP.G., how do you position the title inside the subplot?
Hi @Jarad, thank you for your answer. At that time, I used ax2.text() because ax2.title.set_y() wasn't somehow working. Given 4 subplots of the same size, if I gave a value of $0.9$ for $y$ to each subplot's axis.title.set_y(), it still put the titles at weird locations and didn't match for each subplot.
W
Will Vousden

ax.set_title() should set the titles for separate subplots:

import matplotlib.pyplot as plt

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5]

    fig = plt.figure()
    fig.suptitle("Title for whole figure", fontsize=16)
    ax = plt.subplot("211")
    ax.set_title("Title for first plot")
    ax.plot(data)

    ax = plt.subplot("212")
    ax.set_title("Title for second plot")
    ax.plot(data)

    plt.show()

Can you check if this code works for you? Maybe something overwrites them later?


This works for me, matplotlib version 1.2.2 python 2.7.5
On matplotlib 3.5.2 this throws a ValueError on plt.subplot("211") / plt.subplot("212") . The solution is to just replace with integer arguments, plt.subplot(211) & plt.subplot(212).
M
MRichards

A shorthand answer assuming import matplotlib.pyplot as plt:

plt.gca().set_title('title')

as in:

plt.subplot(221)
plt.gca().set_title('title')
plt.subplot(222)
etc...

Then there is no need for superfluous variables.


this approach is nice because it gives more control over the title position...e.g. by adding kwarg y=0.7 you can plot the subplot title within the subplot
L
Lucas

If you want to make it shorter, you could write :

import matplotlib.pyplot as plt
for i in range(4):
    plt.subplot(2,2,i+1).set_title(f'Subplot n°{i+1}')
plt.show()

It makes it maybe less clear but you don't need more lines or variables


there's a typo error at the import for anyone who is just copy-pasting
J
JMDE

A solution I tend to use more and more is this one:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 2)  # 1
for i, ax in enumerate(axs.ravel()): # 2
    ax.set_title("Plot #{}".format(i)) # 3

Create your arbitrary number of axes axs.ravel() converts your 2-dim object to a 1-dim vector in row-major style assigns the title to the current axis-object


D
Derlin

In case you have multiple images and you want to loop though them and show them 1 by 1 along with titles - this is what you can do. No need to explicitly define ax1, ax2, etc.

The catch is you can define dynamic axes(ax) as in Line 1 of code and you can set its title inside a loop. The rows of 2D array is length (len) of axis(ax) Each row has 2 items i.e. It is list within a list (Point No.2) set_title can be used to set title, once the proper axes(ax) or subplot is selected.

import matplotlib.pyplot as plt    
fig, ax = plt.subplots(2, 2, figsize=(6, 8))  
for i in range(len(ax)): 
    for j in range(len(ax[i])):
        ## ax[i,j].imshow(test_images_gr[0].reshape(28,28))
        ax[i,j].set_title('Title-' + str(i) + str(j))

M
MRUNAL MUNOT

You are able to give every graph a different title and label by Iteration only.

titles = {221: 'First Plot', 222: 'Second Plot', 223: 'Third Plot', 224: 'Fourth Plot'}
fig = plt.figure()
for x in range(221,225):
  ax = fig.add_subplot(x)
  ax.title.set_text(titles.get(x))

plt.subplots_adjust(left=0.1,
                    bottom=0.1, 
                    right=0.9, 
                    top=0.9, 
                    wspace=0.4, 
                    hspace=0.4)
plt.show()

Output:

https://i.stack.imgur.com/LLEvA.png


the subplots_adjust call cures overlapping titles. So this is very useful. Thank you!
W
Wojciech Moszczyński
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=1, ncols=4,figsize=(11, 7))

grid = plt.GridSpec(2, 2, wspace=0.2, hspace=0.5)

ax1 = plt.subplot(grid[0, 0])
ax2 = plt.subplot(grid[0, 1:])
ax3 = plt.subplot(grid[1, :1])
ax4 = plt.subplot(grid[1, 1:])

ax1.title.set_text('First Plot')
ax2.title.set_text('Second Plot')
ax3.title.set_text('Third Plot')
ax4.title.set_text('Fourth Plot')

plt.show()

https://i.stack.imgur.com/EuMDf.png


J
Joma

As of matplotlib 3.4.3, the Figure.add_subplot function supports kwargs with title as:

fig.add_subplot(311, title="first")
fig.add_subplot(312, title="second")

d
divenex

For completeness, the requested result can also be achieve without explicit reference to the figure axes as follows:

import matplotlib.pyplot as plt

plt.subplot(221)
plt.title("Title 1")

plt.subplot(222)
plt.title("Title 2")

plt.subplot(223)
plt.title("Title 3")

plt.subplot(224)
plt.title("Title 4")

https://i.stack.imgur.com/6HPTU.png

Use plt.tight_layout() after the last plot if you have issues with overlapping labels.