【问题标题】:How to display multiple images in one figure correctly? [duplicate]如何在一张图中正确显示多张图片? [复制]
【发布时间】:2018-03-18 20:08:53
【问题描述】:

我正在尝试在单个图形上显示 20 个随机图像。确实显示了图像,但是它们被覆盖了。我正在使用:

import numpy as np
import matplotlib.pyplot as plt
w=10
h=10
fig=plt.figure()
for i in range(1,20):
    img = np.random.randint(10, size=(h,w))
    fig.add_subplot(i,2,1)
    plt.imshow(img)
plt.show()

我希望它们自然地出现在网格布局(比如 4x5)中,每个都具有相同的大小。部分问题是我不知道 add_subplot 的参数是什么意思。该文档指出,参数是行数、列数和图号。没有定位论点。另外,地块编号只能是1或2。我怎样才能做到这一点?

【问题讨论】:

  • 虽然从技术上讲,这个问题是重复的,但这个问题的浏览量是另一个问题的 10 倍左右。

标签: matplotlib


【解决方案1】:

这是我的方法,您可以尝试:

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()

生成的图像:

(原答案日期:2017 年 10 月 7 日 4:20)

编辑 1

由于这个答案的受欢迎程度超出了我的预期。而且我看到需要进行一些小的更改才能灵活地操作各个图。这样我就可以将这个新版本提供给原始代码。 本质上,它提供了:-

  1. 访问子图的各个轴
  2. 可以在选定的轴/子图上绘制更多特征

新代码:

import numpy as np
import matplotlib.pyplot as plt

w = 10
h = 10
fig = plt.figure(figsize=(9, 13))
columns = 4
rows = 5

# prep (x,y) for extra plotting
xs = np.linspace(0, 2*np.pi, 60)  # from 0 to 2pi
ys = np.abs(np.sin(xs))           # absolute of sine

# ax enables access to manipulate each of subplots
ax = []

for i in range(columns*rows):
    img = np.random.randint(10, size=(h,w))
    # create subplot and append to ax
    ax.append( fig.add_subplot(rows, columns, i+1) )
    ax[-1].set_title("ax:"+str(i))  # set title
    plt.imshow(img, alpha=0.25)

# do extra plots on selected axes/subplots
# note: index starts with 0
ax[2].plot(xs, 3*ys)
ax[19].plot(ys**2, xs)

plt.show()  # finally, render the plot

结果图:

编辑 2

在前面的示例中,代码提供了对具有单个索引的子图的访问,当图中有很多行/列的子图时,这很不方便。这是它的替代方案。下面的代码提供了对[row_index][column_index]的子图的访问,更适合对许多子图的数组进行操作。

import matplotlib.pyplot as plt
import numpy as np

# settings
h, w = 10, 10        # for raster image
nrows, ncols = 5, 4  # array of sub-plots
figsize = [6, 8]     # figure size, inches

# prep (x,y) for extra plotting on selected sub-plots
xs = np.linspace(0, 2*np.pi, 60)  # from 0 to 2pi
ys = np.abs(np.sin(xs))           # absolute of sine

# create figure (fig), and array of axes (ax)
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)

# plot simple raster image on each sub-plot
for i, axi in enumerate(ax.flat):
    # i runs from 0 to (nrows*ncols-1)
    # axi is equivalent with ax[rowid][colid]
    img = np.random.randint(10, size=(h,w))
    axi.imshow(img, alpha=0.25)
    # get indices of row/column
    rowid = i // ncols
    colid = i % ncols
    # write row/col indices as axes' title for identification
    axi.set_title("Row:"+str(rowid)+", Col:"+str(colid))

# one can access the axes by ax[row_id][col_id]
# do additional plotting on ax[row_id][col_id] of your choice
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()

结果图:

子图数组的刻度和刻度标签

如果所有子图共享相同的值范围,则可以隐藏子图附带的一些刻度和刻度标签以获得更清晰的图。所有的刻度和刻度标签都可以隐藏,除了左边和底部的外边缘,就像这个图一样。

要实现仅在左侧和底部边缘共享刻度标签的绘图,您可以执行以下操作:-

在fig, ax = plt.subplots() 中添加选项sharex=True, sharey=True

那行代码会变成:

fig,ax=plt.subplots(nrows=nrows,ncols=ncols,figsize=figsize,sharex=True,sharey=True)

要指定所需的刻度数和要绘制的标签,

在for i, axi in enumerate(ax.flat):的正文中,添加这些代码

axi.xaxis.set_major_locator(plt.MaxNLocator(5))
axi.yaxis.set_major_locator(plt.MaxNLocator(4))

数字 5 和 4 是要绘制的刻度/刻度标签的数量。您可能需要适合您的情节的其他值。

【讨论】:

  • 要摆脱子图周围的数字/标记,您可以执行 ax = fig.add_subplot(rows, columns, i) ax.set_xticks([]) ax.set_yticks([])跨度>
  • @AnnaVopureta;实际上,可以操纵选定的轴,比如ax[5],并使用类似:ax[5].set_xxxx(yyy)。这是更笼统的想法。
  • 你如何保存这个数字?
  • plt.savefig('your_preferred_filename.png')
【解决方案2】:

您可以尝试以下方法:

import matplotlib.pyplot as plt
import numpy as np

def plot_figures(figures, nrows = 1, ncols=1):
    """Plot a dictionary of figures.

    Parameters
    ----------
    figures : <title, figure> dictionary
    ncols : number of columns of subplots wanted in the display
    nrows : number of rows of subplots wanted in the figure
    """

    fig, axeslist = plt.subplots(ncols=ncols, nrows=nrows)
    for ind,title in zip(range(len(figures)), figures):
        axeslist.ravel()[ind].imshow(figures[title], cmap=plt.jet())
        axeslist.ravel()[ind].set_title(title)
        axeslist.ravel()[ind].set_axis_off()
    plt.tight_layout() # optional



# generation of a dictionary of (title, images)
number_of_im = 20
w=10
h=10
figures = {'im'+str(i): np.random.randint(10, size=(h,w)) for i in range(number_of_im)}

# plot of the images in a figure, with 5 rows and 4 columns
plot_figures(figures, 5, 4)

plt.show()

但是,这基本上只是从此处复制和粘贴:Multiple figures in a single window,因此该帖子应被视为重复。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2013-06-11
    • 2016-04-16
    • 2022-10-21
    • 2021-12-14
    • 2021-11-11
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多