How to display the value of the bar on each bar with pyplot.barh()?
I generated a bar plot, how can I display the value of the bar on each bar?
Current plot:
What I am trying to get:
My code:
import os
import numpy as np
import matplotlib.pyplot as plt
x = [u'INFO', u'CUISINE', u'TYPE_OF_PLACE', u'DRINK', u'PLACE', u'MEAL_TIME', u'DISH', u'NEIGHBOURHOOD']
y = [160, 167, 137, 18, 120, 36, 155, 130]
fig, ax = plt.subplots()
width = 0.75 # the width of the bars
ind = np.arange(len(y)) # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('title')
plt.xlabel('x')
plt.ylabel('y')
#plt.show()
plt.savefig(os.path.join('test.png'), dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
python matplotlib bar-chart
add a comment |
I generated a bar plot, how can I display the value of the bar on each bar?
Current plot:
What I am trying to get:
My code:
import os
import numpy as np
import matplotlib.pyplot as plt
x = [u'INFO', u'CUISINE', u'TYPE_OF_PLACE', u'DRINK', u'PLACE', u'MEAL_TIME', u'DISH', u'NEIGHBOURHOOD']
y = [160, 167, 137, 18, 120, 36, 155, 130]
fig, ax = plt.subplots()
width = 0.75 # the width of the bars
ind = np.arange(len(y)) # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('title')
plt.xlabel('x')
plt.ylabel('y')
#plt.show()
plt.savefig(os.path.join('test.png'), dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
python matplotlib bar-chart
add a comment |
I generated a bar plot, how can I display the value of the bar on each bar?
Current plot:
What I am trying to get:
My code:
import os
import numpy as np
import matplotlib.pyplot as plt
x = [u'INFO', u'CUISINE', u'TYPE_OF_PLACE', u'DRINK', u'PLACE', u'MEAL_TIME', u'DISH', u'NEIGHBOURHOOD']
y = [160, 167, 137, 18, 120, 36, 155, 130]
fig, ax = plt.subplots()
width = 0.75 # the width of the bars
ind = np.arange(len(y)) # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('title')
plt.xlabel('x')
plt.ylabel('y')
#plt.show()
plt.savefig(os.path.join('test.png'), dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
python matplotlib bar-chart
I generated a bar plot, how can I display the value of the bar on each bar?
Current plot:
What I am trying to get:
My code:
import os
import numpy as np
import matplotlib.pyplot as plt
x = [u'INFO', u'CUISINE', u'TYPE_OF_PLACE', u'DRINK', u'PLACE', u'MEAL_TIME', u'DISH', u'NEIGHBOURHOOD']
y = [160, 167, 137, 18, 120, 36, 155, 130]
fig, ax = plt.subplots()
width = 0.75 # the width of the bars
ind = np.arange(len(y)) # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('title')
plt.xlabel('x')
plt.ylabel('y')
#plt.show()
plt.savefig(os.path.join('test.png'), dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
python matplotlib bar-chart
python matplotlib bar-chart
asked May 14 '15 at 1:55
Franck DernoncourtFranck Dernoncourt
37.8k32196344
37.8k32196344
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
Add:
for i, v in enumerate(y):
ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
result:
The y-values v
are both the x-location and the string values for ax.text
, and conveniently the barplot has a metric of 1 for each bar, so the enumeration i
is the y-location.
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
add a comment |
I have noticed api example code contains an example of barchart with the value of the bar displayed on each bar:
"""
========
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()
output:
FYI What is the unit of height variable in "barh" of matplotlib? (as of now, there is no easy way to set a fixed height for each bar)
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
add a comment |
I know it's an old thread, but I landed here several times via Google and think no given answer is really satisfying yet. Try using one of the following functions:
EDIT: As I'm getting some likes on this old thread, I wanna share an updated solution as well (basically putting my two previous functions together and automatically deciding whether it's a bar or hbar plot):
def label_bars(ax, bars, text_format, **kwargs):
"""
Attaches a label on every bar of a regular or horizontal bar chart
"""
ys = [bar.get_y() for bar in bars]
y_is_constant = all(y == ys[0] for y in ys) # -> regular bar chart, since all all bars start on the same y level (0)
if y_is_constant:
_label_bar(ax, bars, text_format, **kwargs)
else:
_label_barh(ax, bars, text_format, **kwargs)
def _label_bar(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
"""
max_y_value = ax.get_ylim()[1]
inside_distance = max_y_value * 0.05
outside_distance = max_y_value * 0.01
for bar in bars:
text = text_format.format(bar.get_height())
text_x = bar.get_x() + bar.get_width() / 2
is_inside = bar.get_height() >= max_y_value * 0.15
if is_inside:
color = "white"
text_y = bar.get_height() - inside_distance
else:
color = "black"
text_y = bar.get_height() + outside_distance
ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)
def _label_barh(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
Note: label always outside. otherwise it's too hard to control as numbers can be very long
"""
max_x_value = ax.get_xlim()[1]
distance = max_x_value * 0.0025
for bar in bars:
text = text_format.format(bar.get_width())
text_x = bar.get_width() + distance
text_y = bar.get_y() + bar.get_height() / 2
ax.text(text_x, text_y, text, va='center', **kwargs)
Now you can use them for regular bar plots:
fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)
or for horizontal bar plots:
fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
add a comment |
For anyone wanting to have their label at the base of their bars just divide v by the value of the label like this:
for i, v in enumerate(labels):
axes.text(i-.25,
v/labels[i]+100,
labels[i],
fontsize=18,
color=label_color_list[i])
(note: I added 100 so it wasn't absolutely at the bottom)
To get a result like this:
add a comment |
For pandas people :
ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
That's it.
Alternatively, for those who prefer apply
over looping with enumerate:
it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));
Also, ax.patches
will give you the bars that you would get with ax.bar(...)
. In case you want to apply the functions of @SaturnFromTitan or techniques of others.
add a comment |
I needed the bar labels too, note that my y-axis is having a zoomed view using limits on y axis. The default calculations for putting the labels on top of the bar still works using height (use_global_coordinate=False in the example). But I wanted to show that the labels can be put in the bottom of the graph too in zoomed view using global coordinates in matplotlib 3.0.2. Hope it help someone.
def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True
if use_global_coordinate:
for i in data:
ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
verticalalignment='center', transform=ax.transAxes,fontsize=8)
c=c+1
else:
for rect,i in zip(rects,data):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f30228069%2fhow-to-display-the-value-of-the-bar-on-each-bar-with-pyplot-barh%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
Add:
for i, v in enumerate(y):
ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
result:
The y-values v
are both the x-location and the string values for ax.text
, and conveniently the barplot has a metric of 1 for each bar, so the enumeration i
is the y-location.
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
add a comment |
Add:
for i, v in enumerate(y):
ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
result:
The y-values v
are both the x-location and the string values for ax.text
, and conveniently the barplot has a metric of 1 for each bar, so the enumeration i
is the y-location.
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
add a comment |
Add:
for i, v in enumerate(y):
ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
result:
The y-values v
are both the x-location and the string values for ax.text
, and conveniently the barplot has a metric of 1 for each bar, so the enumeration i
is the y-location.
Add:
for i, v in enumerate(y):
ax.text(v + 3, i + .25, str(v), color='blue', fontweight='bold')
result:
The y-values v
are both the x-location and the string values for ax.text
, and conveniently the barplot has a metric of 1 for each bar, so the enumeration i
is the y-location.
edited May 23 '17 at 18:30
answered May 14 '15 at 4:07
cphlewiscphlewis
8,59723143
8,59723143
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
add a comment |
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
6
6
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
maybe replace use va='center', instead of "i + .25" for the horizontal alignment
– mathause
Sep 26 '17 at 16:40
4
4
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
plt.text(v, i, " "+str(v), color='blue', va='center', fontweight='bold')
– João Cartucho
Apr 18 '18 at 11:41
add a comment |
I have noticed api example code contains an example of barchart with the value of the bar displayed on each bar:
"""
========
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()
output:
FYI What is the unit of height variable in "barh" of matplotlib? (as of now, there is no easy way to set a fixed height for each bar)
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
add a comment |
I have noticed api example code contains an example of barchart with the value of the bar displayed on each bar:
"""
========
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()
output:
FYI What is the unit of height variable in "barh" of matplotlib? (as of now, there is no easy way to set a fixed height for each bar)
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
add a comment |
I have noticed api example code contains an example of barchart with the value of the bar displayed on each bar:
"""
========
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()
output:
FYI What is the unit of height variable in "barh" of matplotlib? (as of now, there is no easy way to set a fixed height for each bar)
I have noticed api example code contains an example of barchart with the value of the bar displayed on each bar:
"""
========
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()
output:
FYI What is the unit of height variable in "barh" of matplotlib? (as of now, there is no easy way to set a fixed height for each bar)
edited May 23 '17 at 12:34
Community♦
11
11
answered Feb 28 '17 at 1:41
Franck DernoncourtFranck Dernoncourt
37.8k32196344
37.8k32196344
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
add a comment |
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
1
1
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
It seems like get_x() rounds the number up even if the original x has decimal places. How do you get more decimal places to display?
– ru111
Jan 10 '18 at 16:16
1
1
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
late to the party but for anyone else using this using height+0.1 instead of 1.05*height in the autolabel function creates a consistent gap between the bar and text
– jnPy
Mar 14 '18 at 10:11
add a comment |
I know it's an old thread, but I landed here several times via Google and think no given answer is really satisfying yet. Try using one of the following functions:
EDIT: As I'm getting some likes on this old thread, I wanna share an updated solution as well (basically putting my two previous functions together and automatically deciding whether it's a bar or hbar plot):
def label_bars(ax, bars, text_format, **kwargs):
"""
Attaches a label on every bar of a regular or horizontal bar chart
"""
ys = [bar.get_y() for bar in bars]
y_is_constant = all(y == ys[0] for y in ys) # -> regular bar chart, since all all bars start on the same y level (0)
if y_is_constant:
_label_bar(ax, bars, text_format, **kwargs)
else:
_label_barh(ax, bars, text_format, **kwargs)
def _label_bar(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
"""
max_y_value = ax.get_ylim()[1]
inside_distance = max_y_value * 0.05
outside_distance = max_y_value * 0.01
for bar in bars:
text = text_format.format(bar.get_height())
text_x = bar.get_x() + bar.get_width() / 2
is_inside = bar.get_height() >= max_y_value * 0.15
if is_inside:
color = "white"
text_y = bar.get_height() - inside_distance
else:
color = "black"
text_y = bar.get_height() + outside_distance
ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)
def _label_barh(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
Note: label always outside. otherwise it's too hard to control as numbers can be very long
"""
max_x_value = ax.get_xlim()[1]
distance = max_x_value * 0.0025
for bar in bars:
text = text_format.format(bar.get_width())
text_x = bar.get_width() + distance
text_y = bar.get_y() + bar.get_height() / 2
ax.text(text_x, text_y, text, va='center', **kwargs)
Now you can use them for regular bar plots:
fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)
or for horizontal bar plots:
fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
add a comment |
I know it's an old thread, but I landed here several times via Google and think no given answer is really satisfying yet. Try using one of the following functions:
EDIT: As I'm getting some likes on this old thread, I wanna share an updated solution as well (basically putting my two previous functions together and automatically deciding whether it's a bar or hbar plot):
def label_bars(ax, bars, text_format, **kwargs):
"""
Attaches a label on every bar of a regular or horizontal bar chart
"""
ys = [bar.get_y() for bar in bars]
y_is_constant = all(y == ys[0] for y in ys) # -> regular bar chart, since all all bars start on the same y level (0)
if y_is_constant:
_label_bar(ax, bars, text_format, **kwargs)
else:
_label_barh(ax, bars, text_format, **kwargs)
def _label_bar(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
"""
max_y_value = ax.get_ylim()[1]
inside_distance = max_y_value * 0.05
outside_distance = max_y_value * 0.01
for bar in bars:
text = text_format.format(bar.get_height())
text_x = bar.get_x() + bar.get_width() / 2
is_inside = bar.get_height() >= max_y_value * 0.15
if is_inside:
color = "white"
text_y = bar.get_height() - inside_distance
else:
color = "black"
text_y = bar.get_height() + outside_distance
ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)
def _label_barh(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
Note: label always outside. otherwise it's too hard to control as numbers can be very long
"""
max_x_value = ax.get_xlim()[1]
distance = max_x_value * 0.0025
for bar in bars:
text = text_format.format(bar.get_width())
text_x = bar.get_width() + distance
text_y = bar.get_y() + bar.get_height() / 2
ax.text(text_x, text_y, text, va='center', **kwargs)
Now you can use them for regular bar plots:
fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)
or for horizontal bar plots:
fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
add a comment |
I know it's an old thread, but I landed here several times via Google and think no given answer is really satisfying yet. Try using one of the following functions:
EDIT: As I'm getting some likes on this old thread, I wanna share an updated solution as well (basically putting my two previous functions together and automatically deciding whether it's a bar or hbar plot):
def label_bars(ax, bars, text_format, **kwargs):
"""
Attaches a label on every bar of a regular or horizontal bar chart
"""
ys = [bar.get_y() for bar in bars]
y_is_constant = all(y == ys[0] for y in ys) # -> regular bar chart, since all all bars start on the same y level (0)
if y_is_constant:
_label_bar(ax, bars, text_format, **kwargs)
else:
_label_barh(ax, bars, text_format, **kwargs)
def _label_bar(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
"""
max_y_value = ax.get_ylim()[1]
inside_distance = max_y_value * 0.05
outside_distance = max_y_value * 0.01
for bar in bars:
text = text_format.format(bar.get_height())
text_x = bar.get_x() + bar.get_width() / 2
is_inside = bar.get_height() >= max_y_value * 0.15
if is_inside:
color = "white"
text_y = bar.get_height() - inside_distance
else:
color = "black"
text_y = bar.get_height() + outside_distance
ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)
def _label_barh(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
Note: label always outside. otherwise it's too hard to control as numbers can be very long
"""
max_x_value = ax.get_xlim()[1]
distance = max_x_value * 0.0025
for bar in bars:
text = text_format.format(bar.get_width())
text_x = bar.get_width() + distance
text_y = bar.get_y() + bar.get_height() / 2
ax.text(text_x, text_y, text, va='center', **kwargs)
Now you can use them for regular bar plots:
fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)
or for horizontal bar plots:
fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
I know it's an old thread, but I landed here several times via Google and think no given answer is really satisfying yet. Try using one of the following functions:
EDIT: As I'm getting some likes on this old thread, I wanna share an updated solution as well (basically putting my two previous functions together and automatically deciding whether it's a bar or hbar plot):
def label_bars(ax, bars, text_format, **kwargs):
"""
Attaches a label on every bar of a regular or horizontal bar chart
"""
ys = [bar.get_y() for bar in bars]
y_is_constant = all(y == ys[0] for y in ys) # -> regular bar chart, since all all bars start on the same y level (0)
if y_is_constant:
_label_bar(ax, bars, text_format, **kwargs)
else:
_label_barh(ax, bars, text_format, **kwargs)
def _label_bar(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
"""
max_y_value = ax.get_ylim()[1]
inside_distance = max_y_value * 0.05
outside_distance = max_y_value * 0.01
for bar in bars:
text = text_format.format(bar.get_height())
text_x = bar.get_x() + bar.get_width() / 2
is_inside = bar.get_height() >= max_y_value * 0.15
if is_inside:
color = "white"
text_y = bar.get_height() - inside_distance
else:
color = "black"
text_y = bar.get_height() + outside_distance
ax.text(text_x, text_y, text, ha='center', va='bottom', color=color, **kwargs)
def _label_barh(ax, bars, text_format, **kwargs):
"""
Attach a text label to each bar displaying its y value
Note: label always outside. otherwise it's too hard to control as numbers can be very long
"""
max_x_value = ax.get_xlim()[1]
distance = max_x_value * 0.0025
for bar in bars:
text = text_format.format(bar.get_width())
text_x = bar.get_width() + distance
text_y = bar.get_y() + bar.get_height() / 2
ax.text(text_x, text_y, text, va='center', **kwargs)
Now you can use them for regular bar plots:
fig, ax = plt.subplots((5, 5))
bars = ax.bar(x_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, bars, value_format)
or for horizontal bar plots:
fig, ax = plt.subplots((5, 5))
horizontal_bars = ax.barh(y_pos, values, width=0.5, align="center")
value_format = "{:.1%}" # displaying values as percentage with one fractional digit
label_bars(ax, horizontal_bars, value_format)
edited Jan 7 at 23:28
answered May 15 '18 at 15:35
SaturnFromTitanSaturnFromTitan
14018
14018
add a comment |
add a comment |
For anyone wanting to have their label at the base of their bars just divide v by the value of the label like this:
for i, v in enumerate(labels):
axes.text(i-.25,
v/labels[i]+100,
labels[i],
fontsize=18,
color=label_color_list[i])
(note: I added 100 so it wasn't absolutely at the bottom)
To get a result like this:
add a comment |
For anyone wanting to have their label at the base of their bars just divide v by the value of the label like this:
for i, v in enumerate(labels):
axes.text(i-.25,
v/labels[i]+100,
labels[i],
fontsize=18,
color=label_color_list[i])
(note: I added 100 so it wasn't absolutely at the bottom)
To get a result like this:
add a comment |
For anyone wanting to have their label at the base of their bars just divide v by the value of the label like this:
for i, v in enumerate(labels):
axes.text(i-.25,
v/labels[i]+100,
labels[i],
fontsize=18,
color=label_color_list[i])
(note: I added 100 so it wasn't absolutely at the bottom)
To get a result like this:
For anyone wanting to have their label at the base of their bars just divide v by the value of the label like this:
for i, v in enumerate(labels):
axes.text(i-.25,
v/labels[i]+100,
labels[i],
fontsize=18,
color=label_color_list[i])
(note: I added 100 so it wasn't absolutely at the bottom)
To get a result like this:
answered Nov 23 '18 at 20:48
SkromakSkromak
9317
9317
add a comment |
add a comment |
For pandas people :
ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
That's it.
Alternatively, for those who prefer apply
over looping with enumerate:
it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));
Also, ax.patches
will give you the bars that you would get with ax.bar(...)
. In case you want to apply the functions of @SaturnFromTitan or techniques of others.
add a comment |
For pandas people :
ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
That's it.
Alternatively, for those who prefer apply
over looping with enumerate:
it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));
Also, ax.patches
will give you the bars that you would get with ax.bar(...)
. In case you want to apply the functions of @SaturnFromTitan or techniques of others.
add a comment |
For pandas people :
ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
That's it.
Alternatively, for those who prefer apply
over looping with enumerate:
it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));
Also, ax.patches
will give you the bars that you would get with ax.bar(...)
. In case you want to apply the functions of @SaturnFromTitan or techniques of others.
For pandas people :
ax = s.plot(kind='barh') # s is a Series (float) in [0,1]
[ax.text(v, i, '{:.2f}%'.format(100*v)) for i, v in enumerate(s)];
That's it.
Alternatively, for those who prefer apply
over looping with enumerate:
it = iter(range(len(s)))
s.apply(lambda x: ax.text(x, next(it),'{:.2f}%'.format(100*x)));
Also, ax.patches
will give you the bars that you would get with ax.bar(...)
. In case you want to apply the functions of @SaturnFromTitan or techniques of others.
answered Nov 14 '18 at 19:54
tozCSStozCSS
1,1681018
1,1681018
add a comment |
add a comment |
I needed the bar labels too, note that my y-axis is having a zoomed view using limits on y axis. The default calculations for putting the labels on top of the bar still works using height (use_global_coordinate=False in the example). But I wanted to show that the labels can be put in the bottom of the graph too in zoomed view using global coordinates in matplotlib 3.0.2. Hope it help someone.
def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True
if use_global_coordinate:
for i in data:
ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
verticalalignment='center', transform=ax.transAxes,fontsize=8)
c=c+1
else:
for rect,i in zip(rects,data):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')
add a comment |
I needed the bar labels too, note that my y-axis is having a zoomed view using limits on y axis. The default calculations for putting the labels on top of the bar still works using height (use_global_coordinate=False in the example). But I wanted to show that the labels can be put in the bottom of the graph too in zoomed view using global coordinates in matplotlib 3.0.2. Hope it help someone.
def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True
if use_global_coordinate:
for i in data:
ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
verticalalignment='center', transform=ax.transAxes,fontsize=8)
c=c+1
else:
for rect,i in zip(rects,data):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')
add a comment |
I needed the bar labels too, note that my y-axis is having a zoomed view using limits on y axis. The default calculations for putting the labels on top of the bar still works using height (use_global_coordinate=False in the example). But I wanted to show that the labels can be put in the bottom of the graph too in zoomed view using global coordinates in matplotlib 3.0.2. Hope it help someone.
def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True
if use_global_coordinate:
for i in data:
ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
verticalalignment='center', transform=ax.transAxes,fontsize=8)
c=c+1
else:
for rect,i in zip(rects,data):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')
I needed the bar labels too, note that my y-axis is having a zoomed view using limits on y axis. The default calculations for putting the labels on top of the bar still works using height (use_global_coordinate=False in the example). But I wanted to show that the labels can be put in the bottom of the graph too in zoomed view using global coordinates in matplotlib 3.0.2. Hope it help someone.
def autolabel(rects,data):
"""
Attach a text label above each bar displaying its height
"""
c = 0
initial = 0.091
offset = 0.205
use_global_coordinate = True
if use_global_coordinate:
for i in data:
ax.text(initial+offset*c, 0.05, str(i), horizontalalignment='center',
verticalalignment='center', transform=ax.transAxes,fontsize=8)
c=c+1
else:
for rect,i in zip(rects,data):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., height,str(i),ha='center', va='bottom')
answered Nov 27 '18 at 12:35
HaramozHaramoz
413317
413317
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f30228069%2fhow-to-display-the-value-of-the-bar-on-each-bar-with-pyplot-barh%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown