How to avoid overlapping bars in plt.bar when x-values aren't spaced evenly?

Viewed 101

I have

x = array([0., 0.08, 0.12, 0.18, 0.27, 0.42, 0.65])

y = array([0., 0.03758546, 0.06577713, 0.48786205, 0.28553257, 0.09909356, 0.02414922])

I then write

plt.ticklabel_format(useOffset=False)
plt.figure(figsize=(20,10))
plt.xlabel('D/Dmax')

plt.bar(x, y), align = 'edge', tick_label = x, color = 'red', edgecolor = "black")

And I get the following chart. Why is it like this, and how can I make the bars not overlap and distinct like every other bar chart?

enter image description here

2 Answers

Your real x-values are much smaller than the default bar width which makes the bars overlap. You need to use a smaller bar width, for ex. 0.02 which is of the order of your smaller x-value.

plt.bar(x, y, align='edge', tick_label=x, color='red', edgecolor="black", 
        width=0.02)

enter image description here

As your bars don't have a constant width, you can calculate these widths as the difference between the x-values: np.diff(x). Note that there is one less difference than there are elements in x. To get a width for the last bar (which in theory could be infinite), you can either repeat the next-to-last width, or add an extra x-value to set the rightmost boundary.

from matplotlib import pyplot as plt
import numpy as np

x = np.array([0., 0.08, 0.12, 0.18, 0.27, 0.42, 0.65])
y = np.array([0., 0.03758546, 0.06577713, 0.48786205, 0.28553257, 0.09909356, 0.02414922])
widths = np.pad(np.diff(x), (0, 1), 'edge')

plt.figure(figsize=(20, 10))
plt.xlabel('D/Dmax')

plt.bar(x, y, width=widths, align='edge', tick_label=x, color='red', edgecolor="black")
plt.show()

resulting plot

In this case, a logical extension for x could be to include 1:

from matplotlib import pyplot as plt
import numpy as np

x = np.array([0., 0.08, 0.12, 0.18, 0.27, 0.42, 0.65])
x = np.concatenate([x, [1]])
y = np.array([0., 0.03758546, 0.06577713, 0.48786205, 0.28553257, 0.09909356, 0.02414922])
widths = np.diff(x)

plt.figure(figsize=(20, 10))
plt.xlabel('D/Dmax')

plt.bar(x[:-1], y, width=widths, align='edge', color='red', edgecolor="black")
plt.xticks(x)
plt.show()

example plot including x=1

Related