如何制作重复的`numpy`数组视图

How to make a `numpy` array view that repeats

如何将 numpy 数组切片超出其形状,以便重复数组中的值,而不必将整个数组存储在内存中?这是我想做的事情:

x = numpy.array([[1, 2], [3, 4]])
x[0:3, 0:3]
->
[[1, 2, 1, 2],
 [3, 4, 3, 4],
 [1, 2, 1, 2],
 [3, 4, 3, 4]]

我知道 numpy.repeatnumpy.tile 但它们都复制了数组,我想像 x[1238123:1238143,5328932:5328941] 那样对我的数组进行切片而不需要赚到数百万较小数组的副本数。

NumPy 数组不支持。一个数组必须在每个维度上都有一致的步幅,而你想要的数组不会有那个。

您可以为结果实现您自己的自定义类型,但它不会以 NumPy 的速度运行,并且不会与 NumPy 直接兼容 - 充其量,您尝试调用的任何 NumPy 函数都必须首先从您的对象构建一个真正的数组。

如果您的用例只需要小切片,就像您的 x[1238123:1238143,5328932:5328941] 示例一样,您最好的选择可能是将切片端点向下调整为等效的较小值,然后平铺和切片。

通过 strides 技巧我们可以制作 4d 视图:

In [18]: x = numpy.array([[1, 2], [3, 4]])
In [19]: as_strided = np.lib.stride_tricks.as_strided
In [20]: X = as_strided(x, shape=(2,2,2,2), strides=(0,16,0,8))
In [21]: X
Out[21]: 
array([[[[1, 2],
         [1, 2]],

        [[3, 4],
         [3, 4]]],


       [[[1, 2],
         [1, 2]],

        [[3, 4],
         [3, 4]]]])

可以改造成你想要的数组:

In [22]: X.reshape(4,4)
Out[22]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4],
       [1, 2, 1, 2],
       [3, 4, 3, 4]])

但是重塑将创建 X 的副本。

该 (2,2) 数组可以在计算中用作 (1,1,2,2) 数组,如果需要可扩展为 (2,2,2,2):

In [25]: x[None,None,:,:]
Out[25]: 
array([[[[1, 2],
         [3, 4]]]])
In [26]: np.broadcast_to(x,(2,2,2,2))
Out[26]: 
array([[[[1, 2],
         [3, 4]],

        [[1, 2],
         [3, 4]]],


       [[[1, 2],
         [3, 4]],

        [[1, 2],
         [3, 4]]]])

因此广播让我们可以在更大的计算中使用数组视图。

对 2D 数组使用 numpy.ndarray.take 两次(对 3D 数组使用三次,等等)。每次您指定不同的轴。对于您需要的情况:

x.take(range(0, 4), mode='wrap', axis = 0).take(range(0, 4), mode='wrap', axis = 1)

会产生

array([[1, 2, 1, 2],
       [3, 4, 3, 4],
       [1, 2, 1, 2],
       [3, 4, 3, 4]])