When drawing a bar plot in matplotlib
using bars = plt.bar(...)
, the returned object can be passed to plt.bar_label(bars, labels)
for easy labelling.
plt.bar_label(bars, labels)
labels all of the bars. I want to only label a subset (the first three), ideally using plt.bar_label()
. I don't want to invoke
plt.text()
or plt.annotate()
.
Is there a way of slicing out the bars I want from bars
, and only having those labelled using plt.bar_label()
?
Example below shows the default behaviour where all bars get labelled.
#Imports
import matplotlib.pyplot as plt
import pandas as pd
# Data for testing
values = [10, 9, 10.5, 4, 3.1, 2]
labels = [
'sensor calibration', 'sensor response', 'noise floor estimate',
'noise floor theta', 'weighted response coef', 'linear estimate'
]
#Bar plot with labels
ax = plt.figure(figsize=(5, 2)).add_subplot()
bars = ax.bar(range(6), values, color='lightgray')
ax.set(xlabel='x', ylabel='value', title='Data')
ax.spines[['top', 'right']].set_visible(False)
#Add all bar labels
label_kwargs = dict(rotation=90, weight='bold', fontsize=8, label_type='center')
ax.bar_label(bars, labels, **label_kwargs)
An easy option would be to provide empty labels for the bars that shouldn't be labeled:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Data for testing
values = [10, 9, 10.5, 4, 3.1, 2]
labels = [
'sensor calibration', 'sensor response', 'noise floor estimate',
'noise floor theta', 'weighted response coef', 'linear estimate'
]
# Bar plot with labels
fig, ax = plt.subplots(figsize=(5, 3))
bars = ax.bar(range(6), values, color='lightgray')
ax.set(xlabel='x', ylabel='value', title='Data')
ax.spines[['top', 'right']].set_visible(False)
# Add centered bar labels
k = 3
label_kwargs = dict(rotation=90, weight='bold', fontsize=8, label_type='center')
ax.bar_label(bars, labels[:k] + [''] * (len(bars) - k), **label_kwargs)
plt.show()
Here is a variant that places centered labels for the long bars, and top labels for the shorter bars:
# Bar plot with labels
fig, ax = plt.subplots(figsize=(5, 3))
bars = ax.bar(range(6), values, color='lightgray')
ax.set(xlabel='x', ylabel='value', title='Data')
ax.spines[['top', 'right']].set_visible(False)
cutoff = 5 # bars higher will get centered labels, lower bars get labels on top
# Add the centered bar labels
label_kwargs = dict(rotation=90, weight='bold', fontsize=8, label_type='center')
ax.bar_label(bars, ['' if val <= cutoff else lbl for val, lbl in zip(values, labels)], **label_kwargs)
# Add bar labels at the top of the other bars
label_kwargs['label_type'] = 'edge'
label_kwargs['padding'] = 2
ax.bar_label(bars, ['' if val > cutoff else lbl for val, lbl in zip(values, labels)], **label_kwargs)
plt.show()