I want to give my graph a title in big 18pt font, then a subtitle below it in smaller 10pt font. How can I do this in matplotlib? It appears the title()
function only takes one single string with a single fontsize
attribute. There has to be a way to do this, but how?

- 56,955
- 33
- 144
- 158

- 33,060
- 24
- 83
- 117
-
6The shortest answer to your ``subtitle`` question is: There is a built-in ``suptitle()`` function. Thus, combining ``suptitle()/title()`` is similar to the more intuitively named ``title()/subtitle()``. See Floris van Vugt's answer and Tim Misner's follow-up below. – PatrickT Apr 17 '18 at 11:50
9 Answers
What I do is use the title()
function for the subtitle and the suptitle()
for the main title (they can take different font size arguments).

- 20,030
- 7
- 43
- 238

- 1,031
- 2
- 7
- 3
-
At least on a standard polar plot, the title, the suptitle, and the 90 degree marker all overlap, especially if you use bigger fonts. – gbronner Oct 10 '14 at 01:00
-
4One issue with this is that `title` and `suptitle` center differently, so they may not align for your plot. – Alex Nov 22 '19 at 23:19
-
1
-
For an actual example of this, see [this other answer here](https://stackoverflow.com/a/54842869/4561887). – Gabriel Staples Jun 28 '21 at 18:06
Although this doesn't give you the flexibility associated with multiple font sizes, adding a newline character to your pyplot.title() string can be a simple solution;
plt.title('Really Important Plot\nThis is why it is important')

- 1,307
- 1
- 12
- 11
-
11Most of the time you want some stylistic differences between titles and subtitles. Otherwise it just looks like a sloppy title split over two lines. – AnnanFay Jun 08 '17 at 01:49
-
1
This is a pandas code example that implements Floris van Vugt's answer (Dec 20, 2010). He said:
>What I do is use the title() function for the subtitle and the suptitle() for the >main title (they can take different fontsize arguments). Hope that helps!
import pandas as pd
import matplotlib.pyplot as plt
d = {'series a' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
'series b' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
title_string = "This is the title"
subtitle_string = "This is the subtitle"
plt.figure()
df.plot(kind='bar')
plt.suptitle(title_string, y=1.05, fontsize=18)
plt.title(subtitle_string, fontsize=10)
Note: I could not comment on that answer because I'm new to stackoverflow.

- 343
- 3
- 5
-
6What if you have two subplots? If I call `subtitle_string=('Upper panel: Max, Avg, Min, Footprint % | Lower panel: Footprint % and Critical Cells %')` and then `plt.suptitle(title_string, y=0.99, fontsize=17)` in a chart with two subplots, the subtitle gets printed above the second subplot instead of the first and I don't see the legend printed. – FaCoffee Nov 13 '15 at 12:11
I don't think there is anything built-in, but you can do it by leaving more space above your axes and using figtext
:
axes([.1,.1,.8,.7])
figtext(.5,.9,'Foo Bar', fontsize=18, ha='center')
figtext(.5,.85,'Lorem ipsum dolor sit amet, consectetur adipiscing elit',fontsize=10,ha='center')
ha
is short for horizontalalignment
.

- 43,139
- 5
- 71
- 100
-
It is not clear from the answer, which `axes` is being called. The provenience of `figtext` can also only be found out by following the link. Additionally, the answer might be outdated. Would it be possible to update the answer to a more recent version of Matplotlib? – Stefan_EOX Feb 21 '22 at 11:24
The solution that worked for me is:
- use
suptitle()
for the actual title - use
title()
for the subtitle and adjust it using the optional parametery
:
import matplotlib.pyplot as plt
"""
some code here
"""
plt.title('My subtitle',fontsize=16)
plt.suptitle('My title',fontsize=24, y=1)
plt.show()
There can be some nasty overlap between the two pieces of text. You can fix this by fiddling with the value of y
until you get it right.

- 546
- 5
- 9
-
1The example currently shows suptitle using the `y` parameter, not title as in the explanation text ... – sdbbs Nov 18 '20 at 13:13
Just use TeX ! This works :
title(r"""\Huge{Big title !} \newline \tiny{Small subtitle !}""")
EDIT: To enable TeX processing, you need to add the "usetex = True" line to matplotlib parameters:
fig_size = [12.,7.5]
params = {'axes.labelsize': 8,
'text.fontsize': 6,
'legend.fontsize': 7,
'xtick.labelsize': 6,
'ytick.labelsize': 6,
'text.usetex': True, # <-- There
'figure.figsize': fig_size,
}
rcParams.update(params)
I guess you also need a working TeX distribution on your computer. All details are given at this page:

- 770
- 7
- 14
-
sounds interesting, but do you have set any additional flags for matplotlib to enable tex mode? Using 1.4.1 with default settings does not work for your example. Plotting math with r"$ expr $" in title works by the way. – marscher Nov 28 '14 at 16:26
As mentioned here, uou can use matplotlib.pyplot.text
objects in order to achieve the same result:
plt.text(x=0.5, y=0.94, s="My title 1", fontsize=18, ha="center", transform=fig.transFigure)
plt.text(x=0.5, y=0.88, s= "My title 2 in different size", fontsize=12, ha="center", transform=fig.transFigure)
plt.subplots_adjust(top=0.8, wspace=0.3)

- 3,851
- 5
- 28
- 43
Here's a hello world I wrote as I was figuring out how to use matplotlib for my needs. It's pretty thorough, for all your title and label needs.
Quick summary
Here's how to do a subtitle: just use a regular figure text box stuck in the right place:
# Figure subtitle
fig.text(0.5, 0.9, "Figure subtitle", horizontalalignment="center")
The 0.5
x-location is the halfway point between the left and the right. The 0.9
y-location puts it a little down from the top, so that it will end up under the Figure title. We use horizontalalignment="center"
to ensure it stays centered left and right.
Official matplotlib documentation:
- For
matplotlib.figure.text()
: https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.text - For
matplotlib.pyplot.text()
: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html - etc.
Summary of other plot features and titles:
# Figure title (super-title)
fig.suptitle("Figure title", fontsize=16)
# Figure subtitle
fig.text(0.5, 0.9, "Figure subtitle", horizontalalignment="center")
# Figure footer title
fig.text(0.5, 0.015, "Figure footer: see my website at www.whatever.com.",
horizontalalignment="center")
# Plot title, axes, and legend
plt.title("Plot title")
plt.xlabel("x-axis label")
plt.ylabel("y-axis label")
plt.plot(x_vals, y_vals, 'r-o', label="Drag curve for Vehicle 1")
plt.legend()
# Plot point labels
plt.text(x+.2, y-1, f"({x} m/s, {y:.2f} N drag)",
horizontalalignment="left", rotation=0)
Full, runnable example:
How to add a figure title, figure subtitle, figure footer, plot title, axis labels, legend label, and (x, y) point labels in Matplotlib:
plot_hello_world_set_all_titles_axis_labels_etc.py from my eRCaGuy_hello_world repo:
import matplotlib.pyplot as plt
# ----------------------------------
# 1. Create a new figure
# - Can be done multiple times to create multiple GUI windows of figures.
# ----------------------------------
# Create a new figure. Now, all calls to `plt.whatever()` will apply to this
# figure.
# - When done adding subplots below, you can create more figures using this call
# if you want to create multiple separate GUI windows of figures.
fig = plt.figure()
# ----------------------------------
# 2. Add a plot or subplot to it.
# - You can use the `fig.add_subplot()` call below multiple times to add
# multiple subplots to your figure.
# ----------------------------------
# Optional: make this plot a subplot in a grid of plots in your figure
# fig.add_subplot(2, 2, 1) # `1` row x `1` column of plots, this is subplot `1`
# List of x values
x_vals = [1, 2, 3, 4, 5, 6, 7]
# Use a "list comprehension" to make some y values
y_vals = [val**2 for val in x_vals]
# Plot your x, y values: red (`r`) line (`-`) with circles (`o`) for points
plt.plot(x_vals, y_vals, 'r-o', label="Drag curve for Vehicle 1")
plt.legend()
plt.xlabel("x-axis label")
plt.ylabel("y-axis label")
plt.title("Plot title")
# display (x, y) values next to each point in your plot or subplot
for i, x in enumerate(x_vals):
y = y_vals[i]
# for your last 2 points only
if i >= len(x_vals) - 2:
plt.text(x-.2, y-1, f"({x} m/s, {y:.2f} N drag)",
horizontalalignment="right", rotation=0)
# for all other points
else:
plt.text(x+.2, y-1, f"({x} m/s, {y:.2f} N drag)",
horizontalalignment="left", rotation=0)
# ----------------------------------
# 3. When all done adding as many subplots as you want to for your figure,
# configure your figure title, subtitle, and footer.
# ----------------------------------
fig.suptitle("Figure title", fontsize=16)
# Figure subtitle
fig.text(0.5, 0.9, "Figure subtitle", horizontalalignment="center")
# Figure footer title
fig.text(0.5, 0.015, "Figure footer: see my website at www.whatever.com.",
horizontalalignment="center")
# Important!:
# 1. Use `top=0.8` to bring the top of the plot down to leave some space above
# the plot for the figure subtitle to go above the plot title!
# 2. Use `bottom=0.2` to bring the bottom of the plot up to leave space for the
# figure footer.
plt.subplots_adjust(top=0.8, bottom=0.2)
# ----------------------------------
# 4. Finally, when done adding all of the figures you want to, each with as many
# subplots as you want, call this to show all figures!
# ----------------------------------
plt.show()
See also
- Matplotlib: Display value next to each point on chart
- All of the matplotlib.org documentation. Ex: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots_adjust.html

- 36,492
- 15
- 194
- 265
In matplotlib use the below function to set the subtitle
fig, ax = plt.subplots(2,1, figsize=(5,5))
ax[0, 0].plot(x,y)
ax[0, 0].set_title('text')

- 990
- 2
- 13
- 21