Set bar space using matplotlib

Asked

Viewed 912 times

2

Good afternoon. I’m filling a bar chart but I can’t adjust the spacing between the 3 different bars of the same.

# plota os resultados
diameters = ['<=102', '103-152', '153-203', '203-254', '255-305', '306-356', '357-406', '407-457', 
'458-508', '509-610', '611-711', '>711']

width = 0.3
x = np.arange(len(diameters))

fig, ax = plt.subplots(figsize=(12,12))
rects1 = ax.bar(x - width/1.5, count_kmeans, width=width, label='K-means', align='center')
rects2 = ax.bar(x, count_kmedoids, width=width, label='K-medoids', align='center')
rects3 = ax.bar(x + width/1.5, count_hierarquico, width=width, label='Hierarquico', align='center')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Quantidade')
ax.set_title('Comparativo de diâmetros entre algoritmos')
ax.set_xticks(x)
ax.set_xticklabels(diameters)
ax.set_xlabel('Diâmetro nominal (mm)')
ax.legend()


def autolabel(rects):
   """Attach a text label above each bar in *rects*, displaying its height."""
  for rect in rects:
      height = 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')


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

fig.tight_layout()

plt.show()

Follows the chart

inserir a descrição da imagem aqui

1 answer

1

This happens because the method ax.bar is crowding bars into X-axis positions that are smaller than the width (variable width) of each bar. For example, the first points of the series you plot when calling ax.bar sane:

ax.bar(x - width/1.5, ...)  -> -0.2
ax.bar(x, ...)              ->  0.0
ax.bar(x + width/1.5, ...)  ->  0.2

That is, they have a distance on the X axis of 0.2 but a bar width of 0.3, which means there will be overlapping bars.

I suggest reducing the width and simply add/subtract this value of each series to be plotted, without dividing it by 1.5. For example, modifying the code to:

width = 0.2

and the plotting lines for:

rects1 = ax.bar(x - width, ... )
rects2 = ax.bar(x,... )
rects3 = ax.bar(x + width, ... )

the bars of the same group are "glued" to each other, and spaced in relation to the other groups (note that I used any other data because you did not provide the series of values y in your post):

inserir a descrição da imagem aqui

  • How would it be if it were dynamic? Without knowing the amount in advance?

  • 1

    @Vinithius is not something very intuitive (at least using the matplotlib). You’ll probably have to measure an optimal width for the bars by dividing the range of [0.1] between the number of categories you have, and also consider a margin so the bars don’t stick together between neighboring groups on the X axis. Something like: margin = 0.2; width = (1 - margin)/num_categorias. And then call the ax.bar with increments of width added to the values of X, for example ax.bar(x + 0 * width, ...), ax.bar(x + 1 * width, ...), ax.bar(x + 2 * width, ...), ....

Browser other questions tagged

You are not signed in. Login or sign up in order to post.