Hi,
I am trying to use the Times New Roman font with my plots, and wanted to do this using the following sns.set_style command:
sns.set_style({'font.family':'serif', 'font.serif':'Times New Roman'})
However, the font.serif key and value don't seem to be appearing after I do this. Starting with all default values:
>>> import matplotlib.pyplot as plt
>>> import seaborn as sns
>>> sns.axes_style()
{'axes.axisbelow': True,
'axes.edgecolor': 'white',
'axes.facecolor': '#EAEAF2',
'axes.grid': True,
'axes.labelcolor': '.15',
'axes.linewidth': 0.0,
'figure.facecolor': 'white',
'font.family': ['sans-serif'],
'font.sans-serif': ['Arial',
'Liberation Sans',
'Bitstream Vera Sans',
'sans-serif'],
'grid.color': 'white',
'grid.linestyle': '-',
'image.cmap': 'Greys',
'legend.frameon': False,
'legend.numpoints': 1,
'legend.scatterpoints': 1,
'lines.solid_capstyle': 'round',
'text.color': '.15',
'xtick.color': '.15',
'xtick.direction': 'out',
'xtick.major.size': 0.0,
'xtick.minor.size': 0.0,
'ytick.color': '.15',
'ytick.direction': 'out',
'ytick.major.size': 0.0,
'ytick.minor.size': 0.0}
Change the font family and the font to serif:
>>> sns.set_style({'font.family':'serif', 'font.serif':['Times New Roman']})
>>> sns.axes_style()
{'axes.axisbelow': True,
'axes.edgecolor': 'white',
'axes.facecolor': '#EAEAF2',
'axes.grid': True,
'axes.labelcolor': '.15',
'axes.linewidth': 0.0,
'figure.facecolor': 'white',
'font.family': ['serif'],
'font.sans-serif': ['Arial',
'Liberation Sans',
'Bitstream Vera Sans',
'sans-serif'],
'grid.color': 'white',
'grid.linestyle': '-',
'image.cmap': 'Greys',
'legend.frameon': False,
'legend.numpoints': 1,
'legend.scatterpoints': 1,
'lines.solid_capstyle': 'round',
'text.color': '.15',
'xtick.color': '.15',
'xtick.direction': 'out',
'xtick.major.size': 0.0,
'xtick.minor.size': 0.0,
'ytick.color': '.15',
'ytick.direction': 'out',
'ytick.major.size': 0.0,
'ytick.minor.size': 0.0}
As you can see the font.family changed to serif but the font.serif doesn't even appear and font.sans-serif is still there. Is this by design or am I right in assuming it should be added to the dict?
At the moment the only solution seems to be to change this directly in the Matplotlib rcParams:
import matplotlib as mpl
mpl.rc('font', family='serif', serif='Times New Roman')
Ubuntu 14.04 LTS
Seaborn 0.6.0
Matplotlib 1.4.3
Python 3.4
Looking at rcmod.py, it looks like it should be a case of just adding "font.serif" to the _style_keys. I've tested this and can confirm that it works. rcmod.py looks like this:
_style_keys = (
"axes.facecolor",
"axes.edgecolor",
"axes.grid",
"axes.axisbelow",
"axes.linewidth",
"axes.labelcolor",
"figure.facecolor",
"grid.color",
"grid.linestyle",
"text.color",
"xtick.color",
"ytick.color",
"xtick.direction",
"ytick.direction",
"xtick.major.size",
"ytick.major.size",
"xtick.minor.size",
"ytick.minor.size",
"legend.frameon",
"legend.numpoints",
"legend.scatterpoints",
"lines.solid_capstyle",
"image.cmap",
"font.family",
"font.sans-serif",
"font.serif",
)
Updating the font.serif to Times New Roman now works as expected:
>>> sns.set_style('whitegrid', {'font.family':'serif', 'font.serif':'Times New Roman'})
>>> sns.axes_style()
{'axes.axisbelow': True,
'axes.edgecolor': 'white',
'axes.facecolor': '#EAEAF2',
'axes.grid': True,
'axes.labelcolor': '.15',
'axes.linewidth': 0.0,
'figure.facecolor': 'white',
'font.family': ['serif'],
'font.sans-serif': ['Arial',
'Liberation Sans',
'Bitstream Vera Sans',
'sans-serif'],
'font.serif': ['Times New Roman'],
'grid.color': 'white',
'grid.linestyle': '-',
'image.cmap': 'Greys',
'legend.frameon': False,
'legend.numpoints': 1,
'legend.scatterpoints': 1,
'lines.solid_capstyle': 'round',
'text.color': '.15',
'xtick.color': '.15',
'xtick.direction': 'out',
'xtick.major.size': 0.0,
'xtick.minor.size': 0.0,
'ytick.color': '.15',
'ytick.direction': 'out',
'ytick.major.size': 0.0,
'ytick.minor.size': 0.0}
Is this an adequate solution? The tests will need updating, but they all pass if you add a list of defaults to rcmod.axes_style.style_dict. I'll let you decide which defaults should be set.
I guess if I wanted to use a serif font I would just pass that to the matplotlib rc function, but I guess if you wanted to be very strict about doing everything "through" seaborn that might be an issue (though you could pass it to the rc parameter of seaborn.set. I doubt adding font.serif would hurt anything, though ...
Thanks for the reply. Up until now I've managed to keep all my setting changes through seaborn and since it's such an easy fix, can I request that it be added? I've forked the repo and made the changes, so I can make a pull request if required.
Are you proposing making Times New Roman the "official" default seaborn serif font, or just adding font.serif with the normal matplotlib default, which would therefore allow you or others to pass the serif font they want?
So the default line in the matplotlibrc file is:
#font.serif : Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
This seems a bit excessive to me and when thinking of serif fonts I don't really think of 'Nimbus Roman No9 L' or 'New Century Schoolbook' before Times New Roman. So yes, maybe I would propose making Times New Roman the seaborn default, but I'd like to hear your thoughts.
The reason this all came up is that many journals (at least in physics) specify that the text in graphs be the same as the main body text of the paper (almost always Times New Roman).
p.s. The seaborn defaults for sans-serif are also different from the matplotlib defaults, so I tried to follow that in coming up with a sensible list of defaults.
Yes I understand that seaborn changes the default sans serif font, but that is because it is part of the specific seaborn style. I am wary about feature creep -- seaborn is not meant to be a replacement for the matplotlib rc system, it just has a few canned styles for quickly changing a lot of settings. It does seem somewhat strange to be changing parameters that don't actually take effect in the default style. But I don't know, maybe it's not a big deal.
By the way, if you know that you have access to Times New Roman on your system, you can also do
sns.set(font="Times New Roman")
or
sns.set_style({'font.family': 'Times New Roman'})
Also if you have specified Times New Roman as your preferred serif font in a matplotlib rc file, you can just set font.family to 'serif' and I think it should work.
Thanks for the explanation, sounds reasonable to me. I hadn't considered the question of which parts of matplotlib seaborn should be replacing, so I'll leave that up to you.
I'll use those commands and close this ticket.
Most helpful comment
Yes I understand that seaborn changes the default sans serif font, but that is because it is part of the specific seaborn style. I am wary about feature creep -- seaborn is not meant to be a replacement for the matplotlib rc system, it just has a few canned styles for quickly changing a lot of settings. It does seem somewhat strange to be changing parameters that don't actually take effect in the default style. But I don't know, maybe it's not a big deal.
By the way, if you know that you have access to Times New Roman on your system, you can also do
or
Also if you have specified Times New Roman as your preferred serif font in a matplotlib rc file, you can just set
font.familyto'serif'and I think it should work.