0

I am trying to print about 42 plots in 7 rows, 6 columns, but the printed output in jupyter notebook, shows all the plots one under the other. I want them in (7,6) format for comparison. I am using matplotlib.subplot2grid() function.

Note: I do not get any error, and my code works, however the plots are one under the other, vs being in a grid/ matrix form. Here is my code:

def draw_umap(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean', title=''):
fit = umap.UMAP(
    n_neighbors=n_neighbors,
    min_dist=min_dist,
    n_components=n_components,
    metric=metric
)
u = fit.fit_transform(df);
plots = []
plt.figure(0)
fig = plt.figure()
fig.set_figheight(10)
fig.set_figwidth(10)
for i in range(7):
    for j in range(6):
        plt.subplot2grid((7,6), (i,j), rowspan=7, colspan=6)
        
    plt.scatter(u[:,0], u[:,1], c= df.iloc[:,0])
        
    plt.title(title, fontsize=8)

n=range(7)
d=range(6)

for n in n_neighbors:
    for d in dist:
        draw_umap(n_neighbors=n, min_dist=d, title="n_neighbors={}".format(n) + " min_dist={}".format(d))

I did refer to this post to get the plots in a grid and followed the code. I also referred to this post, and modified my code for size of the fig.

Is there a better way to do this using Seaborn?

What am I missing here? Please help!

  • Would you mind checking if the indent in the code you have given is correct? To me, it is not entirely clear where the `draw_umap` function ends and whether `plt.scatter` and `plt.title` should be in the `for j in range(6)` loop or not. Also, I notice that `n=range(7); d=range(6)` are superfluous as they are overwritten in the following loops. – Patrick FitzGerald Jan 22 '21 at 20:52
  • The indent was right. I think, it is just an issue in jupyter notebook. I will double check the range values. Thank you! – learning_to_code Jan 25 '21 at 04:02

1 Answers1

0

Both questions that you have linked contain solutions that seem more complicated than necessary. Note that subplot2grid is useful only if you want to create subplots of varying sizes which I understand is not your case. Also note that according to the docs Using GridSpec, as demonstrated in GridSpec demo is generally preferred, and I would also recommend this function only if you want to create subplots of varying sizes.

The simple way to create a grid of equal-sized subplots is to use plt.subplots which returns an array of Axes through which you can loop to plot your data as shown in this answer. That solution should work fine in your case seeing as you are plotting 42 plots in a grid of 7 by 6. But the problem is that in many cases you may find yourself not needing all the Axes of the grid, so you will end up with some empty frames in your figure.

Therefore, I suggest using a more general solution that works in any situation by first creating an empty figure and then adding each Axes with fig.add_subplot as shown in the following example:

import numpy as np               # v 1.19.2
import matplotlib.pyplot as plt  # v 3.3.4

# Create sample dataset
rng = np.random.default_rng(seed=1)  # random number generator
nvars = 8
nobs = 50
xs = rng.uniform(size=(nvars, nobs))
ys = rng.normal(size=(nvars, nobs))

# Create figure with appropriate space between subplots
fig = plt.figure(figsize=(10, 8))
fig.subplots_adjust(hspace=0.4, wspace=0.3)

# Plot data by looping through arrays of variables and list of colors
colors = plt.get_cmap('tab10').colors
for idx, x, y, color in zip(range(len(xs)), xs, ys, colors):
    ax = fig.add_subplot(3, 3, idx+1)
    ax.scatter(x, y, color=color)

subplots_grid

This could be done in seaborn as well, but I would need to see what your dataset looks like to provide a solution relevant to your case.



You can find a more elaborate example of this approach in the second solution in this answer.

Patrick FitzGerald
  • 3,280
  • 2
  • 18
  • 30