创建numpy数组的非平凡视图

2024-04-19 14:35:54 发布

您现在位置:Python中文网/ 问答频道 /正文

TL;DR:

我正在寻找一种方法来获得一个numpyndarray的非琐碎的,特别是非连续的视图。你知道吗

例如,给定一个一维数组x = np.array([1, 2, 3, 4]),有没有一种方法可以得到一个非平凡的视图,例如np.array([2, 4, 3, 1])?你知道吗

加长版

问题的上下文如下:我有一个形状(U, V, S, T)的4D数组,我想以一种非平凡的方式将其重塑为形状(U*S, V*T)的2D数组,即一个简单的np.reshape()不起作用,因为我想到了一个更复杂的索引方案,在这个方案中,重塑后的数组在内存中不会是连续的。我的例子中的数组相当大,我希望得到一个视图,而不是数组的副本。你知道吗

示例

给定形状为(2, 2, 2, 2)的数组x(u, v, s, t)

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 + sb = v * T + t的索引方案,在本例中S = 2 = T。你知道吗

我试过的

  1. 使用np.reshape甚至as_strided的各种方法。执行标准重塑不会改变元素在内存中出现的顺序。我试着玩order='F'和转置一点,但不知道哪个给了我正确的结果。

  2. 因为我知道索引方案,所以我尝试使用np.ravel()操作数组的扁平视图。我的想法是按照所需的索引方案创建一个索引数组,并将其应用于展平的数组视图,但不幸的是,fancy/advanced indexing提供了数组的副本,而不是视图。

问题

有没有什么方法可以实现我正在寻找的索引视图?你知道吗

原则上,我认为这应该是可能的,例如ndarray.sort()执行数组的就地非平凡索引。另一方面,这可能是在C/C++中实现的,所以在纯Python中甚至可能不可能实现。你知道吗


Tags: 方法内存视图np副本方案数组array
1条回答
网友
1楼 · 发布于 2024-04-19 14:35:54

让我们回顾一下数组的基础知识—它有一个平面数据缓冲区、一个shapestridesdtype。这三个属性用于以特定的方式view数据缓冲区的元素,无论它是简单的一维序列、二维序列还是更高维序列。你知道吗

一个真正的view不是使用相同的数据缓冲区,而是对其应用不同的形状、步长或数据类型。你知道吗

要从[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。你知道吗

相关问题 更多 >