我想将一个numpy 2D数组复制到第三维。例如,如果我有这样一个(2D)numpy数组:
import numpy as np
arr = np.array([[1,2],[1,2]])
将其转换为3D矩阵,在新维度中包含N个此类副本,如N = 3:
np.array([[[1,2],[1,2]],[[1,2],[1,2]],[[1,2],[1,2]]])
答案 0 :(得分:87)
可能最干净的方法是使用np.repeat
:
while True:
A = raw_input('Enter A:')
try:
A = float(A)
except ValueError:
print "enter a float!"
else:
if A == 0:
print "Enter not 0"
else:
break
话虽如此,您通常可以使用broadcasting完全避免重复数组。例如,我们想要添加a = np.array([[1, 2], [1, 2]])
print(a.shape)
# (2, 2)
# indexing with np.newaxis inserts a new 3rd dimension, which we then repeat the
# array along, (you can achieve the same effect by indexing with None, see below)
b = np.repeat(a[:, :, np.newaxis], 3, axis=2)
print(b.shape)
# (2, 2, 3)
print(b[:, :, 0])
# [[1 2]
# [1 2]]
print(b[:, :, 1])
# [[1 2]
# [1 2]]
print(b[:, :, 2])
# [[1 2]
# [1 2]]
向量:
(3,)
到c = np.array([1, 2, 3])
。我可以在第三维中复制a
3次的内容,然后在第一维和第二维中复制a
两次的内容,这样我的两个数组都是c
,然后计算他们的总和。但是,这样做更简单快捷:
(2, 2, 3)
此处,d = a[..., None] + c[None, None, :]
的形状为a[..., None]
,(2, 2, 1)
的形状为c[None, None, :]
*。当我计算总和时,结果会被广播'沿着大小为1的尺寸,给我一个形状(1, 1, 3)
的结果:
(2, 2, 3)
广播是一种非常强大的技术,因为它避免了在内存中创建输入数组的重复副本所涉及的额外开销。
*虽然我为了清晰起见而添加了print(d.shape)
# (2, 2, 3)
print(d[..., 0]) # a + c[0]
# [[2 3]
# [2 3]]
print(d[..., 1]) # a + c[1]
# [[3 4]
# [3 4]]
print(d[..., 2]) # a + c[2]
# [[4 5]
# [4 5]]
索引None
实际上并不是必需的 - 您也可以c
,即广播a[..., None] + c
针对(2, 2, 1)
数组的数组。这是因为如果其中一个阵列的尺寸小于另一个阵列,则只需要兼容两个阵列的尾随尺寸。举一个更复杂的例子:
(3,)
答案 1 :(得分:17)
另一种方法是使用numpy.dstack
。假设您要重复矩阵a
num_repeats
次:
import numpy as np
b = np.dstack([a]*num_repeats)
诀窍是将矩阵a
包装到单个元素的列表中,然后使用*
运算符复制此列表中的元素num_repeats
次。
例如,如果:
a = np.array([[1, 2], [1, 2]])
num_repeats = 5
这在第三维中重复[1 2; 1 2]
5次。验证(在IPython中):
In [110]: import numpy as np
In [111]: num_repeats = 5
In [112]: a = np.array([[1, 2], [1, 2]])
In [113]: b = np.dstack([a]*num_repeats)
In [114]: b[:,:,0]
Out[114]:
array([[1, 2],
[1, 2]])
In [115]: b[:,:,1]
Out[115]:
array([[1, 2],
[1, 2]])
In [116]: b[:,:,2]
Out[116]:
array([[1, 2],
[1, 2]])
In [117]: b[:,:,3]
Out[117]:
array([[1, 2],
[1, 2]])
In [118]: b[:,:,4]
Out[118]:
array([[1, 2],
[1, 2]])
In [119]: b.shape
Out[119]: (2, 2, 5)
最后我们可以看到矩阵的形状为2 x 2
,第三维中有5个切片。
答案 2 :(得分:3)
A=np.array([[1,2],[3,4]])
B=np.asarray([A]*N)
编辑@ Mr.F,以保留维度顺序:
B=B.T
答案 3 :(得分:3)
现在也可以使用np.tile如下实现:
import numpy as np
a = np.array([[1,2],[1,2]])
b = np.tile(a,(3, 1,1))
b.shape
(3,2,2)
b
array([[[1, 2],
[1, 2]],
[[1, 2],
[1, 2]],
[[1, 2],
[1, 2]]])
答案 4 :(得分:2)
这是一个完全符合要求的广播示例。
b*a
然后(b*a)[:,:,0]
是期望的结果,array([[1, 2],[1, 2]])
生成a
,这是原(b*a)[:,:,1]
,.append()
等等。
答案 5 :(得分:2)
n-dim
数组扩展到n+1-dim
在NumPy 1.10.0
中引入的方法,我们可以利用numpy.broadcast_to
来简单地在3D
输入数组中生成一个2D
视图。好处将是没有额外的内存开销和几乎免费的运行时。这在数组很大且我们可以使用视图的情况下至关重要。此外,这将适用于一般n-dim
情况。
我会用stack
一词代替copy
,因为读者可能会将它与创建内存副本的数组复制混淆。
沿第一个轴堆叠
如果我们要沿第一个轴堆叠输入arr
,则用np.broadcast_to
创建3D
视图的解决方案是-
np.broadcast_to(arr,(3,)+arr.shape) # N = 3 here
沿第三个/最后一个轴堆叠
要沿第三轴堆叠输入arr
,创建3D
视图的解决方案是-
np.broadcast_to(arr[...,None],arr.shape+(3,))
如果我们实际上需要一个内存副本,则可以随时在其中附加.copy()
。因此,解决方案将是-
np.broadcast_to(arr,(3,)+arr.shape).copy()
np.broadcast_to(arr[...,None],arr.shape+(3,)).copy()
这是两种情况下堆叠的工作方式,并显示了样品箱的形状信息-
# Create a sample input array of shape (4,5)
In [55]: arr = np.random.rand(4,5)
# Stack along first axis
In [56]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[56]: (3, 4, 5)
# Stack along third axis
In [57]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[57]: (4, 5, 3)
相同的解决方案可以将n-dim
输入沿第一和最后一个轴扩展到n+1-dim
视图输出。让我们探讨一些更暗淡的情况-
3D输入大小写:
In [58]: arr = np.random.rand(4,5,6)
# Stack along first axis
In [59]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[59]: (3, 4, 5, 6)
# Stack along last axis
In [60]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[60]: (4, 5, 6, 3)
4D输入大小写:
In [61]: arr = np.random.rand(4,5,6,7)
# Stack along first axis
In [62]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[62]: (3, 4, 5, 6, 7)
# Stack along last axis
In [63]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[63]: (4, 5, 6, 7, 3)
以此类推。
让我们使用一个大样本2D
案例,获取时间并验证输出为view
。
# Sample input array
In [19]: arr = np.random.rand(1000,1000)
让我们证明所提出的解决方案确实是一种观点。我们将沿第一个轴使用堆栈(沿第三个轴的结果非常相似)-
In [22]: np.shares_memory(arr, np.broadcast_to(arr,(3,)+arr.shape))
Out[22]: True
让我们了解一下它实际上是免费的-
In [20]: %timeit np.broadcast_to(arr,(3,)+arr.shape)
100000 loops, best of 3: 3.56 µs per loop
In [21]: %timeit np.broadcast_to(arr,(3000,)+arr.shape)
100000 loops, best of 3: 3.51 µs per loop
作为一个视图,将N
从3
增加到3000
不会改变计时,并且两者在计时单位上都可以忽略不计。因此,在内存和性能上都是高效的!