【问题标题】:Plotting a 3D array second by second without converting it to 2D with np.concatenate, np.append or indexing逐秒绘制 3D 数组,而不使用 np.concatenate、np.append 或索引将其转换为 2D
【发布时间】:2021-08-21 01:34:38
【问题描述】:
x = np.array[[[8, 7, 1, 0, 3],
              [2, 8, 5, 5, 2],
              [1, 1, 1, 1, 1]],

             [[8, 4, 1, 0, 0],
              [6, 8, 5, 5, 2],
              [1, 1, 1, 1, 1]],

             [[2, 4, 0, 2, 3],
              [2, 5, 5, 3, 2],
              [1, 1, 1, 1, 1]],

             [[4, 7, 2, 8, 0],
              [1, 3, 6, 5, 2],
              [1, 1, 1, 1, 1]]]

我有一个名为 xNumPy 数组,我想绘制它。这里每 5 列数据代表 1 秒。所以我的数组是 5*4=20 秒的数据。我希望这个数组(我将使用plt.imshow 命令绘制)通过每秒添加到它旁边来增加它。也就是说,只有

[8, 7, 1, 0, 3],
[2, 8, 5, 5, 2],
[1, 1, 1, 1, 1]]

会在第一秒绘制,然后

[[8, 7, 1, 0, 3, 8, 4, 1, 0, 0],
 [2, 8, 5, 5, 2, 6, 8, 5, 5, 2],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

将在第二秒内绘制,以此类推最多 4 秒。

但在此之前,我们需要看到我们的数组每秒递增一次。 您可以在下面找到我想要的图像。

但是这里有一个非常重要的问题。我现实生活中的阵列要大得多。因此,当我想使用np.concatenatenp.appendindexing 将我拥有的 3D 数组转换为 2D 时,我的计算机因为数组太大而崩溃。有什么方法可以使用 matplotlib 库而不将其转换为 2D 吗?我认为可以使用 for 循环来完成,但这里的问题是,在我在互联网上看到的示例中,它们完全刷新了图像,而不是将其附加到另一个旁边。

【问题讨论】:

    标签: python python-3.x numpy matplotlib multidimensional-array


    【解决方案1】:

    更新答案:

    以下代码在我的 8GB RAM 和形状为 (475,5400,200) 的数据数组的笔记本电脑上运行时间不到 5 分钟。

    d1,d2,d3 = 475,5400,200 # dimensions of the data
    
    # Create some data
    values = np.zeros((d1,d2,d3))
    values[:] = 1+np.cos(np.arange(d2)/200)[:,None]
    values[:] *= 1+np.sin(np.arange(d1*d3)/1000).reshape(d1,d3)[:,None,:]
    
    # Produce plots
    fig = plt.figure(figsize=(10,2))
    plt.xlim((0,d1*d3))
    yaxis = range(d2,-1,-1)
    vmin = values.min()
    vmax = values.max()
    
    # plot a background of zeros
    plt.pcolormesh([0,d1*d3],[d2,0],[[0]], vmin=vmin,vmax=vmax)
    plt.savefig('test-000.png')
    plt.clf() # clear figure
    
    # plot the data
    for i,v in enumerate(values):
        print(i)
        plt.xlim((0,d1*d3)); plt.xticks([], ""); plt.yticks([], "")
        xaxis = range(i*d3,(i+1)*d3+1)
        plt.pcolormesh(xaxis,yaxis,v, vmin=vmin,vmax=vmax)
        plt.savefig('test-{:03d}.png'.format(i+1), transparent=True)
        plt.clf() # clear figure
    plt.close()
    

    上面的代码产生了 476 帧,需要叠加起来形成一个动画 gif。我为此使用了 ImageMagick:

    convert -delay 2 -layers 'optimize' -dispose none test-*.png test.gif
    

    这是生成的动画:

    我希望这个方法也适用于你的电脑!

    ...

    原始答案:(不适用于 OP,因为他的计算机内存不足)

    我不知道如何使用 imshow 做到这一点,但这是我如何使用 pcolormesh 做到的:

    d1,d2,d3 = x.shape # dimensions of x
    vmin = x.min()
    vmax = x.max()
    
    fig = plt.figure(figsize=(10,2))
    plt.xlim((0,d1*d3))
    yaxis = range(d2,-1,-1)
    
    # plot a background of zeros
    xaxis = range(0,d1*d3+1)
    plt.pcolormesh(xaxis,yaxis,np.zeros((d2,d1*d3)), vmin=vmin,vmax=vmax)
    plt.savefig('test-0.png')
    
    # plot your data 5 seconds at a time
    for i,xi in enumerate(x):
        xaxis = range(i*d3,(i+1)*d3+1)
        plt.pcolormesh(xaxis,yaxis,xi, vmin=vmin,vmax=vmax)
        plt.savefig('test-{}.png'.format(i+1))
    plt.close()
    

    这段代码以 png 格式每 5 秒保存一帧。为了制作下面的动画 gif,我使用了 ImageMagick:convert -delay 50 test*.png test.gif

    我确信有更有效的方法来制作动画,而不是保存每一帧然后从帧中制作一个 gif。 但是,我对 matplotlib 和动画情节没有太多经验,所以也许其他人可以推荐一种更好的方法来制作动画 gif?

    【讨论】:

    • 谢谢,我要试试这个。
    • 对不起,它没有用。我实际使用的数组太大了,这可能就是它不起作用的原因。我认为这种方法会消耗大量 RAM。
    • @mehmet_kacmaz_03 你的阵列有多大? (以及您有多少 RAM)。如果您降低图像质量,也许您会得到它的工作,并且根据图像的大小,质量损失甚至可能对眼睛不可见。尝试fig = plt.figure(dpi=10),但可能需要更小的dpi,因此也可以尝试更小的dpi 值。
    • 谢谢,我马上试试。顺便说一下,数组的维度是 (475,5400,200),我的 RAM 是 12 Gb。
    • @mehmet_kacmaz_03 。我用一种占用很少 RAM 并且比我原来的答案快得多的方法更新了我的答案。我希望这也适用于您的计算机。
    猜你喜欢
    • 2021-08-20
    • 1970-01-01
    • 2018-04-08
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多