我正在寻找一种方法来获得一个非平凡的,尤其是非连续的,看似numpy ndarray
。
,如果给出1D ndarray,x = np.array([1, 2, 3, 4])
,有没有办法获得它的非平凡视图,例如np.array([2, 4, 3, 1])
?
问题的背景如下:我有一个形状(U, V, S, T)
的4D ndarray,我想以非平凡的方式重塑为形状(U*S, V*T)
的2D ndarray,即a简单的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()
对数组的展平视图进行操作。我的想法是在所需的索引方案之后创建一个索引数组并将其应用于展平的数组视图,但不幸的是,花式/高级索引提供了数组的副本,而不是视图。
有没有办法实现我正在寻找的索引视图?
原则上,我认为这应该是可能的,例如ndarray.sort()
执行数组的非平凡索引。另一方面,这可能是用C / C ++实现的,所以在纯Python中甚至可能无法实现?
答案 0 :(得分:1)
让我们回顾一下数组的基础知识 - 它有一个平面数据缓冲区,shape
,strides
和dtype
。这三个属性以特定的方式用于view
数据缓冲区的元素,无论是简单的1d序列,2d还是更高的维度。
真实view
比使用相同的数据缓冲区,但对其应用不同的形状,步幅或dtype。
要从[2, 4, 3, 1]
获取[1,2,3,4]
,需要从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
。