【问题标题】:Creating a non trivial view of numpy array创建 numpy 数组的重要视图
【发布时间】:2018-05-24 17:37:31
【问题描述】:

TL;DR:

我正在寻找一种方法来获得 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,即简单的 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 + sb = v * T + t 的索引方案,在本例中为S = 2 = T

我尝试过的

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

  2. 由于我知道索引方案,我尝试使用np.ravel() 对数组的平面视图进行操作。我的想法是按照所需的索引方案创建一个索引数组并将其应用于展平的数组视图,但不幸的是,花式/高级索引提供了数组的副本,而不是视图。

问题

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

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

【问题讨论】:

    标签: python arrays numpy numpy-ndarray


    【解决方案1】:

    让我们回顾一下数组的基础知识 - 它有一个平面数据缓冲区、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

    【讨论】:

    • 好的,谢谢。我明白了。我认为也许有可能创建一个具有非恒定步幅的索引方案......
    猜你喜欢
    • 1970-01-01
    • 2014-01-27
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多