了解ndarray形状

时间:2017-07-13 18:09:41

标签: python arrays numpy shape

我是numpy的新手,我很难理解阵列的形状是如何决定的。 形式的数组

[[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4,3]] 

的形状为(2,),而其中一种形式为

[[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4]] 

具有(2,3)的形状。而且,

[[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [[1,2,4], [3,4,2]]] 

的形状为(2,),但添加另一个矢量为

[[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [[1,2,4], [3,4,2], [1,2,4]]] 

将形状更改为(2,3,3)。直觉上,我觉得所有阵列都应该是三维的。谁能帮我理解究竟发生了什么?

1 个答案:

答案 0 :(得分:3)

基本思想是np.array尝试创建尽可能高的维数组。当子列表具有匹配的元素数量时,结果很容易看到。当他们混合不同长度的列表时,结果可能会令人困惑。

在第一种情况下,你有2个子列表,一个长度为3,另一个长度为4.因此它生成一个2元素对象数组,并且不会尝试解析第一个子列表的子列表

In [1]: arr = np.array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4,3]])
In [2]: arr
Out[2]: array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], 
               [1, 2, 4, 3]
              ], dtype=object)   # adjusted format
In [3]: arr.dtype
Out[3]: dtype('O')
In [4]: arr.shape
Out[4]: (2,)
In [5]: arr[0]
Out[5]: [[5, 10, 15], [20, 25, 30], [35, 40, 45]] # 3 element list of lists
In [6]: arr[1]
Out[6]: [1, 2, 4, 3]  # 4 element list of numbers

在第二种情况下,您有两个长度为3的子列表。因此它生成一个2x3阵列。但是一个子列表包含列表,其他数字 - 所以结果又是对象数组:

In [7]: arr = np.array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4]] )
In [8]: arr
Out[8]: 
array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]],
       [1, 2, 4]
      ], dtype=object)
In [9]: arr.shape
Out[9]: (2, 3)
In [10]: arr[0,0]
Out[10]: [5, 10, 15]

最后,有2个列表,每个列表包含3个元素,每个元素也是3个元素列表 - 一个3d数组。

In [11]: arr = np.array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [[1,2,4], [3,4,2], [1,2,4]]] )
In [12]: arr
Out[12]: 
array([[[ 5, 10, 15],
        [20, 25, 30],
        [35, 40, 45]],

       [[ 1,  2,  4],
        [ 3,  4,  2],
        [ 1,  2,  4]]])
In [13]: arr.shape
Out[13]: (2, 3, 3)

还有一些子列表长度混合可能引发错误。

一般情况下,不要随意混合不同大小和内容类型的子列表。当给定列表产生一个漂亮的多维数组时,np.array的行为最为可预测。混合列表长度会导致混淆。

更新了numpy:

In [1]: np.__version__
Out[1]: '1.13.1'
In [2]: np.array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4,3]])
Out[2]: array([list([[5, 10, 15], [20, 25, 30], [35, 40, 45]]), list([1, 2, 4, 3])], dtype=object)

In [3]: np.array([[[5, 10, 15], [20, 25, 30], [35, 40, 45]], [1,2,4]] )
Out[3]: 
array([[list([5, 10, 15]), list([20, 25, 30]), list([35, 40, 45])],
       [1, 2, 4]], dtype=object)

现在识别list元素

这最后一个例子仍然是(2,3)对象数组。因此,这6个元素中的每一个都可以是不同的Python类型,例如:

In [11]: np.array([[[5, 10, 15], np.array([20, 25, 30]), (35, 40, 45)], [None,2,'astr']] )
Out[11]: 
array([[list([5, 10, 15]), array([20, 25, 30]), (35, 40, 45)],
       [None, 2, 'astr']], dtype=object)
In [12]: [type(x) for x in _.flat]
Out[12]: [list, numpy.ndarray, tuple, NoneType, int, str]