如何制作重复的`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.repeat
和 numpy.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]])
如何将 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.repeat
和 numpy.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]])