<jupyter_start><jupyter_text>PurposeWhen plotting subplots in Matplotlib, sometimes, the last subplot should be turned off. For example, imagine you have 5 subplots and you create a 3 rows by 2 columns subplots. The first five subplots should show, but the last one should not. This notebook synthesizes 5 variables for which we want to plot the corresponding univariate distributions onto a 3 x 2 subplots. Since the last subplots is not needed to be displayed, we turn it off.<jupyter_code>%matplotlib inline
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import math

np.random.seed(37)

# simulate data
N = 10000

X = np.concatenate([
    np.random.normal(0, 1.0, N).reshape(-1, 1), 
    np.random.normal(1, 1.5, N).reshape(-1, 1), 
    np.random.normal(2, 2.5, N).reshape(-1, 1), 
    np.random.normal(3, 3.5, N).reshape(-1, 1),
    np.random.normal(4, 4.5, N).reshape(-1, 1)], axis=1)

n_cols = 2
n_rows = math.ceil(X.shape[1] / n_cols)
is_even = True if X.shape[1] / n_cols == 0 else False

# plot data
fig, ax = plt.subplots(n_rows, n_cols, figsize=(15, 10))
ax = np.ravel(ax)

for i, a in zip(range(X.shape[1]), ax):
    label = 'x_{}'.format(i)
    x = X[:, i]
    
    sns.distplot(x, ax=a)
    mu = np.mean(x)
    std = np.std(x)
    
    a.set_title(r'${}$, mean={:.2f}, std={:.2f}'.format(label, mu, std))
    a.set_xlabel(r'${}$'.format(label))
    a.set_ylabel(r'$p({})$'.format(label))

if is_even is False:
    ax[-1].axis('off')
    
plt.tight_layout()<jupyter_output><empty_output><jupyter_text>In this next example, we only plot the first four columns (or variables). However, we want to display 3 plots per row, and this requirement means that we will need 2 rows (first row with 3 plots, second row with 1 plot). We will use `plt.figure` to control the size of the overall graphics, and `fig.add_subplot` to add each plot at a time. We know that there are 6 plots (2 rows by 3 columns) but we only need to display 4 distributions. As such, we turn off the plot through `ax.axis('off')` for the 5th and 6th plots.<jupyter_code>N = 10000

Y = X[:,[0, 1, 2, 3]]

n_cols = 3
n_rows = 2
n_plots = n_cols * n_rows

fig = plt.figure(figsize=(15, 10))

for i in range(n_plots):
    ax = fig.add_subplot(n_rows, n_cols, i + 1)
    
    if i < Y.shape[1]:
        label = 'x_{}'.format(i)
        x = Y[:, i]

        sns.distplot(x, ax=ax)
        mu = np.mean(x)
        std = np.std(x)

        ax.set_title(r'${}$, mean={:.2f}, std={:.2f}'.format(label, mu, std))
        ax.set_xlabel(r'${}$'.format(label))
        ax.set_ylabel(r'$p({})$'.format(label))
    else:
        ax.axis('off')
        
plt.tight_layout()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14684014869888476, 'fraction_numerical': 0.02973977695167286, 'mean_word_length': 3.3685064935064934, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '77475', 'license': 'Apache-2.0', 'n_tokens_mistral': 1071, 'n_tokens_neox': 990, 'n_words': 319, 'path': 'recipe/subplots-off-by-one.ipynb', 'repo_name': 'oneoffcoder/jupyter', 'size': '2690'}