bryan.blackbee
bryan.blackbee

Reputation: 1954

fig.tight_layout() but plots still overlap

Imagine I have some dataset for wines and I find the top 5 wine producing countries:

# Find top 5 wine producing countries.
top_countries = wines_df.groupby('country').size().reset_index(name='n').sort_values('n', ascending=False)[:5]['country'].tolist()

Now that I have the values, I attempt to plot the results in 10 plots, 5 rows 2 columns.

fig = plt.figure(figsize=(16, 15))
fig.tight_layout()
i = 0
for c in top_countries:
    c_df = wines_df[wines_df.country == c]
    i +=1
    ax1 = fig.add_subplot(5,2,i)
    i +=1
    ax2 = fig.add_subplot(5,2,i)
    sns.kdeplot(c_df['points'], ax=ax1)
    ax1.set_title("POINTS OF ALL WINES IN %s, n=%d" % (c.upper(), c_df.shape[0]), fontsize=16)
    sns.boxplot(c_df['price'], ax=ax2)
    ax2.set_title("PRICE OF ALL WINES IN %s, n=%d" % (c.upper(), c_df.shape[0]), fontsize=16)
plt.show()

Even with this result, I still have my subplots overlapping.

enter image description here

Am I doing something wrong? Using python3.6 with matplotlib==2.2.2

Upvotes: 3

Views: 1475

Answers (1)

JE_Muc
JE_Muc

Reputation: 5774

As Thomas Kühn said, you have to move tight_layout() after doing the plots, like in:

fig = plt.figure(figsize=(16, 15))
i = 0
for c in top_countries:
    c_df = wines_df[wines_df.country == c]
    i +=1
    ax1 = fig.add_subplot(5,2,i)
    i +=1
    ax2 = fig.add_subplot(5,2,i)
    sns.kdeplot(c_df['points'], ax=ax1)
    ax1.set_title("POINTS OF ALL WINES IN %s, n=%d" % (c.upper(), c_df.shape[0]), fontsize=16)
    sns.boxplot(c_df['price'], ax=ax2)
    ax2.set_title("PRICE OF ALL WINES IN %s, n=%d" % (c.upper(), c_df.shape[0]), fontsize=16)
fig.tight_layout()
plt.show()

If it is still overlapping (this may happen in some seldom cases), you can specify the padding with:

fig.tight_layout(pad=0., w_pad=0.3, h_pad=1.0)

Where pad is the general padding, w_pad is the horizontal padding and h_pad is the vertical padding. Just try some values until your plot looks nicely. (pad=0., w_pad=.3, h_pad=.3) is a good start, if you want to have your plots as tight as possible.

Another possibility is to specify constrained_layout=True in the figure:

fig = plt.figure(figsize=(16, 15), constrained_layout=True)

Now you can delete the line fig.tight_layout().


edit:
One more thing I stumbled upon:
It seems like you are specifying your figsize so that it fits on a standard DIN A4 paper in centimeters (typical textwidth: 16cm). But figsize in matplotlib is in inches. So probably replacing the figsize with figsize=(16/2.54, 15/2.54) might be better.

I know that it is absolutely confusing that matplotlib internally uses inches as units, considering that it is mostly the scientific community and data engineers working with matplotlib (and these usually use SI units). As ImportanceOfBeingErnest pointed out, there are several discussions going on about how to implement other units than inches.

Upvotes: 3

Related Questions