'imshow subplot placement inside matplotlib figure

I have a Python script that draws a matrix of images, each image is read from disk and is 100x100 pixels. Current result is:

matrix of images

I don't know why Python adds vertical spacing between each row. I tried setting several parameters for plt.subplots. Rendering code is below:

fig, axs = plt.subplots(
    gridRows, gridCols, sharex=True, sharey=False, constrained_layout={'w_pad': 0, 'h_pad': 0, 'wspace': 0, 'hspace': 0}, figsize=(9,9)
)
k = 0

for i in range(len(axs)):
    for j in range(len(axs[i])):
        if (k < paramsCount and dataset.iat[k,2]):
            img = mpimg.imread(<some_folder_path>)
        else:
            img = mpimg.imread(<some_folder_path>)
            
        ax = axs[i, j]    
        ax.imshow(img)
        ax.axis('off')
        if (i == 0): ax.set_title(dataset.iat[k,1])
        if (j == 0): ax.text(-0.2, 0.5, dataset.iat[k,0], transform=ax.transAxes, verticalalignment='center', rotation='vertical', size=12)
        
        axi = ax.axis()
        rec = plt.Rectangle((axi[0], axi[2]), axi[1] - axi[0], axi[3] - axi[2], fill=False, lw=1, linestyle="dotted")
        rec = ax.add_patch(rec)
        rec.set_clip_on(False)

        k = k + 1

plt.show()

Desired result is like:

desired result

Does anyone have ideas?



Solution 1:[1]

I'm sure there are many ways to do this other than the tashi answer, but the grid and subplot keywords are used in the subplot to remove the spacing and scale. In the loop process for each subplot, I set the graph spacing, remove the tick labels, and adjust the spacing by making the border dashed and the color gray. The title and y-axis labels are also added based on the loop counter value. Since the data was not provided, some of the data is written directly, so please replace it with your own data.

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(20220510)
grid = np.random.rand(4, 4)
gridRows, gridCols = 5, 10
titles = np.arange(5,51,5)
ylabels = [500,400,300,200,100]
fig, axs = plt.subplots(gridRows, gridCols,
                        figsize=(8,4), 
                        gridspec_kw={'wspace':0, 'hspace':0},
                       subplot_kw={'xticks': [], 'yticks': []}
                       )

for i, ax in enumerate(axs.flat):
    ax.imshow(grid, interpolation='lanczos', cmap='viridis', aspect='auto')
    ax.margins(0, 0)
    if i < 10:
        ax.set_title(str(titles[i]))
    if i in [0,10,20,30,40]:
        ax.set_ylabel(ylabels[int(i/10)])
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    for s in ['bottom','top','left','right']:
        ax.spines[s].set_linestyle('dashed')
        ax.spines[s].set_capstyle("butt")
    for spine in ax.spines.values():
        spine.set_edgecolor('gray')

plt.show()

enter image description here

Solution 2:[2]

I realized it has to do with the dimensions passed to figsize. Since rows count is half the columns count, I need to pass figsize(width, width/2).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 r-beginners
Solution 2 agrock