Comprehensively setting matplotlib font parameters - python

From what I understand of this documentation matplotlib provides 3 ways to change the style parameters for plotting (things like axes.grid). Those ways are: using style sheets to set many parameters at a time; setting specific parameters through matplotlib.rcParams or matplotlib.rc; or using a matplotlibrc file to set defaults.
I would like to understand if all of the parameters are accessible in each of the methods I listed above and where I can find a comprehensive list of all of the parameters.
I have tried to understand this from the linked documentation, but I often fail. A specific example is setting the axis font. I typically use a combination like this:
axis_font = {'fontname':'Arial', 'size':'32'}
ax.set_ylabel('some axis title',**axis_font)
But it is not clear what matplotlib parameter (if any) I have set. Does there exist a parameter for the axis font that could be included in a style file for example?
Other attempts in my code include confusing blocks like:
legend_font = {'fontname':'Arial', 'size':'22'}
#fonts global settings
matplotlib.rc('font',family=legend_font['fontname'])
By the names it seems like it would be changing the legend font, but actually it is clearly setting the parameter for the overall font. And the size is not being used. Are there matplotlib parameters for specifically the legend font and legend size?
The things I've tried are:
Checking the example matplotlibrc at the bottom of the linked page (no sign of axis or legend fonts specifically)
Printing matplotlib.rcParams (no sign of axis or legend fonts)
Checking the axis api (could not match up with example style files e.g. the classic predefined style file has facecolor set, which is mentioned in that page, but it also has edgecolor set which is not mentioned on the page)

The rcParams property which changes the font is font.family it accepts 'serif', 'sans-serif', 'cursive', 'fantasy', and 'monospace' as outlined in the linked sample matplotlibrc file. If text.usetex is False it also accepts any concrete font name or list of font names - which will be tried in the order they are specified until one works.
This method applies the specified font name to the entire figure (and to all figures when done globally). If you want to modify the font family for an individual Text instance (i.e. an axis label) you can use matplotlib.text.Text.set_family() (which is an alias for matplotlib.text.Text.set_fontfamily())
import matplotlib.pyplot as plt
ylabel = plt.ylabel("Y Label")
ylabel.set_family("DejaVu Serif")
plt.xlabel("X Label")
plt.show()
And to set the font family for just a legend instance you can use plt.setp, e.g.
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
ylabel = plt.ylabel("Y Label")
plt.xlabel("X Label")
ylabel.set_family("DejaVu Serif")
legend = plt.legend(handles = [mpatches.Patch(color='grey', label="Label")])
plt.setp(legend.texts, family="EB Garamond")
plt.show()
Note that this method will not work when text.usetex is True.

Related

Changing sns clustermap x axis, label color to white

I've set my plot to transparent so when i access it after plotting,axis and labels looks dark
How can i set the label's and axis to "white" .??
I've tried this
import seaborn as sns
DATA=sns.load_dataset("tips")
import matplotlib.pyplot as plt
plt.figure()
sns.set_style(style="white")
ax=sns.clustermap(DATA.corr(),
cmap="viridis")
#ax.xaxis.label.set_color('white')
#ax.yaxis.label.set_color('white')
plt.savefig("clustermap",transparent=True)
Note that i don't want to change the ' background ' color, just the label and axis color
You can probably use the seaborn.set() function. Here you have a previous answer:
Setting plot background colour in Seaborn
Here you have an example it seems to work in your case (at least in my environment ;-) ):
sns.set(rc={'axes.facecolor':'white', 'figure.facecolor':'white'})
to change just the axis's labels you can use this:
sns.set(rc{'ytick.labelcolor':'white','xtick.labelcolor':'white'})
There are a lot of very fine parameters to set your plot. You can review the full list of parameters just with the command:
plt.rcParams
You can get many details on such command in the link I gave before, going to the Joelostblom answer

I am very new to python, I want to increase the font size of my legend in sns.lmplot [duplicate]

The instructions from this question don't work for Seaborn FacetPlots. Would it be possible to get the method to do the same?
A facetgrid legend is not part of the axes, but part of the facetgrid object. The legend is still a standard matplotlib legend and can be manipulated as such.
plt.setp(g._legend.get_title(), fontsize=20)
Where g is your facetgrid object returned after you call the function making it.
If you're using a newer version of matplotlib there's an easier way to change legend font sizes -
plt.legend(fontsize='x-large', title_fontsize='40')
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html
Might depend on the version of matplotlib you're using. I'm using 2.2.3 and it has the fontsize parameter but not the title_fontsize.
As in the linked answer you may use setp to set the properties (in this case the fontsize of the legend).
The only difference to the linked question is that you need to do that for each axes of the FacetGrid
g = FacetGrid( ... )
for ax in g.axes.flat:
plt.setp(ax.get_legend().get_texts(), fontsize=22) # for legend text
plt.setp(ax.get_legend().get_title(), fontsize=32) # for legend title

Axis grid is not displayed when employing explicitly grid-containing style with matplotlib.pyplot.style.use('seaborn-whitegrid')

Even though I set the plotting style in every plotting script manually right at the beginning of the code, directly after importing the modules, the figure-plotting-style to seaborn-whitegrid, the resulting figures comprise the plain matplotlib.pyplot standard white background without grid display, e.g. like this graph:
Therefore, I assume that setting the style has no effect on my scripts, but I can't tell where it goes wrong, or where the style changes back to default. It'd be practical to print out the currently active plotting style at any given point, e.g. during a debugging session.
This is how I set my plotting style:
import .....
import matplotlib.pyplot as plt
import .....
# * Set the matplotlib.pyplot default template (plotting style and background) *
plt.style.use('seaborn-whitegrid')
# Start of script #
...
I even inserted the line plt.style.use('seaborn-whitegrid') in my plotting-submodules, which the main script calls, but it doesn't seem to have an effect on the output.
EDIT on additional trials:
According to what was suggested below by #Bernardo Trindade, I replaced plt.style.use with mpl.style.use:
# * Set the matplotlib.pyplot default template (plotting style and background) *
mpl_plt_default_template = 'seaborn-whitegrid'
import matplotlib as mpl
mpl.style.use(mpl_plt_default_template)
What I also tried is temporary styling, but with no avail either:
# Set plotting style
with plt.style.context('seaborn-whitegrid'):
# * Instantiate figure
fig, axs = plt.subplots(rows, cols, figsize=(width, height))
....
All of the above has not lead to any difference in the output graphs; still showing the plain standard matplotlib background without grid etc.
System specifics:
Lubuntu 20.04 LTS,
python 3.9x,
VS Code
I don't think there's a variable that stores the name of the stylesheet currently used, as all the style information is kept in a large dictionary whose values are simply updated when calling matplotlib.style.use().
Have you tried:
import matplotlib as mpl
mpl.style.use('seaborn-whitegrid')
Finally I found the culprit:
ax.grid(which='both', alpha=1)
Previously, this line never caused an issue, the grids were displayed just fine.
By contrast, now this setting the grid like this renders the grid invisible.
1) CONCLUSION (short answer)
The easiest way to make it work, i.e. safeguard that the grid appears, is setting either the parameter b to True like so:
ax.grid(b=True, which='both', alpha=1)
Alternatively, the kwarg visible can be set to True like so:
ax.grid(which='both', alpha=1, visible=True)
I recommend using visible=True since the naming of the kwarg is more intuitive as to what it actually does, compared to the optional parameter merely called b.
2) ELABORATE ANSWER
The following information is based on the official matplotlib docs:
The allegedly optional parameter b must be set manually to True or False, because otherwise, it'll be set to None in this context,
even though the current docs state:
b : bool or None, optional
Whether to show the grid lines. If any kwargs are supplied, it is assumed you want the grid on and b will be set to True.
If b is None and there are no kwargs, this toggles the visibility of the lines.
NOTE on boolean parameter "b":
I've tried both True and False to find out that even False delivers a proper grid, which is counterintuitive.
On the contrary, when put explicitely to None, which is equivalent to passing nothing, the grid won't appear:
ax.grid(b=None, which='both', alpha=1)
As mentioned before, the grid is invisible in this context also with the following, which was my original code line:
ax.grid(which='both', alpha=1)
Skimming through the **kwargs revealed an extra visibility kwarg called visible:
NOTE on naming of the visibility kwarg in its docs:
Artist.set_visible(self, b)[source]
It is called b, just like the
optional parameter
of ax.grid().
I confirmed that they actually do the same thing.
The grid appears, when putting the visible-kwarg to True:
ax.grid(b=None, which='both', alpha=1, visible=True)
When put to contradictory values, the following error is thrown:
ValueError: 'b' and 'visible' specify inconsistent grid visibilities
This error is caused when employing one of the following two possibilities:
ax.grid(b=False, which='both', alpha=1, visible=True)
ax.grid(b=True, which='both', alpha=1, visible=False)
Eventually, to make the grid appear successfully, set either the parameter b to True like so:
ax.grid(b=True, which='both', alpha=1)
Alternatively, the kwarg visible can be set to True like so:
ax.grid(which='both', alpha=1, visible=True)

set the font of xlabel to be Arial in matplotlib

I am wondering how to set the font of xlabel to be Arial using matplotlib. I checked functions like Axes.set_xlabel but does not see options to change that.
The Axes.set_xlabel and pyplot's xlabel functions can take the same keyword arguments as the Text class. This is noted in the documentation in the Other Parameters section.
One of these arguments is family, which can be used to set the font by family ('serif', 'sans-serif', etc., as shown in the font demo) or by font name. In your case it could be as simple as
plt.xlabel('My Label', family='Arial')
or
ax.set_xlabel('My Label', family='Arial')
# Assuming ax is an instance of Axes.

Python: Changing Marker Type in Seaborn

In regular matplotlib you can specify various marker styles for plots. However, if I import seaborn, '+' and 'x' styles stop working and cause the plots not to show - others marker types e.g. 'o', 'v', and '*' work.
Simple example:
import matplotlib.pyplot as plt
import seaborn as sns
x_cross = [768]
y_cross = [1.028e8]
plt.plot(x_cross, y_cross, 'ok')
plt.gca().set_xlim([10, 1e4])
plt.gca().set_ylim([1, 1e18])
plt.xscale('log')
plt.yscale('log')
plt.show()
Produces this: Simple Seaborn Plot
Changing 'ok' on line 6 to '+k' however, no longer shows the plotted point. If I don't import seaborn it works as it should: Regular Plot With Cross Marker
Could someone please enlighten me as to how I change the marker style to a cross type when seaborn being used?
The reason for this behaviour is that seaborn sets the marker edge width to zero. (see source).
As is pointed out in the seaborn known issues
An unfortunate consequence of how the matplotlib marker styles work is that line-art markers (e.g. "+") or markers with facecolor set to "none" will be invisible when the default seaborn style is in effect. This can be changed by using a different markeredgewidth (aliased to mew) either in the function call or globally in the rcParams.
This issue is telling us about it as well as this one.
In this case, the solution is to set the markeredgewidth to something larger than zero,
using rcParams (after importing seaborn):
plt.rcParams["lines.markeredgewidth"] = 1
using the markeredgewidth or mew keyword argument
plt.plot(..., mew=1)
However, as #mwaskom points out in the comments, there is actually more to it. In this issue it is argued that markers should be divided into two classes, bulk style markers and line art markers. This has been partially accomplished in matplotlib version 2.0 where you can obtain a "plus" as marker, using marker="P" and this marker will be visible even with markeredgewidth=0.
plt.plot(x_cross, y_cross, 'kP')
It is very like to be a bug. However you can set marker edge line width by mew keyword to get what you want:
import matplotlib.pyplot as plt
import seaborn as sns
x_cross = [768]
y_cross = [1.028e8]
# set marker edge line width to 0.5
plt.plot(x_cross, y_cross, '+k', mew=.5)
plt.gca().set_xlim([10, 1e4])
plt.gca().set_ylim([1, 1e18])
plt.xscale('log')
plt.yscale('log')
plt.show()

Categories

Resources