96

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?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
priestc
  • 33,060
  • 24
  • 83
  • 117
  • 6
    The 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 Answers9

103

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).

starball
  • 20,030
  • 7
  • 43
  • 238
Floris van Vugt
  • 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
  • 4
    One 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
    This is a nice hack, but won't work if your figure has multiple axis. – neves Jul 31 '20 at 20:44
  • 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
45

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')
Jason
  • 1,307
  • 1
  • 12
  • 11
34

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.

Tim Misner
  • 343
  • 3
  • 5
  • 6
    What 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
23

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.

Jouni K. Seppänen
  • 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
20

The solution that worked for me is:

  • use suptitle() for the actual title
  • use title() for the subtitle and adjust it using the optional parameter y:
    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.

data.dude
  • 546
  • 5
  • 9
  • 1
    The example currently shows suptitle using the `y` parameter, not title as in the explanation text ... – sdbbs Nov 18 '20 at 13:13
18

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:

http://matplotlib.org/users/usetex.html

pierre
  • 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
6

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)
PatriceG
  • 3,851
  • 5
  • 28
  • 43
2

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:

  1. For matplotlib.figure.text(): https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.text
  2. For matplotlib.pyplot.text(): https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html
  3. 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:

enter image description here

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

  1. Matplotlib: Display value next to each point on chart
    1. And my answer on this too: How to plot the (x, y) text for each point using plt.text(), and handle the first and last points with custom text formatting
  2. All of the matplotlib.org documentation. Ex: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
0

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')
Sibaram Sahu
  • 990
  • 2
  • 13
  • 21