我想把一个二维数组复制到三维空间。例如,给定2D numpy数组:
import numpy as np
arr = np.array([[1, 2], [1, 2]])
# arr.shape = (2, 2)
将其转换为在新维度中具有N个这样的副本的3D矩阵。使用N=3
作用于arr
,输出应为:
new_arr[:,:,0]
# array([[1, 2], [1, 2]])
new_arr[:,:,1]
# array([[1, 2], [1, 2]])
new_arr[:,:,2]
# array([[1, 2], [1, 2]])
# new_arr.shape = (2, 2, 3)
7条答案
按热度按时间8gsdolmq1#
最简单的方法可能是使用
np.repeat
:话虽如此,您通常可以通过使用broadcasting完全避免重复数组。例如,假设我想添加一个
(3,)
向量:到
a
。我可以在第三个维度复制a
的内容3次,然后在第一个和第二个维度复制c
的内容两次,这样我的两个数组都是(2, 2, 3)
,然后计算它们的总和。但是,这样做更简单,更快捷:这里,
a[..., None]
的形状为(2, 2, 1)
,c[None, None, :]
的形状为(1, 1, 3)
*。当我计算总和时,结果会沿着尺寸为1的维度沿着“广播”出来,得到形状为(2, 2, 3)
的结果:广播是一种非常强大的技术,因为它避免了在内存中创建输入数组的重复副本所涉及的额外开销。
None
索引到c
中-您也可以使用a[..., None] + c
,即。针对(3,)
阵列广播(2, 2, 1)
阵列。这是因为如果其中一个数组的维数比另一个少,那么两个数组的 trailing 维需要兼容。给予一个更复杂的例子:rkue9o1l2#
另一种方法是使用
numpy.dstack
。假设你想重复矩阵a
num_repeats
次:技巧是将矩阵
a
Package 成一个单一元素的列表,然后使用*
运算符将该列表中的元素复制num_repeats
次。例如,如果:
这将在第三维中重复
[1 2; 1 2]
数组5次。要验证(在IPython中):最后我们可以看到矩阵的形状是
2 x 2
,在第三维中有5个切片。n3ipq98p3#
使用视图并获得免费运行时!将通用
n-dim
阵列扩展到n+1-dim
在NumPy
1.10.0
中引入,我们可以利用numpy.broadcast_to
简单地在2D
输入数组中生成3D
视图。好处是没有额外的内存开销和几乎免费的运行时。这在数组很大并且我们可以使用视图的情况下是必不可少的。此外,这将适用于一般的n-dim
情况。我将使用
stack
来代替copy
,因为读者可能会将其与创建内存副本的数组复制混淆。沿沿着第一轴堆叠
如果我们想将输入
arr
沿着第一个轴堆叠,则使用np.broadcast_to
创建3D
视图的解决方案为-沿沿着第三/最后一个轴堆叠
要沿第三个轴沿着堆叠输入
arr
,创建3D
视图的解决方案为-如果我们真的需要一个内存副本,我们可以在那里附加
.copy()
。因此,解决办法是-以下是两种情况下的堆叠工作方式,显示了示例情况下的形状信息-
相同的解决方案可以沿着第一个和最后一个轴将
n-dim
输入扩展到n+1-dim
视图输出。我们来看看更高亮度的情况-3D输入案例:
4D输入案例:
等
计时
让我们使用一个大样本
2D
案例,获取时序并验证输出是否为view
。让我们来证明所提出的解决方案确实是一个视图。我们将使用沿沿着第一轴的叠加(结果与沿沿着第三轴的叠加非常相似)-
我们来看看时间表,它实际上是免费的-
作为一个视图,将
N
从3
增加到3000
在时序上没有任何变化,两者在时序单位上都可以忽略不计。因此,高效的内存和性能!vktxenjb4#
现在也可以使用np.tile实现,如下所示:
xmq68pz95#
编辑@Mr.F,以保留维度顺序:
wz1wpwve6#
下面是一个广播示例,它完全按照要求执行。
然后
b*a
是期望的结果,(b*a)[:,:,0]
产生array([[1, 2],[1, 2]])
,这是原始的a
,(b*a)[:,:,1]
也是如此,等等。mrwjdhj37#
总结上述解决方案:
好运