gaborous
gaborous

Reputation: 16620

Inconsistent figsize resizing in matplotlib

I have several different barplot figures to generate with a varying amount of bars. The total width and height of the figure thus varies, but I would like the bars to be consistently sized the same for all barplots.

What I tried so far is to resize the figsize proportionally to the number of bars. This does not seem to work consistently.

Here is a sample code:

nb_bars_list = [2, 10]

for i, nb_bars in enumerate(nb_bars_list):
    # Resize proportionally to the number of bars
    figsize = [1+nb_bars, 5]
    # Prepare the ticks
    ticks = np.arange(1, 1+nb_bars, 1)
    # Generate random points
    points = [np.random.randn(10) for x in xrange(nb_bars)]
    # Make the plot
    fig, ax = plt.subplots()
    if figsize:
        fig.set_size_inches(figsize[0], figsize[1], forward=True)
    for b in xrange(nb_bars):
        ax.bar(ticks[b], points[b].mean())
    fig.savefig('test%i' % i, bbox_inches='tight')

Which results in: 2-bars 10-bars

If we overlap both using GIMP, we can clearly notice the difference in bar widths:

both-bars

How can I ensure the same width for the bars, whatever the number of bars?

I am using matplotlib 2.

Upvotes: 4

Views: 932

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339660

To set the figure size such that different numbers of bars in a figure always have the same width would require to take the figure margins into account. Also one would need to set the xlimits of the plot equally in all cases.

import matplotlib.pyplot as plt
import numpy as np

nb_bars_list = [2, 10]
margleft = 0.8 # inch
margright= 0.64 # inch
barwidth = 0.5 # inch


for i, nb_bars in enumerate(nb_bars_list):
    # Resize proportionally to the number of bars
    axwidth = nb_bars*barwidth # inch
    figsize = [margleft+axwidth+margright, 5]
    # Prepare the ticks
    ticks = np.arange(1, 1+nb_bars, 1)
    # Generate random points
    points = [np.random.randn(10) for x in xrange(nb_bars)]
    # Make the plot
    fig, ax = plt.subplots(figsize=figsize)
    fig.subplots_adjust(left=margleft/figsize[0], right=1-margright/figsize[0])

    for b in xrange(nb_bars):
        ax.bar(ticks[b], points[b].mean())
    ax.set_xlim(ticks[0]-0.5,ticks[-1]+0.5)
    #fig.savefig('test%i' % i, bbox_inches='tight')
plt.show()

enter image description here

Upvotes: 6

Related Questions