Keywords: Matplotlib | Multi-image Display | Subplot Layout
Abstract: This article provides a detailed explanation of how to display multiple images in a single figure using Python's Matplotlib library. By analyzing common error cases, it thoroughly explains the parameter meanings and usage techniques of the add_subplot and plt.subplots methods. The article offers complete solutions from basic to advanced levels, including grid layout configuration, subplot index calculation, axis sharing settings, and custom tick label functionalities. Through step-by-step code examples and in-depth technical analysis, it helps readers master the core concepts and best practices of multi-image display.
Introduction
In data visualization and image processing applications, there is often a need to display multiple images simultaneously in a single figure for comparative analysis. Matplotlib, as the most popular plotting library in Python, provides powerful subplot functionality to meet this requirement. However, many beginners encounter issues such as image overlap and layout confusion, which typically stem from misunderstandings about subplot creation methods.
Common Error Analysis
In the original problem, the user attempted to use fig.add_subplot(i,2,1) to create subplots, but this approach has several key issues. First, the first parameter i represents the number of rows, which increases from 1 to 19 during the loop, resulting in subplot grids of varying sizes. Second, the third parameter is always 1, meaning all images are plotted in the first subplot position, causing image overlap.
The correct understanding is: the three parameters of add_subplot(nrows, ncols, index) represent the total number of rows, total number of columns, and the position index of the current subplot, respectively. Position indexing starts from the top-left corner and proceeds in row-major order.
Basic Solution
To achieve a 4×5 grid layout displaying 20 images, the grid structure must be clearly defined first:
import numpy as np
import matplotlib.pyplot as plt
w = 10
h = 10
fig = plt.figure(figsize=(8, 8))
columns = 4
rows = 5
for i in range(1, columns*rows +1):
img = np.random.randint(10, size=(h,w))
fig.add_subplot(rows, columns, i)
plt.imshow(img)
plt.show()In this implementation, columns and rows clearly define the grid dimensions, while the figsize parameter controls the overall figure size to ensure sufficient display space for each subplot. The loop variable i ranges from 1 to 20, corresponding to the index positions of the 20 subplots.
Advanced Features: Subplot Object Access
To provide more flexible plotting control, each subplot's axis object can be saved:
import numpy as np
import matplotlib.pyplot as plt
w = 10
h = 10
fig = plt.figure(figsize=(9, 13))
columns = 4
rows = 5
# Prepare additional plotting data
xs = np.linspace(0, 2*np.pi, 60)
ys = np.abs(np.sin(xs))
# Store axis objects
ax = []
for i in range(columns*rows):
img = np.random.randint(10, size=(h,w))
ax.append(fig.add_subplot(rows, columns, i+1))
ax[-1].set_title("ax:" + str(i))
plt.imshow(img, alpha=0.25)
# Add additional plots on selected subplots
ax[2].plot(xs, 3*ys)
ax[19].plot(ys**2, xs)
plt.show()This approach allows independent control over each subplot, including adding titles, adjusting transparency, and overlaying other graphical elements on specific subplots.
Modern Approach: Using plt.subplots
Matplotlib provides a more modern plt.subplots function that returns both the figure object and an array of axis objects:
import matplotlib.pyplot as plt
import numpy as np
# Parameter settings
h, w = 10, 10
nrows, ncols = 5, 4
figsize = [6, 8]
# Prepare additional plotting data
xs = np.linspace(0, 2*np.pi, 60)
ys = np.abs(np.sin(xs))
# Create figure and axis array
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)
# Plot images on each subplot
for i, axi in enumerate(ax.flat):
img = np.random.randint(10, size=(h,w))
axi.imshow(img, alpha=0.25)
rowid = i // ncols
colid = i % ncols
axi.set_title("Row:" + str(rowid) + ", Col:" + str(colid))
# Access specific subplots via 2D indexing
ax[0][2].plot(xs, 3*ys, color='red', linewidth=3)
ax[4][3].plot(ys**2, xs, color='green', linewidth=3)
plt.tight_layout(True)
plt.show()The main advantage of this method is that axis objects are organized as a 2D array, allowing direct access to specific subplots via ax[row][col], which is more intuitive and convenient when dealing with large grids.
Axis Sharing and Tick Control
When all subplots display the same type of data, sharing axes can create a cleaner visual effect:
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize, sharex=True, sharey=True)
for i, axi in enumerate(ax.flat):
img = np.random.randint(10, size=(h,w))
axi.imshow(img, alpha=0.25)
# Control tick count
axi.xaxis.set_major_locator(plt.MaxNLocator(5))
axi.yaxis.set_major_locator(plt.MaxNLocator(4))
plt.tight_layout(True)
plt.show()The sharex=True and sharey=True parameters ensure all subplots share the same x-axis and y-axis ranges, with tick labels automatically hidden for inner subplots. MaxNLocator is used to control the number of displayed ticks, preventing overcrowding.
Practical Application Considerations
In practical applications, several important factors must be considered. The figure size figsize should be adjusted according to the number of subplots and image resolution to ensure adequate display space for each subplot. tight_layout(True) automatically adjusts subplot spacing to prevent label overlap. For color images, consistent colormaps should be ensured, and the vmin and vmax parameters can be used to unify color ranges.
Performance Optimization Suggestions
When processing large numbers of images, performance becomes an important consideration. It is recommended to use vectorized operations to generate image data, avoiding repeated creation of identically structured arrays within loops. For static image displays, consider using plt.ioff() to turn off interactive mode and improve rendering speed. In Jupyter Notebook environments, use %matplotlib inline to ensure images are displayed correctly.
Conclusion
By correctly understanding Matplotlib's subplot mechanism, multiple images can be efficiently organized within a single figure. From the basic add_subplot to the modern plt.subplots, Matplotlib offers multiple methods to meet requirements of varying complexity. Mastering advanced techniques such as axis sharing, tick control, and layout optimization enables the creation of professional-level multi-image displays. These techniques are widely applicable not only in academic research and data analysis but also provide powerful visualization support for tasks such as image comparison and algorithm evaluation.