我正在尝试找到一种矢量化方式(或者至少比使用循环更好)来从 2D NumPy 数组列表创建一个 3 维 NumPy 数组。现在,我有一个列表 L 看起来像:
UIViewPropertyAnimator
每个 NumPy 数组的第二维大小相同(在上面的例子中,它是 3)。但是第一个维度有不同的大小。
我的目标是创建一个包含上述数据的 3D NumPy 数组 M。我一直在尝试使用 np.pad() 函数,因为我的每个数组的第一个维度都有最大大小,但看起来它只能对列表的各个元素进行操作。然后我可以使用该函数并循环遍历每个数组来做我想做的事情。但是,如果可能,我想使用矢量化方法在没有循环的情况下执行此操作。有什么技术可以做到这一点吗?
这个问题与 this one 相关,但我希望一次对我的整个列表进行此操作。
答案 0 :(得分:1)
首先让我们看一下将一维数组填充到通用大小的常见任务。
In [441]: alist = [np.ones((2,),int),np.zeros((1,),int)+2, np.zeros((3,),int)+3]
In [442]: alist
Out[442]: [array([1, 1]), array([2]), array([3, 3, 3])]
明显的迭代方法:
In [443]: [np.hstack((arr, np.zeros((3-arr.shape[0]),int))) for arr in alist]
Out[443]: [array([1, 1, 0]), array([2, 0, 0]), array([3, 3, 3])]
In [444]: np.stack(_)
Out[444]:
array([[1, 1, 0],
[2, 0, 0],
[3, 3, 3]])
一个聪明的选择。它仍然需要迭代来确定大小,但其余的是整个数组“矢量化”:
In [445]: sizes = [arr.shape[0] for arr in alist]
In [446]: sizes
Out[446]: [2, 1, 3]
使用填充值制作输出数组:
In [448]: res = np.zeros((3,3),int)
做一个聪明的面具(@Divakar首先提出这个)
In [449]: np.array(sizes)[:,None]>np.arange(3)
Out[449]:
array([[ True, True, False],
[ True, False, False],
[ True, True, True]])
然后将“扁平化”输入映射到 res:
In [450]: res[_]=np.hstack(alist)
In [451]: res
Out[451]:
array([[1, 1, 0],
[2, 0, 0],
[3, 3, 3]])
我认为这个过程可以扩展到您的 2d=>3d 案例。但这需要一些工作。我试着直接做,发现我在敷面膜时迷路了。这就是为什么我决定首先布局 1d=>2d 的情况。有足够的开箱即用的思考,我必须每次都制定出新鲜的细节。
In [457]: a2list = [np.ones((2,3),int),np.zeros((1,3),int)+2, np.zeros((3,3),int)+3]
In [458]: [np.vstack((arr, np.zeros((3-arr.shape[0],arr.shape[1]),int))) for arr in a2list]
Out[458]:
[array([[1, 1, 1],
[1, 1, 1],
[0, 0, 0]]),
array([[2, 2, 2],
[0, 0, 0],
[0, 0, 0]]),
array([[3, 3, 3],
[3, 3, 3],
[3, 3, 3]])]
In [459]: np.stack(_)
Out[459]:
array([[[1, 1, 1],
[1, 1, 1],
[0, 0, 0]],
[[2, 2, 2],
[0, 0, 0],
[0, 0, 0]],
[[3, 3, 3],
[3, 3, 3],
[3, 3, 3]]])
现在是“矢量化”方法:
In [460]: sizes = [arr.shape[0] for arr in a2list]
In [461]: sizes
Out[461]: [2, 1, 3]
In [462]: np.array(sizes)[:,None]>np.arange(3)
Out[462]:
array([[ True, True, False],
[ True, False, False],
[ True, True, True]])
In [463]: res = np.zeros((3,3,3),int)
以及来自掩码的相应索引:
In [464]: I,J=np.nonzero(Out[462])
In [465]: I
Out[465]: array([0, 0, 1, 2, 2, 2])
In [466]: J
Out[466]: array([0, 1, 0, 0, 1, 2])
In [467]: res[I,J,:] = np.vstack(a2list)
In [468]: res
Out[468]:
array([[[1, 1, 1],
[1, 1, 1],
[0, 0, 0]],
[[2, 2, 2],
[0, 0, 0],
[0, 0, 0]],
[[3, 3, 3],
[3, 3, 3],
[3, 3, 3]]])