0

I have the following code:

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('ggplot')

def autolabel(rects):
    """Attach a text label above each bar in *rects*, displaying its height."""
    for rect in rects:
        height = int(rect.get_height())
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom', fontsize=6)

data = [108, 140.9, 187, 237.6, 299.2, 360.9, 413.3, 431.9, 437.2, 441.9]
set1 = [140.973, 161.588, 202.391, 213.57, 408.55, 442.648, 491.883, 517.456, 534.018, 545.594]
set2 = [140.386, 156.932, 200.106, 213.789, 401.426, 440.09, 490.252, 516.478, 533.255, 545.232]
set3 = [141.046, 162.663, 202.05, 213.613, 408.678, 442.685, 491.894, 517.552, 534.028, 545.858]
stage = [1,2,3,4,5,6,7,8,9,10]

x = np.arange(len(stage))  # the label locations
y = [50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600]
width = 0.20  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - 3*width/2, data, width, color = "tab:gray", label='Data')
rects2 = ax.bar(x - width/2, set1, width, color = "tab:red", label='Set 1')
rects3 = ax.bar(x + width/2, set2, width, color = "tab:blue", label='Set 2')
rects4 = ax.bar(x + 3*width/2, set3, width, color = "tab:purple", label='Set 3')

ax.set_yticks(y)
ax.set_yticklabels(y, fontsize=10)
ax.set_ylim(0,580)
ax.set_xticks(x)
ax.set_xticklabels(stage, fontsize=10)
ax.legend(fontsize=8)
ax.grid(True)

autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
autolabel(rects4)

fig.savefig("plot.png", dpi=300)

which gives me the following bar plot:

Bar Plot

Can anyone help me to plot this with readable text on top of all the bars? I tried increasing the width for more text visibility but then the bars at second point on the x-axis and so on are overlapped with previous bars.

c0r3
  • 15
  • 6
  • Would you be open to rotating the labels by 90 degrees? Also see [`bar_label`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar_label.html) – tomjn Feb 14 '22 at 14:46
  • Yes, I would be open to that. How do you suggest doing that? – c0r3 Feb 14 '22 at 15:04

1 Answers1

2

matplotlib now has a method for adding labels to bars, bar_label. You can replace your custom function with that and add your options there. To make your labels fit, without reducing the size of the text further, you can rotate by 90 degrees e.g.

ax.bar_label(rects1, fmt="%d", fontsize=6, rotation=90, padding=3)
tomjn
  • 5,100
  • 1
  • 9
  • 24