创建 numpy 数组的非平凡视图
Creating a non trivial view of numpy array
长话短说:
我正在寻找一种方法来获得 numpy 的非平凡视图,尤其是非连续视图 ndarray
。
例如,给定一个 1D ndarray x = np.array([1, 2, 3, 4])
,有没有办法获得它的非平凡 view,例如np.array([2, 4, 3, 1])
?
加长版
问题的背景如下:我有一个形状为 (U, V, S, T)
的 4D ndarray,我想以一种非平凡的方式将其重塑为形状为 (U*S, V*T)
的 2D ndarray,也就是说,一个简单的 np.reshape()
并不能解决问题,因为我有一个更复杂的索引方案,其中重塑的数组在内存中不会连续。在我的例子中,数组相当大,我想获得一个视图而不是数组的副本。
例子
给定一个 x(u, v, s, t)
形状 (2, 2, 2, 2)
的数组:
x = np.array([[[[1, 1], [1, 1]],[[2, 2], [2, 2]]],
[[[3, 3], [3, 3]], [[4, 4], [4, 4]]]])
我想获取数组的视图 z(a, b)
:
np.array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
这对应于 a = u * S + s
和 b = v * T + t
的索引方案,在这种情况下 S = 2 = T
.
我试过的
使用 np.reshape
甚至 as_strided
的各种方法。进行标准的重塑不会改变元素在内存中出现的顺序。我试着玩弄 order='F'
并转置了一下,但不知道哪个给了我正确的结果。
因为我知道索引方案,所以我尝试使用np.ravel()
对数组的扁平视图进行操作。我的想法是根据所需的索引方案创建一个索引数组,并将其应用于展平的数组视图,但不幸的是,fancy/advanced 索引给出了数组的副本,而不是视图。
问题
有什么方法可以实现我正在寻找的索引视图吗?
原则上,我认为这应该是可能的,例如 ndarray.sort()
执行数组的就地非平凡索引。另一方面,这可能是在 C/C++ 中实现的,所以在纯 Python?
中甚至不可能实现
让我们回顾一下数组的基础知识 - 它有一个平面数据缓冲区、一个 shape
、strides
和 dtype
。这三个属性用于以特定方式 view
数据缓冲区的元素,无论它是简单的 1d 序列、2d 还是更高维度。
真正的 view
比使用相同的数据缓冲区,但对其应用不同的形状、步幅或 dtype。
要从 [1,2,3,4]
得到 [2, 4, 3, 1]
需要从 2
开始,向前跳 2,然后跳回到 1 和向前跳 2。这不是可以表示的常规模式strides
.
arr[1::2]
给出 [2,4],arr[0::2]
给出 [1,3]
.
(U, V, S, T)
到 (U*S, V*T)
需要转置到 (U, S, V, T)
,然后再整形
arr.transpose(0,2,1,3).reshape(U*S, V*T)
那将需要一份副本,没有办法。
In [227]: arr = np.arange(2*3*4*5).reshape(2,3,4,5)
In [230]: arr1 = arr.transpose(0,2,1,3).reshape(2*4, 3*5)
In [231]: arr1.shape
Out[231]: (8, 15)
In [232]: arr1
Out[232]:
array([[ 0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 40, 41, 42,
43, 44],
[ 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 45, 46, 47,
48, 49],
....)
或者用你的x
In [234]: x1 = x.transpose(0,2,1,3).reshape(4,4)
In [235]: x1
Out[235]:
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
请注意元素的顺序不同:
In [254]: x.ravel()
Out[254]: array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4])
In [255]: x1.ravel()
Out[255]: array([1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 4, 4])
ndarray.sort
就地改变了数据缓冲区中字节的顺序。它在我们无法访问的低级别运行。它不是原始数组的 view
。
长话短说:
我正在寻找一种方法来获得 numpy 的非平凡视图,尤其是非连续视图 ndarray
。
例如,给定一个 1D ndarray x = np.array([1, 2, 3, 4])
,有没有办法获得它的非平凡 view,例如np.array([2, 4, 3, 1])
?
加长版
问题的背景如下:我有一个形状为 (U, V, S, T)
的 4D ndarray,我想以一种非平凡的方式将其重塑为形状为 (U*S, V*T)
的 2D ndarray,也就是说,一个简单的 np.reshape()
并不能解决问题,因为我有一个更复杂的索引方案,其中重塑的数组在内存中不会连续。在我的例子中,数组相当大,我想获得一个视图而不是数组的副本。
例子
给定一个 x(u, v, s, t)
形状 (2, 2, 2, 2)
的数组:
x = np.array([[[[1, 1], [1, 1]],[[2, 2], [2, 2]]],
[[[3, 3], [3, 3]], [[4, 4], [4, 4]]]])
我想获取数组的视图 z(a, b)
:
np.array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
这对应于 a = u * S + s
和 b = v * T + t
的索引方案,在这种情况下 S = 2 = T
.
我试过的
使用
np.reshape
甚至as_strided
的各种方法。进行标准的重塑不会改变元素在内存中出现的顺序。我试着玩弄order='F'
并转置了一下,但不知道哪个给了我正确的结果。因为我知道索引方案,所以我尝试使用
np.ravel()
对数组的扁平视图进行操作。我的想法是根据所需的索引方案创建一个索引数组,并将其应用于展平的数组视图,但不幸的是,fancy/advanced 索引给出了数组的副本,而不是视图。
问题
有什么方法可以实现我正在寻找的索引视图吗?
原则上,我认为这应该是可能的,例如 ndarray.sort()
执行数组的就地非平凡索引。另一方面,这可能是在 C/C++ 中实现的,所以在纯 Python?
让我们回顾一下数组的基础知识 - 它有一个平面数据缓冲区、一个 shape
、strides
和 dtype
。这三个属性用于以特定方式 view
数据缓冲区的元素,无论它是简单的 1d 序列、2d 还是更高维度。
真正的 view
比使用相同的数据缓冲区,但对其应用不同的形状、步幅或 dtype。
要从 [1,2,3,4]
得到 [2, 4, 3, 1]
需要从 2
开始,向前跳 2,然后跳回到 1 和向前跳 2。这不是可以表示的常规模式strides
.
arr[1::2]
给出 [2,4],arr[0::2]
给出 [1,3]
.
(U, V, S, T)
到 (U*S, V*T)
需要转置到 (U, S, V, T)
,然后再整形
arr.transpose(0,2,1,3).reshape(U*S, V*T)
那将需要一份副本,没有办法。
In [227]: arr = np.arange(2*3*4*5).reshape(2,3,4,5)
In [230]: arr1 = arr.transpose(0,2,1,3).reshape(2*4, 3*5)
In [231]: arr1.shape
Out[231]: (8, 15)
In [232]: arr1
Out[232]:
array([[ 0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 40, 41, 42,
43, 44],
[ 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 45, 46, 47,
48, 49],
....)
或者用你的x
In [234]: x1 = x.transpose(0,2,1,3).reshape(4,4)
In [235]: x1
Out[235]:
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
请注意元素的顺序不同:
In [254]: x.ravel()
Out[254]: array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4])
In [255]: x1.ravel()
Out[255]: array([1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 4, 4])
ndarray.sort
就地改变了数据缓冲区中字节的顺序。它在我们无法访问的低级别运行。它不是原始数组的 view
。