How can I make the legend text 'bold ' in Python - python

I want to make the legend 'bold' I also want to change the font style of the legend like times new roman etc.
plt.gca().legend(('Experimental Values','Simulated Values'))
params = {'legend.fontsize': 15, 'legend.handlelength': 1}
plot.rcParams.update(params)
plt.figure(figsize=(6,6))

edit/update:
I have found a nice and complete example here
Try this:
import numpy as np
import matplotlib.font_manager as font_manager
fig, (ax0) = plt.subplots(1, 1, figsize=(10,5));
xx = np.arange(10)
yy = 0.3*xx
plt.plot(xx,yy,label='Line')
font = font_manager.FontProperties(family= 'Comic Sans MS', # 'Times new roman',
weight='bold',
style='normal', size=25)
plt.legend(loc="best" , prop=font)
plt.show()

The following code solved my problem.
plt.gca().legend(('Experimental Values','Simulated Values'))
params = {'legend.fontsize':10, 'legend.handlelength': 1, 'font.weight': 'bold'}
plot.rcParams.update(params)
plt.figure(figsize=(6,6))

Related

How to change scientific notation form in Matplotlib

This is my code.
time = sig[:, 0] # data first column: time
displacement = sig[:, 1] # data second column: displacement
font = {'family': 'Times New Roman', 'weight': 'bold', 'size': 16}
fig, ax = plt.subplots(figsize = (9, 8)) # set figure size (width,height)
ax.plot(time, displacement, linewidth = 2)
ax.set_xlim(0, 3e-3) # set x-axis limit
ax.set_ylim(-4e-6, 1e-6) # set y-axis limit
ax.set_xticklabels([0, 0.5, 1, 1.5, 2, 2.5, 3])
ax.tick_params(labelsize = 16) # tick_params can only change label size
labels = ax.get_xticklabels() + ax.get_yticklabels()
for label in labels: # thus use for loop(?) change font name and weight
label.set_fontname('Times New Roman')
label.set_fontweight('bold')
ax.set_xlabel('Time (msec.)', font)
ax.set_ylabel('Displacement (m)', font)
plt.show()
And this is the code's result.
But actually, that's what I want to get.
How can I change the notation form from 1e-6 to 10^-6 and also make the font bold.
To change the scientific notation of ticklabel:
ax.ticklabel_format(useMathText=True)
To change the text properties, grab the text object with:
ty = ax.yaxis.get_offset_text()
ty.set_fontweight('bold')
ty.set_size(16)

Change fontsize of indivual labels in the matplotlib legend

I would like to change the font size of individual elements in the legend. I know how to change the font properties of the whole legend but I can not figure out a way to change them individually.
For example: In the example below I am plotting two lines and I want the label for line1 to have a bigger font size than line 2
import numpy as np
from matplotlib import pyplot as plt
def line (m , c):
return m*x + c
x = np.arange(0, 10, .25)
plt.plot(x, line(1, 0), label = "Line 1")
plt.plot(x, line(1,1), label = "Line 2")
plt.legend(prop={'family': 'Georgia', 'size': 15})
plt.show()
Using prop={'family': 'Georgia', 'size': 15} I can modify the font size of both the labels simultaneously but is there a way to control the font properties of individual labels in the legend?
Thanks any and all help is appreciated.
Here are some great answers: one is to set the font properties, and the other is to use Latexh notation for the label settings. I will answer with the method of customizing with font properties.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontProperties
def line (m , c):
return m*x + c
x = np.arange(0, 10, .25)
plt.plot(x, line(1, 0), label = "Line 1")
plt.plot(x, line(1,1), label = "Line 2")
leg = plt.legend(prop={'family': 'Georgia', 'size': 15})
label1, label2 = leg.get_texts()
label1._fontproperties = label2._fontproperties.copy()
label1.set_size('medium')
plt.show()

How do I give some space between Y axis and my starting and ending vertical bars in Matplotlib

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.pyplot import figure
plt.style.use('ggplot')
overs = np.arange(1, 51)
india_score = np.random.randint(low = 1, high = 18, size = 50, dtype = 'int16')
plt.bar(overs, india_score, width = 0.80, align = 'center', color = 'orange', label = 'Runs per over')
plt.xlabel('Overs')
plt.ylabel('Score')
plt.title('India Inning')
plt.axis([1, 50, 0, 18])
plt.legend()
plt.grid(color='k', linestyle='-', linewidth=1)
fig = plt.gcf()
fig.set_size_inches(16, 9)
plt.show()
The output looks like this:
If you see the bar chart then runs scored in first over and runs scored in last over stick to the Y axis. How can I give some space between Y axis and my first and last vertical bars. I tried the margins function but that is not working
I searched for similar posts but I was unable to understand the solution as I am new to matplotlib. Any help will be greatly appreciated. Thanks.
Here is how you could do this:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.pyplot import figure
plt.style.use('ggplot')
overs = np.arange(1, 51)
india_score = np.random.randint(low = 1, high = 18, size = 50, dtype = 'int16')
plt.bar(overs, india_score, width = 0.80, align = 'center', color = 'orange', label = 'Runs per over')
plt.xlabel('Overs')
plt.ylabel('Score')
plt.title('India Inning')
plt.axis([1, 50, 0, 18])
plt.legend()
plt.grid(color='k', linestyle='-', linewidth=1)
fig = plt.gcf()
fig.set_size_inches(16, 9)
left, right = plt.xlim()
plt.xlim(left-1, right+1)
plt.show()
left, right = plt.xlim() gets the current limits of the x-axis and plt.xlim(left-1, right+1) sets the new limits by one step further outside relative to the old limits.

Legend is cut off, solving the issue is affecting the font size in an unwanted way

I am creating a figure in Matplotlib with the following code and I hope it is not too messy:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import locale
locale.setlocale(locale.LC_ALL, 'German')
#the data to be plotted
CSB = [9205.0, 8845.0, 19740.0, 410.0, 11560.0, 11632.0, 14368.0,
11556.0, 9846.0, 14544.0]
DOC = [np.nan, 1853.0, 4172.0, 259.0, np.nan, np.nan, np.nan, np.nan,
np.nan, np.nan]
NH3N = [3593.5, 3318.8, 5208.0, 306.4, 2708.2, 2682.1, 2812.3, 3033.1,
3098.4, 3815.9]
x = np.linspace(1, 10, 10)
Daten = ['09.05.2017', '16.05.2017', '23.05.2017', '06.06.2017', '28.08.2017',
'31.08.2017', '04.09.2017', '07.09.2017', '14.09.2017', '18.09.2017']
#setting the font and font size globally
font = {'family' : 'Arial',
'size' : 12}
matplotlib.rc('font', **font)
fig, ax1 = plt.subplots()
#first plot
l1, = ax1.plot(x, NH3N, 'k+', label='NH$_3$-N-Konzentration', ms=8)
ax1.set_ylabel(r'NH$_3$-N-Konzentration $[\frac{mg}{L}]$')
ax1.set_xlabel('Datum Probenahme')
ax1.set_ylim([0,10000])
ax1.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
#getting the x tick lables fitted to dates
plt.xticks(x, Daten, rotation=30)
fig.autofmt_xdate()
plt.subplots_adjust(bottom=0.3)
#second plot as a parasite of the first
ax2 = ax1.twinx()
l2, = ax2.plot(x, CSB, 'k.', label='CSB-Konzentration', ms=8)
ax2.set_ylabel(r'CSB-Konzentration $[\frac{mg}{L}]$')
ax2.set_ylim([0,25000])
ax2.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
#third plot as a parasite of the first
ax3 = ax1.twinx()
l3, = ax3.plot(x, DOC, 'k^', label='DOC-Konzentration', ms=8)
ax3.set_ylabel(r'DOC-Konzentration $[\frac{mg}{L}]$')
ax3.set_ylim([0,5000])
ax3.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
#manipulating the position of the third y axis
ax3.tick_params(direction='in', pad=-50)
ax3.spines['left'].set_position(('axes', 1.3))
ax3.yaxis.set_ticks_position('left')
ax3.yaxis.set_label_coords(1.48,0.5)
fig.legend((l1,l2,l3),('NH$_3$-N-Konzentration','CSB-Konzentration',
'DOC-Konzentration'), loc=9, ncol = 3, bbox_to_anchor=(0.75, 0.15))
plt.savefig('CSB_NH3N_DOC_unbehandeltes_Abwasser.eps', format='eps',
dpi=1000, bbox_inches='tight')
plt.show()
The code is resulting in this graph, which is supposed to be part of a Latex file. I am pretty new to Python, so I might have overlooked something or there might be other issues, besides the one I am asking for: I am sorry for that.
Now to my problem: the legend is supposed to be below the figure, which I can accomplish with the bbox_to_anchor attribute. This results in a cut off legend, a problem I tried to solve with
plt.margins(0.2)
plt.subplots_adjust(bottom=0.30)
and/or
plt.tight_layout()
and/or
bbox_inches='tight'
In the end, all of this is either scaling the hole figure in an awkward way or at least scaling the font size, an issue that gets obvious, when the figure is added to the Latex file. I think the whole twinx() thing is making everything quite unstable, but for me as a newbie it seemed to be an easier solution than this. Reading a lot of questions like this to find an answer it seems there is no easy way like "just add some space to the bottom manually without scaling", but I have to try and ask anyway.
Is there a way to put the legend to the very bottom of the figure and keeping the font size and the look of the figure as it is i.e. without any scaling commands?
Use
loc="lower center", bbox_to_anchor=(0.5, 0.)
where "lower" means that the anchor point's y coordinate (0.) refers to the lower border of the legend and "center" that the x coordinate (0.5) refers to the center of the legend. Both coordinates have a range of 0 to 1. This is illustrated in How to specify legend position in matplotlib in graph coordinates
I now followed the general example and with some help I was able to get to the result I aimed at. Here is the code with a proper positioning of the legend:
import matplotlib.pyplot as plt
import numpy as np
CSB = [9205.0, 8845.0, 19740.0, 410.0, 11560.0, 11632.0, 14368.0,
11556.0, 9846.0, 14544.0]
DOC = [np.nan, 1853.0, 4172.0, 259.0, np.nan, np.nan, np.nan, np.nan,
np.nan, np.nan]
NH3N = [3593.5, 3318.8, 5208.0, 306.4, 2708.2, 2682.1, 2812.3, 3033.1,
3098.4, 3815.9]
x = np.linspace(1, 10, 10)
Daten = ['09.05.2017', '16.05.2017', '23.05.2017', '06.06.2017', '28.08.2017',
'31.08.2017', '04.09.2017', '07.09.2017', '14.09.2017', '18.09.2017']
font = {'family' : 'Arial',
'size' : 12}
plt.rc('font', **font)
fig = plt.figure()
host = fig.add_subplot(111)
par1 = host.twinx()
par2 = host.twinx()
host.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
par1.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
par2.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x,
loc: "{0:n}".format(float(x))))
offset = 85
par2.spines['right'].set_position(('outward', offset))
host.set_xlim(0, 11)
host.set_ylim(0, 10000)
host.set_xlabel("Datum Probenahme")
host.set_ylabel(r'NH$_3$-N-Konzentration $[\frac{mg}{L}]$')
par1.set_ylabel(r'CSB-Konzentration $[\frac{mg}{L}]$')
par2.set_ylabel(r'DOC-Konzentration $[\frac{mg}{L}]$')
host.set_xticks(x)
host.set_xticklabels(Daten)
p1, = host.plot(x, NH3N, '+k', label='NH$_3$-N-Konzentration')
p2, = par1.plot(x, CSB, '.k', label=r'CSB-Konzentration')
p3, = par2.plot(x, DOC, '^k', label=r'DOC-Konzentration')
par1.set_ylim(0, 25000)
par2.set_ylim(0, 5000)
host.legend((p1,p2,p3),('NH$_3$-N-Konzentration','CSB-Konzentration','DOC-Konzentration'), loc='lower center', ncol = 3, bbox_to_anchor=(0.5, -0.5))
fig.autofmt_xdate()
plt.tight_layout()
plt.show()
Next time I will take an even closer look at the gallery. Thanks a lot for your time!

Matplotlib 2 inconsistent font

I updated Anaconda Python to the latest version (4.3), where they upgraded Matplotlib to version 2.
The upgrade has made some major changes to the default style (see here).
And, while I really like some of those changes, I am not in agreement with a few of them.
Hence I did some modifications, as suggested in the link above:
#%matplotlib inline
#%config InlineBackend.figure_format = 'svg'
import scipy as sc
import matplotlib.pyplot as plt
import matplotlib
# http://matplotlib.org/users/dflt_style_changes.html
params = {'legend.fontsize': 18,
'axes.labelsize': 18,
'axes.titlesize': 18,
'xtick.labelsize' :12,
'ytick.labelsize': 12,
'mathtext.fontset': 'cm',
'mathtext.rm': 'serif',
'grid.color': 'k',
'grid.linestyle': ':',
'grid.linewidth': 0.5,
}
matplotlib.rcParams.update(params)
x = sc.linspace(0,100)
y = x**2
fig = plt.figure('Fig')
ax = fig.add_subplot(1, 1, 1)
lines = ax.semilogy(x, y)
ax.set_yticks([300], minor=True)
ax.yaxis.grid(True, which='minor')
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.tick_params(axis='y', pad=10)
ax.set_xlabel(r'$\mathrm{R_L}$')
ax.set_ylabel(r'$\sigma \int_l \; dx$')
#fig.savefig('./PNG/test.png', dpi=300, bbox_inches='tight')
Using Latex as the axes labels, as in the code above, results in a figure with inconsistent text on axes (see the following image).
How to get back to the previous behaviour (see the image below) or to a consistent font scheme?
EDIT:
Using the Latex back-end I am able to get a good result, but it is extremely slow.
Anyway, I think the internal back-end should be able to get a consistent output and switching to a different back-end is not a real solution, but more a workaround.
To use the latex back-end:
#%matplotlib inline
#%matplotlib notebook
#%config InlineBackend.figure_format = 'svg'
import scipy as sc
import matplotlib.pyplot as plt
import matplotlib
# http://matplotlib.org/users/dflt_style_changes.html
params = {'legend.fontsize': 18,
'axes.labelsize': 18,
'axes.titlesize': 18,
'xtick.labelsize' :12,
'ytick.labelsize': 12,
'mathtext.fontset': 'cm',
'mathtext.rm': 'serif',
'grid.color': 'k',
'grid.linestyle': ':',
'grid.linewidth': 0.5,
}
matplotlib.rcParams.update(params)
matplotlib.rcParams.update({'text.usetex':True, 'text.latex.preamble':[r'\usepackage{amsmath, newtxmath}']})
x = sc.linspace(0,100)
y = x**2
fig = plt.figure('Fig')
ax = fig.add_subplot(1, 1, 1)
lines = ax.semilogy(x, y)
ax.set_yticks([300], minor=True)
ax.yaxis.grid(True, which='minor')
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.tick_params(axis='y', pad=10)
ax.set_xlabel(r'$\mathrm{R_L}$')
ax.set_ylabel(r'$\sigma \int_l \; dx$')
#fig.savefig('./PNG/test.png', dpi=300, bbox_inches='tight')
The result with matplotlib 2 is:
The resulting plot with the older version is (still a bit different, maybe due to some latex differences):
But again, the desired result is what obtained from an older version of matplotlib and in displayed in figure 2.
If consistency is the only issue, you can use a "Roman" style using the "Times" font. It is not necessary to use Latex via usetex. Instead simply use the STIX fontset, the Times font and serif mathtext.
import scipy as sc
import matplotlib.style
import matplotlib.pyplot as plt
params = {'legend.fontsize': 18,
'axes.labelsize': 18,
'axes.titlesize': 18,
'xtick.labelsize' :12,
'ytick.labelsize': 12,
'grid.color': 'k',
'grid.linestyle': ':',
'grid.linewidth': 0.5,
'mathtext.fontset' : 'stix',
'mathtext.rm' : 'serif',
'font.family' : 'serif',
'font.serif' : "Times New Roman", # or "Times"
}
matplotlib.rcParams.update(params)
x = sc.linspace(0,100)
y = x**2
fig = plt.figure('Fig')
ax = fig.add_subplot(1, 1, 1)
lines = ax.semilogy(x, y)
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.tick_params(axis='y', pad=10)
ax.set_yticks([300], minor=True)
ax.yaxis.grid(True, which='minor')
ax.set_xlabel(r'$\mathrm{R_L}$')
ax.set_ylabel(r'$\sigma \int_l \; dx$')
plt.tight_layout()
plt.show()
From the link you did provide:
A ‘classic’ style sheet is provided so reverting to the 1.x default values is a single line of python
mpl.style.use('classic')
Adding this line
matplotlib.style.use('classic')
to your script should solve your problem.
I tested it on my python2.7/matplotlib 2, and it worked fine (i.e. I get back the matplotlib 1.x fonts).
While trying to find a solution to my question, I tried comparing the dictionaries of the old and new rcParams and setting the elements which were different and related to mathtext font: the result is quite good.
The code is:
#%matplotlib inline
#%matplotlib notebook
#%config InlineBackend.figure_format = 'svg'
import scipy as sc
import matplotlib.pyplot as plt
import matplotlib
# http://matplotlib.org/users/dflt_style_changes.html
params = {'legend.fontsize': 18,
'axes.labelsize': 18,
'axes.titlesize': 18,
'xtick.labelsize' :12,
'ytick.labelsize': 12,
'mathtext.fontset': 'cm',
'mathtext.rm': 'serif',
'mathtext.bf': 'serif:bold',
'mathtext.it': 'serif:italic',
'mathtext.sf': 'sans\\-serif',
'grid.color': 'k',
'grid.linestyle': ':',
'grid.linewidth': 0.5,
}
matplotlib.rcParams.update(params)
#matplotlib.rcParams.update({'text.usetex':True, 'text.latex.preamble':[r'\usepackage{amsmath, newtxmath}']})
#matplotlib.rcParams.update({'text.usetex':True, 'text.latex.preamble':[r'\usepackage{amsmath, mathptmx}']})
#matplotlib.rcParams.update({'text.usetex':True, 'text.latex.preamble':[r'\usepackage{amsmath}']})
x = sc.linspace(0,100)
y = x**2
fig = plt.figure('Fig')
ax = fig.add_subplot(1, 1, 1)
lines = ax.semilogy(x, y)
ax.set_yticks([300], minor=True)
ax.yaxis.grid(True, which='minor')
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.tick_params(axis='y', pad=10)
ax.set_xlabel(r'$\mathrm{R_L}$')
ax.set_ylabel(r'$\sigma \int_l \; dx$')
fig.savefig('./PNG/test.png', dpi=300, bbox_inches='tight')
hence adding also:
'mathtext.rm': 'serif',
'mathtext.bf': 'serif:bold',
'mathtext.it': 'serif:italic',
'mathtext.sf': 'sans\\-serif',
which results in:
that I consider quite good and consistent in a Latex document.
The other answer in this thread from #ImportanceOfBeingErnest is also neat and nice.

Categories

Resources