890

How does one change the font size for all elements (ticks, labels, title) on a matplotlib plot?

I know how to change the tick label sizes, this is done with:

import matplotlib 
matplotlib.rc('xtick', labelsize=20) 
matplotlib.rc('ytick', labelsize=20) 

But how does one change the rest?

daniel451
  • 10,626
  • 19
  • 67
  • 125
Herman Schaaf
  • 46,821
  • 21
  • 100
  • 139

16 Answers16

1100

From the matplotlib documentation,

font = {'family' : 'normal',
        'weight' : 'bold',
        'size'   : 22}

matplotlib.rc('font', **font)

This sets the font of all items to the font specified by the kwargs object, font.

Alternatively, you could also use the rcParams update method as suggested in this answer:

matplotlib.rcParams.update({'font.size': 22})

or

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 22})

You can find a full list of available properties on the Customizing matplotlib page.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Herman Schaaf
  • 46,821
  • 21
  • 100
  • 139
  • 12
    nice, except it override any fontsize property found on it's way è_é – yota Sep 25 '14 at 11:56
  • 4
    Where can I find more options for elements like `'family'`, `'weight'`, etc.? – haccks Jun 11 '15 at 09:26
  • @haccks I added a link to the customizing matplotlib page in the answer. – Herman Schaaf Jun 11 '15 at 16:45
  • 2
    @HermanSchaaf; I visited that page before. I would like to know all the options for `'family'` Like `'normal'`, `'sans-serif'`, etc. – haccks Jun 11 '15 at 16:56
  • 140
    Since many people start with `import matplotlib.pyplot as plt`, you might like to point out that `pyplot` has `rc` as well. You can do `plt.rc(...` without having to change your imports. – LondonRob Jul 27 '15 at 15:55
  • Does this permanently mess up the maplotlib defaults for fontsize?? – user32882 Jul 22 '17 at 13:49
  • 63
    For the impatient: The default font size is 10, as in the second link. – FvD Oct 16 '17 at 08:19
  • @LondonRob `plt.rcParams.update({'font.size':22})` works, too. Thanks. – Josiah Yoder Aug 14 '18 at 15:51
  • 1
    @haccks for all options run plt.rcParams.keys() – DannyMoshe Aug 17 '18 at 11:46
  • I believe 'weight' is no longer valid and is now 'font.weight' – DannyMoshe Aug 17 '18 at 11:47
  • 6
    @user32882 - not permanently, it's not saved to disk, but I would assume it would change subsequent plots generated in the same code unless the original value is stored and restored, which is no always convenient. You can do something like `for label in (ax.get_xticklabels() + ax.get_yticklabels()): label.set_fontsize(22)` to affect text size in a single figure. – Terry Brown Jan 28 '19 at 19:03
  • 3
    If you want to temporarily change the font size, `plt.style.context` will accept a dictionary of `rcParams` like so: `with plt.style.context({'font.size': 22}):` – Charlie G Mar 13 '20 at 13:53
  • In Colab notebook will increase the font size on the screen, but *not* on a print. To fix this you must *also* add `dpi` e.g. `plt.figure(dpi=80)` – Axel Bregnsbo Nov 27 '22 at 13:06
  • 1
    I would suggest `'family' : 'Sans'` that will resolve to something sensible – am70 Jan 23 '23 at 09:37
  • It's funny: The [documentation](https://matplotlib.org/stable/api/matplotlib_configuration_api.html#matplotlib.rc) uses `'size' : 'larger'` in one of the examples, but when I try out that example, I get `ValueError: Key font.size: Could not convert 'larger' to float`. Your code on the other hand, `'size' : 22`, worked. – HelloGoodbye May 25 '23 at 14:42
601

If you are a control freak like me, you may want to explicitly set all your font sizes:

import matplotlib.pyplot as plt

SMALL_SIZE = 8
MEDIUM_SIZE = 10
BIGGER_SIZE = 12

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE)     # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE)    # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE)  # fontsize of the figure title

Note that you can also set the sizes calling the rc method on matplotlib:

import matplotlib

SMALL_SIZE = 8
matplotlib.rc('font', size=SMALL_SIZE)
matplotlib.rc('axes', titlesize=SMALL_SIZE)

# and so on ...
Pedro M Duarte
  • 26,823
  • 7
  • 44
  • 43
  • 14
    I tried many of the answers. This one looks the best, at least in Jupyter notebooks. Just copy the above block at the top and customize the three font size constants. – fviktor Sep 13 '17 at 18:48
  • 20
    For me the title size didn't work. I used: ``plt.rc('axes', titlesize=BIGGER_SIZE)`` – Fernando Irarrázaval G May 06 '18 at 05:06
  • 2
    I think you can combine all settings for the same object into one line. E.g., `plt.rc('axes', titlesize=SMALL_SIZE, labelsize=MEDIUM_SIZE)` – BallpointBen Aug 21 '18 at 05:17
265

If you want to change the fontsize for just a specific plot that has already been created, try this:

import matplotlib.pyplot as plt

ax = plt.subplot(111, xlabel='x', ylabel='y', title='title')
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
             ax.get_xticklabels() + ax.get_yticklabels()):
    item.set_fontsize(20)
ryggyr
  • 3,341
  • 2
  • 20
  • 14
  • 2
    My purpose was to have the font of x-y labels, ticks and the titles to be of different sizes. A modified version of this worked so well for me. – Ébe Isaac Feb 13 '17 at 05:27
  • 11
    To get the legends as well use ax.legend().get_texts(). Tested on Matplotlib 1.4. – James S. Sep 11 '17 at 04:19
  • Might need an `ax=plt.gca()` if the plot was created without defining an axis. – dylnan Jan 28 '19 at 18:46
  • 5
    @JamesS. Rather use `ax.get_legend().get_texts()`, because `ax.legend()` redraws the whole legend with default parameters on top of returning the value of `ax.get_legend()`. – Guimoute Nov 21 '19 at 10:57
228
matplotlib.rcParams.update({'font.size': 22})
Marius Retegan
  • 2,416
  • 1
  • 17
  • 12
  • 2
    In may case this solution works only if I create a first plot, then "update" as suggested, which leads to updated font size for new figures. Maybe the first plot is necessary to initialize rcParams... – Songio Mar 07 '20 at 21:36
84

This answer is for anyone trying to change all the fonts, including for the legend, and for anyone trying to use different fonts and sizes for each thing. It does not use rc (which doesn't seem to work for me). It is perhaps a bit cumbersome but I could not get to grips with any other method, personally.

I have worked out a slightly different, less cluttered approach than my original answer below. It allows any font on your system, even .otf fonts. To have separate fonts for each thing, just write more font_path and font_prop like variables.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
import matplotlib.ticker
# Workaround for Matplotlib 2.0.0 log axes bug https://github.com/matplotlib/matplotlib/issues/8017 :
# matplotlib.ticker._mathdefault = lambda x: '\\mathdefault{%s}'%x 

# Set the font properties (can use more variables for more fonts)
font_path = 'C:\Windows\Fonts\AGaramondPro-Regular.otf'
font_prop = font_manager.FontProperties(fname=font_path, size=14)

ax = plt.subplot() # Defines ax variable by creating an empty plot

# Define the data to be plotted
x = np.linspace(0, 10)
y = x + np.random.normal(x)
plt.plot(x, y, 'b+', label='Data points')

for label in (ax.get_xticklabels() + ax.get_yticklabels()):
    label.set_fontproperties(font_prop)
    label.set_fontsize(13) # Size here overrides font_prop

plt.title("Exponentially decaying oscillations", fontproperties=font_prop,
          size=16, verticalalignment='bottom') # Size here overrides font_prop
plt.xlabel("Time", fontproperties=font_prop)
plt.ylabel("Amplitude", fontproperties=font_prop)
plt.text(0, 0, "Misc text", fontproperties=font_prop)

lgd = plt.legend(loc='lower right', prop=font_prop) # NB different 'prop' argument for legend
lgd.set_title("Legend", prop=font_prop)

plt.show()

Original answer

This basically combines ryggyr's answer here with other answers on SO.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager

# Set the font dictionaries (for plot title and axis titles)
title_font = {'fontname':'Arial', 'size':'16', 'color':'black', 'weight':'normal',
              'verticalalignment':'bottom'} # Bottom vertical alignment for more space
axis_font = {'fontname':'Arial', 'size':'14'}

# Set the font properties (for use in legend)   
font_path = 'C:\Windows\Fonts\Arial.ttf'
font_prop = font_manager.FontProperties(fname=font_path, size=14)

ax = plt.subplot() # Defines ax variable by creating an empty plot

# Set the tick labels font
for label in (ax.get_xticklabels() + ax.get_yticklabels()):
    label.set_fontname('Arial')
    label.set_fontsize(13)

x = np.linspace(0, 10)
y = x + np.random.normal(x) # Just simulates some data

plt.plot(x, y, 'b+', label='Data points')
plt.xlabel("x axis", **axis_font)
plt.ylabel("y axis", **axis_font)
plt.title("Misc graph", **title_font)
plt.legend(loc='lower right', prop=font_prop, numpoints=1)
plt.text(0, 0, "Misc text", **title_font)
plt.show()

By having several font dictionaries, you can choose different fonts/sizes/weights/colours for the various titles, choose the font for the tick labels, and choose the font for the legend, all independently.

binaryfunt
  • 6,401
  • 5
  • 37
  • 59
67

Here is a totally different approach that works surprisingly well to change the font sizes:

Change the figure size!

I usually use code like this:

import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(4,3))
ax = fig.add_subplot(111)
x = np.linspace(0,6.28,21)
ax.plot(x, np.sin(x), '-^', label="1 Hz")
ax.set_title("Oscillator Output")
ax.set_xlabel("Time (s)")
ax.set_ylabel("Output (V)")
ax.grid(True)
ax.legend(loc=1)
fig.savefig('Basic.png', dpi=300)

The smaller you make the figure size, the larger the font is relative to the plot. This also upscales the markers. Note I also set the dpi or dot per inch. I learned this from a posting the AMTA (American Modeling Teacher of America) forum. Example from above code: enter image description here

Krishna
  • 6,107
  • 2
  • 40
  • 43
Prof Huster
  • 938
  • 7
  • 14
  • 11
    To avoid the axis label being cut-off, save figure with the `bbox_inches` argument `fig.savefig('Basic.png', bbox_inches="tight")` – Paw Oct 22 '18 at 11:05
  • What if I am NOT saving the figure? I am plotting in Juypter Notebook and the resulting axis labels get cut-off. – Zythyr Oct 04 '19 at 07:43
  • Thanks! Pointing out the dpi settings was extremely helpful to me in preparing printable versions of my plots without having to adjust all the line sizes, font sizes, etc. – ybull Oct 23 '19 at 18:56
  • 1
    To prevent the label cut-off, also in the notebook as @Zythyr asks, you can use `plt.tight_layout()` – Ramon Crehuet Jul 08 '20 at 09:35
  • 1
    @Zythyr You can use the dpi=XXX argument also in the call of plt.figure(): `plt.figure(figsize=(4,3), dpi=300)` to achieve the same result without saving – dnalow Jul 24 '20 at 17:27
  • I am grateful that you posted this answer here! It addressed the root problem that my 'font size' increase was attempting to solve. – LunkRat May 24 '22 at 02:17
50

You can use plt.rcParams["font.size"] for setting font_size in matplotlib and also you can use plt.rcParams["font.family"] for setting font_family in matplotlib. Try this example:

import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')

label = [1,2,3,4,5,6,7,8]
x = [0.001906,0.000571308,0.0020305,0.0037422,0.0047095,0.000846667,0.000819,0.000907]
y = [0.2943301,0.047778308,0.048003167,0.1770876,0.532489833,0.024611333,0.157498667,0.0272095]


plt.ylabel('eigen centrality')
plt.xlabel('betweenness centrality')
plt.text(0.001906, 0.2943301, '1 ', ha='right', va='center')
plt.text(0.000571308, 0.047778308, '2 ', ha='right', va='center')
plt.text(0.0020305, 0.048003167, '3 ', ha='right', va='center')
plt.text(0.0037422, 0.1770876, '4 ', ha='right', va='center')
plt.text(0.0047095, 0.532489833, '5 ', ha='right', va='center')
plt.text(0.000846667, 0.024611333, '6 ', ha='right', va='center')
plt.text(0.000819, 0.157498667, '7 ', ha='right', va='center')
plt.text(0.000907, 0.0272095, '8 ', ha='right', va='center')
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["font.size"] = "50"
plt.plot(x, y, 'o', color='blue')

Please, see the output:

Hamed Baziyad
  • 1,954
  • 5
  • 27
  • 40
49

Use plt.tick_params(labelsize=14)

Andrey Nikishaev
  • 3,759
  • 5
  • 40
  • 55
  • 6
    Thank you for the code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its [long-term value](https://meta.stackexchange.com/q/114762/206345) by describing why this is a good solution to the problem, and would make it more useful to future readers with other similar questions. Please edit your answer to add some explanation, including the assumptions you've made. – sepehr Oct 31 '18 at 17:29
  • 3
    Doesn't this just change the tick font size? – JiK Jul 16 '20 at 20:14
  • Ant thing similar for legend? – nightcrawler Nov 02 '22 at 07:49
37

Here is what I generally use in Jupyter Notebook:

# Jupyter Notebook settings

from IPython.core.display import display, HTML
display(HTML("<style>.container { width:95% !important; }</style>"))
%autosave 0
%matplotlib inline
%load_ext autoreload
%autoreload 2

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"


# Imports for data analysis
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', 2500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_colwidth', 2000)
pd.set_option('display.width', 2000)
pd.set_option('display.float_format', lambda x: '%.3f' % x)

#size=25
size=15
params = {'legend.fontsize': 'large',
          'figure.figsize': (20,8),
          'axes.labelsize': size,
          'axes.titlesize': size,
          'xtick.labelsize': size*0.75,
          'ytick.labelsize': size*0.75,
          'axes.titlepad': 25}
plt.rcParams.update(params)
stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217
15

The changes to the rcParams are very granular, most of the time all you want is just scaling all of the font sizes so they can be seen better in your figure. The figure size is a good trick but then you have to carry it for all of your figures. Another way (not purely matplotlib, or maybe overkill if you don't use seaborn) is to just set the font scale with seaborn:

sns.set_context('paper', font_scale=1.4)

DISCLAIMER: I know, if you only use matplotlib then probably you don't want to install a whole module for just scaling your plots (I mean why not) or if you use seaborn, then you have more control over the options. But there's the case where you have the seaborn in your data science virtual env but not using it in this notebook. Anyway, yet another solution.

anishtain4
  • 2,342
  • 2
  • 17
  • 21
8

Based on the above stuff:

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

fontPath = "/usr/share/fonts/abc.ttf"
font = fm.FontProperties(fname=fontPath, size=10)
font2 = fm.FontProperties(fname=fontPath, size=24)

fig = plt.figure(figsize=(32, 24))
fig.text(0.5, 0.93, "This is my Title", horizontalalignment='center', fontproperties=font2)

plot = fig.add_subplot(1, 1, 1)

plot.xaxis.get_label().set_fontproperties(font)
plot.yaxis.get_label().set_fontproperties(font)
plot.legend(loc='upper right', prop=font)

for label in (plot.get_xticklabels() + plot.get_yticklabels()):
    label.set_fontproperties(font)
nvd
  • 2,995
  • 28
  • 16
7

I just wanted to point out that both the Herman Schaaf's and Pedro M Duarte's answers work but you have to do that before instantiating subplots(), these settings will not affect already instantiated objects. I know it's not a brainer but I spent quite some time figuring out why are those answers not working for me when I was trying to use these changes after calling subplots().

For eg:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 6,})
fig, ax = plt.subplots()
#create your plot
plt.show()

or

SMALL_SIZE = 8
MEDIUM_SIZE = 10
BIGGER_SIZE = 12

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('xtick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
fig, ax = plt.subplots()
#create your plot
plt.show()
InvisibleWolf
  • 917
  • 1
  • 9
  • 22
6

I totally agree with Prof Huster that the simplest way to proceed is to change the size of the figure, which allows keeping the default fonts. I just had to complement this with a bbox_inches option when saving the figure as a pdf because the axis labels were cut.

import matplotlib.pyplot as plt
plt.figure(figsize=(4,3))
plt.savefig('Basic.pdf', bbox_inches='tight')
5

This is an extension to Marius Retegan answer. You can make a separate JSON file with all your modifications and than load it with rcParams.update. The changes will only apply to the current script. So

import json
from matplotlib import pyplot as plt, rcParams

s = json.load(open("example_file.json")
rcParams.update(s)

and save this 'example_file.json' in the same folder.

{
  "lines.linewidth": 2.0,
  "axes.edgecolor": "#bcbcbc",
  "patch.linewidth": 0.5,
  "legend.fancybox": true,
  "axes.color_cycle": [
    "#348ABD",
    "#A60628",
    "#7A68A6",
    "#467821",
    "#CF4457",
    "#188487",
    "#E24A33"
  ],
  "axes.facecolor": "#eeeeee",
  "axes.labelsize": "large",
  "axes.grid": true,
  "patch.edgecolor": "#eeeeee",
  "axes.titlesize": "x-large",
  "svg.fonttype": "path",
  "examples.directory": ""
}
Michael H.
  • 535
  • 6
  • 11
  • Or using matplotlib's styling, which is very similar to your idea: https://matplotlib.org/stable/tutorials/introductory/customizing.html – PatrickT Jan 04 '22 at 09:44
3

I wrote a modified version of the answer by @ryggyr that allows for more control over the individual parameters and works on multiple subplots:

def set_fontsizes(axes,size,title=np.nan,xlabel=np.nan,ylabel=np.nan,xticks=np.nan,yticks=np.nan):
    if type(axes) != 'numpy.ndarray':
        axes=np.array([axes])
    
    options = [title,xlabel,ylabel,xticks,yticks]
    for i in range(len(options)):
        if np.isnan(options[i]):
            options[i]=size
        
    title,xlabel,ylabel,xticks,yticks=options
    
    for ax in axes.flatten():
        ax.title.set_fontsize(title)
        ax.xaxis.label.set_size(xlabel)
        ax.yaxis.label.set_size(ylabel)
        ax.tick_params(axis='x', labelsize=xticks)
        ax.tick_params(axis='y', labelsize=yticks)
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
ari
  • 1,122
  • 1
  • 9
  • 15
2

It is mentioned in a comment but deserves its own answer:

Modify both figsize= and dpi= in conjunction to adjust the figure size and the scale of all text labels:

fig, ax = plt.subplots(1, 1, figsize=(8, 4), dpi=100)

(or shorter:)

fig, ax = plt.subplots(figsize=(8, 4), dpi=100)

It's a bit tricky:

  1. figsize actually controls the scale of the text relative to the plot extent (as well as the aspect ratio of the plot).

  2. dpi adjusts the size of the figure within the notebook (keeping constant the relative scale of the text and the plot aspect ratio).

Hugues
  • 2,865
  • 1
  • 27
  • 39