matplotlib: add special math symbol to xticklabels - python

I am following the example code here to produce a bar chart. I just want to add a superscript \textdagger(†) to the last group name "G5". Here is what I tried (check the line ax.set_xticklabels):
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
matplotlib.rc('text', usetex = True)
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std)
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5\textsuperscript{\textdagger}'))
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()
But the output is totally messed up.
How can I get a proper superscript † for "G5" then?

Many tex commands can be used within matplotlib without the need to use tex itself; this is called MathText. Like tex commands, you would enclose MathText command with two dollar signs.
'G5$^\dagger$'
Now, even if you use tex (plt.rc('text', usetex = True)) the command stays the same:
'G5$^\dagger$'

Related

Jupyter Notebook: Putting the numbers on top of the Bar [duplicate]

This question already has answers here:
Annotate bars with values on Pandas bar plots
(4 answers)
Closed 2 years ago.
I am new in Jupyer Notebook/Python. Can i ask what script should I add if I want my numbers, to be also placed on top of the bars?
please see image below.
If you are looking for something like this...
here is a sample code taken from this site
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std)
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()

Bar chart with label name and value on top in pandas [duplicate]

This question already has answers here:
Annotate bars with values on Pandas bar plots
(4 answers)
Closed 12 months ago.
I have two columns where i used groupby option create a df called output_duration_per_device such as
output_duration_per_device=s3_dataset.groupby('DeviceType')['Output_media_duration'].sum().reset_index(name ='format_duration')
output_duration_per_device
DeviceType format_duration
0 Alchemist 8.166905e+06
1 CaptionMaker 1.310864e+07
2 Elemental 1.818089e+07
3 EncodingCloud 0.000000e+00
4 FfMpeg 5.258470e+07
5 FlipFactory 4.747456e+02
6 Rhozet 6.263442e+08
7 Tachyon 4.827463e+06
I can make a bar chat and find like this
output_duration_per_device=s3_dataset.groupby('DeviceType')['Output_media_duration'].sum().reset_index(name ='Device_duration').plot(kind ='bar', figsize=(10,7), fontsize=13)
output_duration_per_device.set_alpha(0.8)
output_duration_per_device.set_title('DeviceType Output Media duration')
output_duration_per_device.set_xlabel('DeviceType')
plt.ylabel('Output_media_duration')
which gives me
but i want like below
please help me
Using plot and annotating via height (I would recommend fiddling with the spacing):
from decimal import Decimal
ax = df.plot(x='DeviceType', y='format_duration', kind='bar')
for p in ax.patches:
ax.annotate('{:.2E}'.format(Decimal(str(p.get_height()))), (p.get_x(), p.get_height()))
plt.tight_layout()
plt.show()
"""
Barchart
A bar plot with errorbars and height labels on individual bars
"""
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std)
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()
Bar Chart output
The following code is collected from Matplotlib official website. Please take a look. click here

Removing the bottom error caps only on matplotlib

I wanted to display only half error bars, as they are symetric ; as I had no clue how to do this with a "clean way", I chose to use asymetric errors with 0 on the bottom side ; but then, when I displayed caps, I realised this was not the best way to do this.
Here's the code :
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N)
width = 0.35
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r',yerr=[np.zeros(len(men_std)),men_std],capsize = 5)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y',yerr=[np.zeros(len(women_std)),women_std],capsize = 5)
plt.show()
And this is the plot I get :. As you can see, my way of plotting half error bars is probably not what should be done.
So is there any way to hide the bottom cap line or a better way to plot half error bars ?
ax.errorbar has the option to set uplims=True or lolims=True to signify that the means repesent the upper or lower limits, respectively. Unfortunately, it doesn't seem like you can use these options directly with ax.bar, so we have to plot the errorbar and the bar plot separately.
The documentation for the uplims/lolims options in ax.errorbar:
lolims / uplims / xlolims / xuplims : bool, optional, default:None
These arguments can be used to indicate that a value gives only upper/lower limits. In that case a caret symbol is used to indicate this. lims-arguments may be of the same type as xerr and yerr. To use limits with inverted axes, set_xlim() or set_ylim() must be called before errorbar().
Note that using this option changes your caps to arrows. See below for an example of how to change them back to caps, if you need flat caps instead of arrows.
You can see these options in action in this example on the matplotlib website.
Now, here's your example, modified:
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N)
width = 0.35
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r')
err1 = ax.errorbar(ind, men_means, yerr=men_std, lolims=True, capsize = 0, ls='None', color='k')
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y')
err2 = ax.errorbar(ind + width, women_means, yerr=women_std, lolims=True, capsize = 0, ls='None', color='k')
plt.show()
If you don't like the arrows, you change them to flat caps, by changing the marker of the caplines that are returned (as the second item) from ax.errorbar. We can change them from the arrows to the marker style _, and then control their size with .set_markersize:
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N)
width = 0.35
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r')
plotline1, caplines1, barlinecols1 = ax.errorbar(
ind, men_means, yerr=men_std, lolims=True,
capsize = 0, ls='None', color='k')
caplines1[0].set_marker('_')
caplines1[0].set_markersize(20)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y')
plotline2, caplines2, barlinecols2 = ax.errorbar(
ind + width, women_means, yerr=women_std,
lolims=True, capsize = 0, ls='None', color='k')
caplines2[0].set_marker('_')
caplines2[0].set_markersize(10)
plt.show()
A simpler solution is to use zorder. The grid has zorder=0. Setting the errorbar to zorder=1 and the bar to zorder=2and lowering the bottom error a bit will hide the lower error bar with little effort. This also allows to use bar_label. The only downside is if alpha is used for the bars.
I also changed to use np.zeros_like(std) instead of np.zeros(len(std)) and use error_kw to style the errorbar.
import numpy as np
import matplotlib.pyplot as plt
N = 5
ind = np.arange(N)
width = 0.8
fig, ax = plt.subplots()
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y',yerr=[np.zeros_like(women_std)+0.5,women_std],zorder=2,error_kw=dict(capsize = 10, capthick=1,zorder=1))
ax.bar_label(rects2,labels=[f'{v:.2f} ± {e:.2f}' for v,e in zip(women_means, women_std)], padding=10, fontsize=14, label_type='edge')
fig.tight_layout()
plt.show()
Many thanks,
based on your answer, method below is my solution:
def process_error_bar(ax, x, y, y_err, marker_size):
"""
hide half error_bar
:param ax: plt.subplots()
:param x: x position
:param y: y position
:param y_err: y errors
:param marker_size: size
"""
lolims = []
uplims = []
for y_value in y:
if y_value < 0:
lolims.append(False)
uplims.append(True)
else:
lolims.append(True)
uplims.append(False)
plotline, caplines, barlinecols = ax.errorbar(
x, y, yerr=y_err, lolims=lolims, uplims=uplims,
capsize=0, ls='None', color='k')
# [arrow] -> [-]
for capline in caplines:
capline.set_marker('_')
capline.set_markersize(marker_size)

matplotlib bar chart example not matching website

i am running the below code in python 2, taken directly from this site:
http://matplotlib.org/examples/api/barchart_demo.html
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std)
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std)
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()
what is strange is that when this displays the first bar corresponding to "G1" displays touching the edge of the y-axis, and not how it shows on the website.
i am having this same issue with other bar charts im creating so trying to understand how i can space the bars out - basically leaving a margin on either side.
The example you link to is for matplotlib version 2.0. However you are running 1.5 or below. So you need to refer to the example of the previous versions: barchart example for 1.5.
Alternatively, you can update matplotlib to version 2.0.
In order to add space at the edges, you can use
plt.margins(x=0.05) or ax.margins(x=0.05)
with any number as a fraction of axis length you like.
Alternatively you can set the limits of the axes,like
plt.xlim((0,N)) or ax.set_xlim((0,N))
where N is the number of bars.

How to increase the thickness of error line in a matplotlib bar chart?

Please refer the minimum working example here.
The bar chart is plotted as shown below but I can't find a way to increase the thickness of the error lines. The elinewidth option is not available in ax.bar
> rects1 = ax.bar(..., elinewidth=3)
AttributeError: Unknown property elinewidth
The following links require the use of ax.errorbar()
Change errorbar size
How to set the line width of error bar caps, in matplotlib?
But is there an option that can be supplied directly to ax.bar()?
You can use the error_kw parameters as follows:
error_kw=dict(lw=5, capsize=5, capthick=3)
So in the example, it would be:
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std, error_kw=dict(lw=5, capsize=5, capthick=3))
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std, error_kw=dict(lw=5, capsize=5, capthick=3))
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width() / 2,
1.05 * height,
f'{height:.0f}',
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()
Giving you:
An improvement to this would be to display the values above each of the error bars. This can be done by first obtaining the error bar heights as follows:
import numpy as np
import matplotlib.pyplot as plt
N = 5
men_means = (20, 35, 30, 35, 27)
men_std = (2, 3, 4, 1, 2)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, men_means, width, color='r', yerr=men_std, error_kw=dict(lw=5, capsize=5, capthick=3))
women_means = (25, 32, 34, 20, 25)
women_std = (3, 5, 2, 3, 3)
rects2 = ax.bar(ind + width, women_means, width, color='y', yerr=women_std, error_kw=dict(lw=5, capsize=5, capthick=3))
# add some text for labels, title and axes ticks
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.set_ylim(0, 45) # Add space for errorbar height
ax.legend((rects1[0], rects2[0]), ('Men', 'Women'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
data_line, capline, barlinecols = rects.errorbar
for err_segment, rect in zip(barlinecols[0].get_segments(), rects):
height = err_segment[1][1] # Use height of error bar
ax.text(rect.get_x() + rect.get_width() / 2,
1.05 * height,
f'{height:.0f}',
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
plt.show()
Giving you:
Note: The y axis limit would need to be calculated.

Categories

Resources