How to reduce the space between the axes and the first and last bar in pyplot?

Viewed 1750

There is a big space between the border/x-axe of the graph and the first and last bar in a bar plot in pyplot (red arrows in the first picture). In the image below, it looks fine in the graph on the left, but it's wasting a lot of space in the graph on the right. The larger the graph, the larger the space. enter image description here See how much space is wasted in the second picture: enter image description here Any idea how to fix that?

The code:

plt.figure(figsize=figsize)
grid = plt.GridSpec(figsize[1], figsize[0], wspace=120/figsize[0])
plt.suptitle(feature.upper())

# NaN plot
plt.subplot(grid[:, :2])
plt.title('Présence')
plt.ylabel('occurences')
plt.bar([0, 1], [df.shape[0] - nan, nan], color=['#4caf50', '#f44336'])
plt.xticks([0, 1], ['Renseigné', 'Absent'], rotation='vertical')

# Distrib plot
plt.subplot(grid[:, 2:])
plt.title('Distribution')
x_pos = [i for i, _ in enumerate(sizes)]
plt.bar(x_pos, sizes)
plt.xticks(x_pos, labels, rotation='vertical')
plt.show()

df is my pandas DataFrame, nan the amount of null value for the feature I'm plotting, sizes is the number of occurrences for each value, and labels are the corresponding label's value.

1 Answers

You can use plt.margins(x=0, tight=True).

The default margins are 0.05 which means that 5% of the distance between the first and last x-values is used as a margin. Choosing a small value such as plt.margins(x=0-01, tight=True) would leave a bit of margin, so the bars don't look glued to the axes.

In some situations wider margins are desired. For example when drawing only two very narrow bars. So, the exact value for a plot to look nice depends on multiple factors as well as on personal preferences.

Note that plt.margins is best called after the last function that adds elements to the plot.

Also note that plt.xlim has a similar function of changing the drawing limits. Here is an example that sets xlim to have the same distance between the axes and the bars as between the bars themselves.

import matplotlib.pyplot as plt

fig, axes = plt.subplots(ncols=3, figsize=(12, 3))
for ax in axes:
    width = 0.4
    ax.bar([0, 1, 2], [2, 3, 5], width=width, color='turquoise')
    if ax == axes[0]:
        ax.margins(x=0.01)
        ax.set_title('1% margins')
    elif ax == axes[1]:
        ax.margins(x=0.1)
        ax.set_title('10% margins')
    else:
        ax.set_xlim(-1+width/2, 3-width/2)
        ax.set_title('setting xlim')
plt.show()

example plot

Related