包含具有可变形状的多维 numpy 数组的 numpy 数组

Posted

技术标签:

【中文标题】包含具有可变形状的多维 numpy 数组的 numpy 数组【英文标题】:numpy array containing multi-dimension numpy arrays with variable shape 【发布时间】:2020-08-08 18:35:53 【问题描述】:

我有一个 numpy 数组列表,其形状为以下之一:(10,4,4,20), (10,4,6,20)。我想将列表转换为 numpy 数组。因为,它们的形状不同,我不能把它们叠起来。所以,我想创建 numpy 数组,将每个数组视为一个对象,如here。我尝试了以下方法:

b = numpy.array(a)
b = numpy.array(a, dtype=object)

其中 a 是 numpy 数组的列表。两者都给我以下错误:

ValueError: could not broadcast input array from shape (10,4,4,20) into shape (10,4)

如何将该列表转换为 numpy 数组?

示例

import numpy
a = [numpy.random.random((10,4,4,20)),
     numpy.random.random((10,4,6,20)),
     numpy.random.random((10,4,6,20)),
     numpy.random.random((10,4,4,20)),
     numpy.random.random((10,4,6,20)),
     numpy.random.random((10,4,6,20)),
     numpy.random.random((10,4,4,20)),
     numpy.random.random((10,4,4,20)),
     numpy.random.random((10,4,6,20))
    ]
b = numpy.array(a)

用例: 我知道 numpy 对象数组效率不高,但我没有对它们进行任何操作。通常,我有一个相同形状的 numpy 数组的列表,因此我可以轻松地堆叠它们。这个数组被传递给另一个函数,它只选择某些元素。如果我的数据是 numpy 数组,我可以做b[[1,3,8]]。但我不能对列表做同样的事情。如果我对 list 尝试相同的操作,我会收到以下错误

c = a[[1,3,8]]
TypeError: list indices must be integers or slices, not list

【问题讨论】:

如果您保持列表的原样,您仍然可以通过以下方式访问您想要的任何元素 a[0][1, 3, 3, 8] 其中 0 只是列表中的第一个 numpy 数组。但是,您如何区分第三维为 6 的数组,这意味着您如何知道您是否可以实际访问例如 a[6][1, 3, 5, 8] 我不想访问列表中第一个数组的1,3,5,8th 元素。我想访问列表中的1,3,5,8th numpy 数组。抱歉,如果我的问题令人困惑,因为我在示例中只使用了 2 个 numpy 数组。我已经更新了这个问题。希望现在很清楚 感谢您的澄清。使用[a[x] for x in [1, 3, 5, 8]] 怎么样?我不明白的是,如果您不对它们执行操作,为什么需要将数组堆叠起来? 是的。我能做到。通常,我得到相同形状的 numpy 数组。所以,我的其余代码假设它是一个 numpy 数组。这只是一个特例。我不想在使用此数据的任何地方添加额外的处理代码。 【参考方案1】:

np.array(alist) 如果列表数组的第一维不同,则将创建一个对象 dtype 数组。但是在您的情况下,它们在第三个方面有所不同,从而产生了此错误。实际上,它不能明确地确定包含维度的结束位置以及对象的开始位置。

In [270]: alist = [np.ones((10,4,4,20),int), np.zeros((10,4,6,20),int)]                                
In [271]: arr = np.array(alist)                                                                        
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-271-3fd8e9bd05a9> in <module>
----> 1 arr = np.array(alist)

ValueError: could not broadcast input array from shape (10,4,4,20) into shape (10,4)

相反,我们需要创建一个大小合适的对象数组,并将列表复制到其中。有时这个副本仍然会产生广播错误,但这里似乎还可以:

In [272]: arr = np.empty(2, object)                                                                    
In [273]: arr                                                                                          
Out[273]: array([None, None], dtype=object)
In [274]: arr[:] = alist                                                                               
In [275]: arr                                                                                          
Out[275]: 
array([array([[[[1, 1, 1, ..., 1, 1, 1],
         [1, 1, 1, ..., 1, 1, 1],
         [1, 1, 1, ..., 1, 1, 1],
...
         [0, 0, 0, ..., 0, 0, 0],
         [0, 0, 0, ..., 0, 0, 0]]]])], dtype=object)
In [276]: arr[0].shape                                                                                 
Out[276]: (10, 4, 4, 20)
In [277]: arr[1].shape                                                                                 
Out[277]: (10, 4, 6, 20)

【讨论】:

哇!如此优雅的解决方案!为此 +1。

以上是关于包含具有可变形状的多维 numpy 数组的 numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章

具有多维形状的 np.zeros 结构

如何将 4D numpy 数组重塑为 3D 数组

创建具有未指定可变行长度的多维数组(Java)

多处理 - 具有多维 numpy 数组的共享内存

python中ge=num_x0010_是啥意思

从具有适当形状的现有迭代中创建3D numpy数组