从两个多维NumPy数组复制到另一个不同形状的数组

3
我有两个形状如下的numpy数组:
print(a.shape) -> (100, 20, 3, 3)
print(b.shape) -> (100, 3)

数组a为空的,我只需要预定义的形状,所以我用以下方式创建它:

a = numpy.empty(shape=(100, 20, 3, 3))

现在我想将数组b中的数据复制到数组a中,使得数组a的第二和第三维被相应b数组的行的同样3个值填充。
让我试着更加清晰地阐述: 数组b包含100行(100,3),每行都有三个值(100,3)。 现在,数组a100,20,3,3)的每一行也应该在最后一个维度上保持相同的三个值(100,20,3,3),而对于同一行(100,20,3,3),这些三个值在第二和第三维上保持不变(100,203,3)。
我怎样才能按照描述的方式复制数据而不使用循环?我无法完成它,但必须有一个简单的解决方案。
2个回答

2
你可以沿着 axis 使用 repeat。你也不需要预定义 a。我建议不要使用 broadcast_to,因为它返回的是只读视图,并且内存在元素之间共享:
a = np.repeat(b[:,None,None,:], 20, 1) #adds dimensions 1 and 2 and repeats 20 times along axis 1
a = np.repeat(a, 3, 2) #repeats 3 times along axis 2

更小的例子:

b = np.arange(2*3).reshape(2,3)
#[[0 1 2]
# [3 4 5]]
a = np.repeat(b[:,None,None,:], 2, 1) 
a = np.repeat(a, 3, 2) 
#shape(2,2,3,3)
[[[[0 1 2]
   [0 1 2]
   [0 1 2]]

  [[0 1 2]
   [0 1 2]
   [0 1 2]]]


 [[[3 4 5]
   [3 4 5]
   [3 4 5]]

  [[3 4 5]
   [3 4 5]
   [3 4 5]]]]

非常感谢,这似乎有效。你能想到另一种只使用广播和 None 而不使用 np.repeat 函数的方法吗?只是好奇是否有另一种方便的方法。 - H123321
@H123321,你可以使用np.broadcast_to(b, (2,3,2,3)).transpose(2,0,1,3),但正如我在帖子中提到的那样,我建议你不要这样做,除非你以后不会对它进行任何处理。仅使用None进行广播只会添加维度,而不会复制内容(添加维度的形状为1)。 - Ehsan
1
@Ehsan 只在视图上复制一份就足够了,而且比重复两次更好,不是吗? - Divakar
@Divakar 好主意。谢谢。点赞。如果我们只需要在一个轴上重复而不是两个轴,它的时间复杂度是否相同?或者重复比复制慢还有其他原因吗? - Ehsan
我猜测只有两次重复就意味着需要两份副本。 - Divakar
我明白了。谢谢。 - Ehsan

2
我们可以利用 np.broadcast_to
如果您对视图满意 -
np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3))

如果您需要一个具有自己内存空间的输出,只需使用.copy()进行追加即可。
如果您想节省内存并填充到已定义的数组a中:
a[:] = b[:,None,None,:]

请注意,我们可以跳过末尾的冒号:
时间:
In [20]: b = np.random.rand(100, 3)

In [21]: %timeit np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3))
5.93 µs ± 64.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [22]: %timeit np.broadcast_to(b[:,None, None, :], (100, 2, 3, 3)).copy()
11.4 µs ± 56.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [23]: %timeit np.repeat(np.repeat(b[:,None,None,:], 20, 1), 3, 2)
39.3 µs ± 147 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接