如何将数组复制/重复N次到新数组?

JDS*_*JDS 6 python arrays numpy

我有:

test = np.random.randn(40,40,3)
Run Code Online (Sandbox Code Playgroud)

我想做:

result = Repeat(test, 10)
Run Code Online (Sandbox Code Playgroud)

这样result包含test重复10次的数组,形状如下:

(10, 40, 40, 3)
Run Code Online (Sandbox Code Playgroud)

因此,使用新轴创建一个张量,以容纳10个副本test.我也想尽可能高效地做到这一点.我怎么能和Numpy一起做这个?

谢谢!

Odd*_*org 10

您可以使用以下np.repeat方法np.newaxis:

import numpy as np

test = np.random.randn(40,40,3)
result = np.repeat(test[np.newaxis,...], 10, axis=0)
print(result.shape)
>> (10, 40, 40, 3)
Run Code Online (Sandbox Code Playgroud)


aba*_*ert 7

假设您要复制值 10 次,则只能复制 10stack个数组:

def repeat(arr, count):
    return np.stack([arr for _ in range(count)], axis=0)
Run Code Online (Sandbox Code Playgroud)

axis=0 实际上是默认值,所以在这里并不是真的有必要,但我认为它更清楚地表明您在前面添加了新轴。


事实上,这与示例stack所做的几乎相同:

>>> arrays = [np.random.randn(3, 4) for _ in range(10)]
>>> np.stack(arrays, axis=0).shape
(10, 3, 4)
Run Code Online (Sandbox Code Playgroud)

乍一看,您可能认为repeattile会更合适。

但是repeat是关于在现有轴上重复(或展平阵列),因此您需要reshape在之前或之后。(这同样有效,但我认为并不那么简单。)

并且tile(假设你使用一个类似数组的reps——reps它基本上repeat是标量)是关于在所有方向上填写一个多维规范,这比你想要的这个简单案例复杂得多。


所有这些选项都将同样有效。它们都将数据复制 10 次以上,这是昂贵的部分;任何内部处理、构建微小的中间对象等的成本都是无关紧要的。使其更快的唯一方法是避免复制。您可能不想这样做。

但是,如果您这样做……要在 10 个副本之间共享行存储,您可能需要broadcast_to

def repeat(arr, count):
    return np.broadcast_to(arr, (count,)+arr.shape)
Run Code Online (Sandbox Code Playgroud)

请注意,broadcast_to这实际上并不能保证它避免复制,只是它返回某种只读视图,其中“广播数组的多个元素可能引用单个内存位置”。在实践中,它将避免复制。如果你出于某种原因确实需要保证这一点(或者如果你想要一个可写的视图——这通常是一个糟糕的主意,但也许你有一个很好的理由......),你必须下降到as_strided

def repeat(arr, count):
    shape = (count,) + arr.shape
    strides = (0,) + arr.strides
    return np.lib.stride_tricks.as_strided(
        arr, shape=shape, strides=strides, writeable=False)
Run Code Online (Sandbox Code Playgroud)

请注意,一半的文档as_strided警告你可能不应该使用它,另一半警告你绝对不应该将它用于可写视图,所以......在做之前确保这是你想要的。