获取数字数组或异常的平面视图数组、视图、平面、异常

2023-09-04 01:52:48 作者:爱不单行

This question及其答案...

ReShape((-1,))只要数组的跨度允许,就获取一个视图,即使这意味着您不总是获得连续的数组。

LeetCode 数组中出现次数超过一半的数字 Python

.提出了另一个问题:假设我有一个具有任何可以想象的形状和内存布局的n维数值数组,我如何获得它的有保证的平面化视图,或者如果它不是视图,我如何获得有保证的异常?

推荐答案

我在想这张纸条。它可以转换为函数

It is not always possible to change the shape of an array without copying the data. If you want an error to be raised when the data is copied, you should assign the new shape to the shape attribute of the array:

a = np.zeros((10, 2))

# A transpose makes the array non-contiguous
b = a.T

# Taking a view makes it possible to modify the shape without modifying
# the initial object.
c = b.view()
c.shape = (20)
Traceback (most recent call last):
   ...
AttributeError: Incompatible shape for in-place modification. Use
`.reshape()` to make a copy with the desired shape.

糟糕,我看到删除的答案中引用了这一点。

编辑

我们来探索一下

In [17]: x = np.arange(24).reshape(2, 3, 4)
In [18]: x
Out[18]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
In [19]: x.ravel()
Out[19]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])
In [20]: x.T
Out[20]: 
array([[[ 0, 12],
        [ 4, 16],
        [ 8, 20]],
   ...
       [[ 3, 15],
        [ 7, 19],
        [11, 23]]])
转置的默认顺序‘C’Ravel产生与碱基aranage不同的序列。很明显这是一份复制品。

In [21]: x.T.ravel()
Out[21]: 
array([ 0, 12,  4, 16,  8, 20,  1, 13,  5, 17,  9, 21,  2, 14,  6, 18, 10,
       22,  3, 15,  7, 19, 11, 23])

但"F"顺序是相同的-它是一个视图

In [22]: x.T.ravel(order='F')
Out[22]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])

让我们尝试一个列切片:

In [23]: x[:, 2:]
Out[23]: 
array([[[ 8,  9, 10, 11]],

       [[20, 21, 22, 23]]])
In [24]: _.strides            # same as x
Out[24]: (96, 32, 8)
In [25]: __.ravel()
Out[25]: array([ 8,  9, 10, 11, 20, 21, 22, 23])
In [26]: x.strides
Out[26]: (96, 32, 8)

Ravel不是初始arange的&q;常规&q;子集。这是副本。

shares_memory证实了我的观察:

In [27]: np.shares_memory(x, Out[22])
Out[27]: True
In [28]: np.shares_memory(x, Out[21])
Out[28]: False
In [29]: np.shares_memory(x, Out[25])
Out[29]: False

让我们试试引语中提出的技巧:

In [30]: c = Out[23].view()
In [31]: c
Out[31]: 
array([[[ 8,  9, 10, 11]],

       [[20, 21, 22, 23]]])
In [32]: c.size
Out[32]: 8
In [34]: c.shape = (8,)
Traceback (most recent call last):
  Input In [34] in <module>
    c.shape = (8,)
AttributeError: Incompatible shape for in-place modification. Use `.reshape()` to make a copy with the desired shape.
像[34]中那样尝试设置shape仅适用于兼容的视图。它从不复制。