MAS
MAS

Reputation: 4993

title and axis gets over each other

I am trying to plot several plots. I want to add to each a title. However, in my code the title and the axis gets over each other. Is there a workaround this?

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

randn = np.random.randn

fig = plt.figure(figsize=(15, 12))
train= df = pd.DataFrame(randn(10, 34))
for i in range(1, train.shape[1]):
    plt.subplot(6, 6, i)
    f = plt.gca()
    f.axes.get_yaxis().set_visible(False)
    f.set_title(train.columns.values[i])

    vals = np.size(train.iloc[:, i].unique())
    if vals < 10:
        bins = vals
    else:
        vals = 10
    plt.hist(train.iloc[:, i], bins=30, color='#3F5D7D')
plt.show()

Upvotes: 2

Views: 83

Answers (3)

Jean-S&#233;bastien
Jean-S&#233;bastien

Reputation: 2697

An alternative solution would be to place your subplots manually in your figure to allow a maximum of flexibility in your layout design. I've put together some code that shows how this can be done. Note that there is a big part of the code that is only to make the xticks format visually appealing.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.close('all')

#------------------------------------------------------------- prepare data ----

randn = np.random.randn
train= df = pd.DataFrame(randn(10, 34))
ngraphs = train.shape[1]

#------------------------------------------------------------ create figure ----

fwidth = 15
fheight = 12

fig = plt.figure(figsize=(fwidth, fheight))
fig.patch.set_facecolor('white')

left_margin  = 0.5 / fwidth
right_margin = 0.5 / fwidth
bottom_margin = 0.5 / fheight
top_margin = 0.75 / fheight

vinter_margin = 0.75 / fheight
hinter_margin = 0.5 / fwidth

#-------------------------------------------------------------- create axes ----

ncol = 6
nrow = int(np.ceil(ngraphs/float(ncol)))

w0 = (1 - (left_margin + right_margin + (ncol-1) * hinter_margin)) / ncol
h0 = (1 - (bottom_margin + top_margin + (nrow-1) * vinter_margin)) / nrow

AX0 = [0] * ngraphs
itot = 0
y0 = 1 - top_margin - h0
for row in range(nrow):

    x0 = left_margin

    for col in range(ncol):

        AX0[itot] = fig.add_axes([x0, y0, w0, h0], frameon=True)

        #-------------------------------------------------------- plot data ----

        vals = np.size(train.iloc[:, itot].unique())
        if vals < 10:
            bins = vals
        else:
            vals = 10

        AX0[itot].hist(train.iloc[:, itot], bins=30, color='#3F5D7D')

        #--------------------------------------------------------- set axis ----

        AX0[itot].axes.get_yaxis().set_visible(False)
        AX0[itot].set_title(train.columns.values[itot])

        #---- major ticks ----

        AX0[itot].tick_params(top='off', labeltop='off')
        AX0[itot].tick_params(axis='x', direction='out', labelsize=8) 

        trainmax = np.ceil(np.max(train.iloc[:, itot])/0.5)*0.5
        trainmin = np.floor(np.min(train.iloc[:, itot])/0.5)*0.5

        AX0[itot].set_xticks([trainmin,0, trainmax])

        #---- minor ticks ----

        AX0[itot].set_xticks(np.arange(trainmin, trainmax, 0.5), minor=True)
        AX0[itot].tick_params(axis='x', which='minor', direction='out',
                              top='off', length=3)

        #---- axis limits ----

        AX0[itot].axis(xmin=trainmin, xmax=trainmax)               

        #---------------------------------------------------------- iterate ----

        x0 = x0 + w0 + hinter_margin                                   
        itot += 1

        if itot == ngraphs:
            break

    y0 = y0 - h0 - vinter_margin

plt.show(block=False)

fig.savefig('subplot_layout.png')

Which results in:

enter image description here

Upvotes: 2

hilms
hilms

Reputation: 53

The solution is:

plt.tight_layout()

Here is some good documentation, it has an example that looks like your problem.

http://matplotlib.org/users/tight_layout_guide.html

Upvotes: 2

Diziet Asahi
Diziet Asahi

Reputation: 40667

you could try:

plt.tight_layout()

Upvotes: 3

Related Questions