Legend title pad in matplotlib - python

I would like the title in the legend of my matplotlib figure to be more distant from the content of the legend. Currently, I have the following:
I see the set_title function of the Legend class accepts a prop dictionary, which should be the one described in the text properties page. This one contains the field bbox, where a pad property could be added. But when I try something like the following
legend.set_title('Legend', prop={'bbox':{'pad':somepad}})
python complains that bbox is not an accepted parameter.
I'm using matplotlib 2.1.0 under Python 3.6.3 on Arch Linux.
An obvious workaround would be add a linebreak, like this:
legend.set_title('Legend\n ')
Although one might like the result, matplotlib has the great advantage that everything can be configured to the slightest detail, so I'm looking for a solution which gives me more fine-grained control over this spacing.

Of course introducing a linebreak in the title text as legend.set_title('Legend\n ') is a valid option.
If you don't like that you can set the separation between title and legend handle box manually as
legend._legend_box.sep = 20
Complete example:
import matplotlib.pyplot as plt
plt.plot([1,2], label="some")
plt.plot([1,3], label="label")
legend = plt.legend(title="Legend title", ncol=2)
legend._legend_box.sep = 20
plt.show()
The default separation is labelspacing * fontsize, hence
plt.rcParams["legend.labelspacing"] * plt.rcParams["font.size"] == 0.5 * 10 == 5

Related

Customising legend in Matplotlib

I’m trying to customise individual legend labels. In the example below, the legend contains two items. I’d like to make the text bold for only the second legend label.
Here’s a general outline of the code:
leg = plt.legend()
for text in leg.get_texts():
text.set_fontweight...
Here’s a runnable example:
import matplotlib.pyplot as plt
X=range(10)
Y=range(100,110)
Z=range(105,115)
plt.plot(X,Y,label='normal')
plt.plot(X,Z,label='bold')
fontweights=['normal','bold']
leg=plt.legend()
for fw,text in zip(fontweights,leg.get_texts()):
text.set_fontweight(fw)
plt.show()
Here's the output:
enter image description here
The plot produced shows that set_fontweight() changes both labels to bold. So is this a bug with set_fontweight(), or am I doing something wrong?
Similar functions, such as text.set_color(), can be used to modify legend labels individually.
Lastly, I’m using matplotlib version 3.2.2.
Thanks!
I have matplotlib 3.3.4 running, and get a bold and unbold legend entry - see attached image - so I think an upgrade should fix the problem.

Pyplot: leaving space for a bigger title

sns.boxplot(data=df, width=0.5)
plt.title(f'Distribution of scores for initial and resubmission\
\nonly among students who resubmitted at all.\
\n(n = {df.shape[0]})')
I want to use a bigger font, and leave more space in the top white margin so that the title doesn't get crammed in. Surprisingly, I am totally unable to find the option despite some serious googling!
The basic problem you have is that the multi-line title is too tall, and is rendered "off the page".
A few options for you:
the least effort solution is probably to use tight_layout(). plt.tight_layout() manipulates the subplot locations and spacing so that labels, ticks and titles fit more nicely.
if this isn't enough, also look at plt.subplots_adjust() which gives you control over how much whitespace is used around one or more subfigures; you can modify just one aspect at at time, and all the other settings are left alone. In your case, you could use plt.subplots_adjust(top=0.8).
If you are generating a final figure for publication or similar, you might be aiming to tweak a lot to perfect it. In this case, you can precisely control the (sub)plot locations, using add_axes (see this example https://stackoverflow.com/a/17479417).
Here is an example, with a 6-line title for emphasis. The left panel shows the default - with half the title clipped off. The right panel has all measurements the same except the top; the middle has automatically removed whitespace on all sides.
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
data = 55 + 5* np.random.randn(1000,) # some data
vlongtitle = "\n".join(["long title"]*6) # a 6-line title
# using tight_layout, all the margins are reduced
plt.figure()
sns.boxplot(data, width=0.5)
plt.title(vlongtitle)
plt.tight_layout()
# 2nd option, just edit one aspect.
plt.figure()
sns.boxplot(data, width=0.5)
plt.title(vlongtitle)
plt.subplots_adjust(top=0.72)

python matplotlib make everything bold

Well , I am making some plots and wants to make everything in bold font. I can can use weight="bold" to make bold font of label to ticks. Can also use the prop={'weight':'bold'} to make the legends lines bold, but I can't make the legend title bold. So, 1st question is there a way to make the legend title bold?
2nd,I tried to used matplotlib latex support to make the title bold, that did it but if I use rc('text', usetex=True) I cant use weight=bold and have to use \textbf{} everytime, also how do I make the ticks bold in this way.
3rd , If I use latex support then the font changes that I don't like. How do use the normal matplotlib font with using latex?
Making everything bold is rather easy. Just add
plt.rcParams["font.weight"] = "bold"
plt.rcParams["axes.labelweight"] = "bold"
at the top of the script.
import matplotlib.pyplot as plt
plt.rcParams["font.weight"] = "bold"
plt.rcParams["axes.labelweight"] = "bold"
plt.plot([2,3,1], label="foo")
plt.plot([3,1,3], label="bar")
plt.legend(title="Legend Title")
plt.xlabel("xLabel")
plt.show()
You should be able to pass parameters into the plt.legend using the prop argument
legend_prop = {'weight':'bold'}
plt.plot(x, y, label='some label')
plt.legend(prop=legend_prop)
This would give you bold labels. Is this not what you're looking for?

Upright mu in plot label: retaining original tick fonts

I have a problem which I thought would be more occurring. However, after scouring the internet for some time now I have not been able to find the solution to my problem. So here it goes:
For a plot, created using matplotlib.pyplot I want to incorporate the SI-unit micro meter into my xlabel. The unit micro meter however needs to be upright. After some fiddling around I achieved the desired xlabel.
The code that I have to generate this is:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('text', usetex = True)
params = {'text.latex.preamble': [r'\usepackage{siunitx}', r'\usepackage{cmbright}']}
plt.rcParams.update(params)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('$\si{\micro \meter}$', fontsize = 16)
ax.set_ylabel("hi", fontsize = 16)
plt.savefig("test.png")
The result is shown below:
The micro meter is exactly as I want it to be. The problem however is that the font of the x and y ticks is altered. This is because of:
matplotlib.rc('text', usetex = True)
How can I reset the font values to their original values? Or how can I make sure the fonts are not changed when introducing tex?
As a reference, the original values I am referring to look like this:
Besides trying to revert the fonts back to their original values I also tried different methods of incorporating micro meter into my xlabel. The problem that arises here is that I it remains italic or it has a bold type setting. The micro meter I am looking for is the one given in the first figure.
I hope someone can help me solve this problem.
Thanx in advance
What worked for me was not to usetex, but to use Unicode:
ax.set_xlabel(u'\u03bc')
sets the label as a single upright mu.
This requires the following settings when loading matplotlib:
import matplotlib
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rc('font', family='serif', serif='CMU Serif')
import matplotlib.pyplot as plt
Here I'm using the "Computer Modern Unicode" font from Sourceforge (highly recommended if you'd like consistency with writing typeset in LaTeX and its default Computer Modern font).
But any unicode font with the mu glyph should work. Actually, the mu from CMU Serif is not as aesthetically nice as the mu from SIunitx, but it is correct.
Python needed to be restarted for that to take effect.
I am also struggling with such a problem, i.e. getting the tick labels and axes labels to be consistent when text.usetex = True. The solution that I have managed to find it not ideal, but it works for the moment.
What you have to do is set the font family to "sans-serif" and also add a latex package that uses sans-serif math fonts (sfmath -- make sure it is in your tex path!)
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('text', usetex = True)
matplotlib.rc('font', **{'family':"sans-serif"})
params = {'text.latex.preamble': [r'\usepackage{siunitx}',
r'\usepackage{sfmath}', r'\sisetup{detect-family = true}',
r'\usepackage{amsmath}']}
plt.rcParams.update(params)
fig = plt.figure(figsize = (4,4))
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('$\si{\um} detection$')
ax.set_ylabel(r"$\mu \boldsymbol{\mu}$")
plt.show()
In addition, I had to tell the siunitx package to detect the font family, and I also had to add some additional text to the x-label in order for the detection to actually work (you can remove this text later and the label will still work after that).
For me this results in:
More generally, I have the following my ~/.matplotlib/matploblibrc file, for serif fonts:
font.family : serif
text.latex.preamble : \usepackage{mathptmx}
and for sans-serif:
font.family : sans-serif
text.latex.preamble : \usepackage{sfmath}
I had the same problem and this solved it:
In your matplotlibrc file change
mathtext.default : it
to
mathtext.default : regular

Add graph description under graph in pylab [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a way of drawing a caption box in matplotlib
Is it possible to add graph description under graph in pylab?
Let's say that I plot the following graph:
import pylab
x = [1,2,3,2,4,5,6,4,7,8]
pylab.plot(x)
pylab.title('My Plot')
pylab.xlabel('My x values')
pylab.ylabel('My y values')
pylab.show()
I also want to insert a few lines that describe the graph, perhaps something like this (not real code):
pylab.description('Figure 1.1 is designed for me to learn basics of Pylab')
Is that possible?
Also, I am vague on differences between pylab and matplotlib, so if there is a solution that works when using matplotlib, it will probably work.
Thank You in Advance
figtext is useful for this since it adds text in the figure coordinates, that is, 0 to 1 for x and y, regardless of the axes. Here's an example:
from pylab import *
figure()
gca().set_position((.1, .3, .8, .6)) # to make a bit of room for extra text
plot([1,2], [3,4])
figtext(.95, .9, "This is text on the side of the figure", rotation='vertical')
figtext(.02, .02, "This is text on the bottom of the figure.\nHere I've made extra room for adding more text.\n" + ("blah "*16+"\n")*3)
xlabel("an interesting axis label")
show()
Here I've used axes.set_position() to make some extra room on the bottom of the figure by making the axes a bit smaller. Here I added room for lots of text and also so the text doesn't bump into the axes label, though it's probably a bit excessive.
Although you asked for text on the bottom, I usually put such labels on the side, so they are more clearly notes and not part of the figure. (I've found it useful, for example, to have a little function that automatically puts the name of the file that generated each figure onto the figure.)

Categories

Resources