左滑查看目录



nparray索引 numpy 索引_NumPy

nparray索引 numpy 索引_nparray索引_02

nparray索引 numpy 索引_NumPy

nparray索引 numpy 索引_nparray索引_02

形状操纵


我们在创建二维数组的过程中,借助 reshape() 函数,将一维数组转换为矩阵 。

>>> a = np.random.random(12)>>> aarray([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,        0.41894881,  0.73581471])>>> A = a.reshape(3, 4)>>> Aarray([[ 0.77841574,  0.39654203,  0.38188665,  0.26704305],       [ 0.27519705,  0.78115866,  0.96019214,  0.59328414],       [ 0.52008642,  0.10862692,  0.41894881,  0.73581471]])
>>> a = np.random.random(12)
>>> a
array([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,
        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,
        0.41894881,  0.73581471])
>>> A = a.reshape(3, 4)
>>> A
array([[ 0.77841574,  0.39654203,  0.38188665,  0.26704305],
       [ 0.27519705,  0.78115866,  0.96019214,  0.59328414],
       [ 0.52008642,  0.10862692,  0.41894881,  0.73581471]])


reshape() 函数返回一个新的数组,因此可以创建新对象。但是,如果要通过修改形状来修改对象,则必须将包含新尺寸的元组直接分配给它的 形状 attribute。

>>> a.shape = (3, 4)>>> aarray([[ 0.77841574,  0.39654203,  0.38188665,  0.26704305],       [ 0.27519705,  0.78115866,  0.96019214,  0.59328414],       [ 0.52008642,  0.10862692,  0.41894881,  0.73581471]])
>>> a.shape = (3, 4)
>>> a
array([[ 0.77841574,  0.39654203,  0.38188665,  0.26704305],
       [ 0.27519705,  0.78115866,  0.96019214,  0.59328414],
       [ 0.52008642,  0.10862692,  0.41894881,  0.73581471]])


这次是改变形状的起始数组,并且没有返回对象。逆运算也是可能的,即,您可以使用 ravel() 函数将二维数组转换为一维数组。

>>> a = a.ravel()array([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,        0.41894881,  0.73581471])
>>> a = a.ravel()
array([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,
        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,
        0.41894881,  0.73581471])


甚至在这里直接作用于数组本身的 shape 属性。

>>> a.shape = (12)>>> aarray([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,        0.41894881,  0.73581471])
>>> a.shape = (12)
>>> a
array([ 0.77841574,  0.39654203,  0.38188665,  0.26704305,  0.27519705,
        0.78115866,  0.96019214,  0.59328414,  0.52008642,  0.10862692,
        0.41894881,  0.73581471])


另一个重要的操作是转置矩阵,该矩阵将列与行反转。NumPy启用了 transpose() 函数即可提供此功能 。

>>> A.transpose()array([[ 0.77841574,  0.27519705,  0.52008642],       [ 0.39654203,  0.78115866,  0.10862692],       [ 0.38188665,  0.96019214,  0.41894881],       [ 0.26704305,  0.59328414,  0.73581471]])
>>> A.transpose()
array([[ 0.77841574,  0.27519705,  0.52008642],
       [ 0.39654203,  0.78115866,  0.10862692],
       [ 0.38188665,  0.96019214,  0.41894881],
       [ 0.26704305,  0.59328414,  0.73581471]])

阵列操作


通常,我们需要使用已创建的数组再创建一个数组。  下面,你将看到如何通过联接或拆分已定义的数组来创建新数组。

连接数组


可以合并多个阵列以形成一个包含所有阵列的新阵列。NumPy使用 堆栈

的概念,为此提供了许多功能。  例如,可以使用 vstack() 函数执行垂直堆栈,该函数将第二个数组合并为第一个数组的新行。  在这种情况下,阵列沿垂直方向生长。  相比之下, hstack() 函数执行水平堆叠。也就是说,第二个数组将添加到第一个数组的列中。

>>> A = np.ones((3, 3))>>> B = np.zeros((3, 3))>>> np.vstack((A, B))array([[ 1.,  1.,  1.],       [ 1.,  1.,  1.],       [ 1.,  1.,  1.],       [ 0.,  0.,  0.],       [ 0.,  0.,  0.],       [ 0.,  0.,  0.]])>>> np.hstack((A,B))array([[ 1.,  1.,  1.,  0.,  0.,  0.],       [ 1.,  1.,  1.,  0.,  0.,  0.],       [ 1.,  1.,  1.,  0.,  0.,  0.]])
>>> A = np.ones((3, 3))
>>> B = np.zeros((3, 3))
>>> np.vstack((A, B))
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
>>> np.hstack((A,B))
array([[ 1.,  1.,  1.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.,  0.]])


另外两个函数的多个阵列之间进行堆叠是 column_stack() 一个 第二 row_stack()   。这些功能与之前的两个功能不同。通常,这些功能与一维数组一起使用,这些维数组按列或行堆叠以形成新的二维数组。

>>> a = np.array([0, 1, 2])>>> b = np.array([3, 4, 5])>>> c = np.array([6, 7, 8])>>> np.column_stack((a, b, c))array([[0, 3, 6],       [1, 4, 7],       [2, 5, 8]])>>> np.row_stack((a, b, c))array([[0, 1, 2],       [3, 4, 5],        [6, 7, 8]])
>>> a = np.array([0, 1, 2])
>>> b = np.array([3, 4, 5])
>>> c = np.array([6, 7, 8])
>>> np.column_stack((a, b, c))
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])
>>> np.row_stack((a, b, c))
array([[0, 1, 2],
       [3, 4, 5],
        [6, 7, 8]])

分割阵列


在上面,我们了解了如何通过堆叠组装多个阵列。现在,我们将学习如何将数组分为几个部分。在NumPy中,我们可以使用拆分来执行此操作。这里也一样,我们有一组功能的工作水平都与 hsplit()  函数和垂直与 vsplit()  函数。

>>> A = np.arange(16).reshape((4, 4))>>> Aarray([[ 0,  1,  2,  3],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11],       [12, 13, 14, 15]])
>>> A = np.arange(16).reshape((4, 4))
>>> A
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])


因此,如果要水平拆分数组,这意味着将数组的宽度分为两部分,则4x4矩阵A将被拆分为两个2x4矩阵。

>>> [B,C] = np.hsplit(A, 2)>>> Barray([[ 0,  1],       [ 4,  5],       [ 8,  9],       [12, 13]])>>> Carray([[ 2,  3],       [ 6,  7],       [10, 11],       [14, 15]])
>>> [B,C] = np.hsplit(A, 2)
>>> B
array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]])
>>> C
array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])


相反,如果要垂直拆分数组,这意味着将数组的高度分为两部分,则4x4矩阵A将拆分为两个4x2矩阵。

>>> [B,C] = np.vsplit(A, 2)>>> Barray([[0, 1, 2, 3],       [4, 5, 6, 7]])>>> Carray([[ 8,  9, 10, 11],       [12, 13, 14, 15]])
>>> [B,C] = np.vsplit(A, 2)
>>> B
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])
>>> C
array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])


一个更复杂的命令是 split() 函数,该函数允许您将数组拆分为非对称部分。将数组作为参数传递时,还必须指定要分割的零件的索引。  如果使用option  axis = 1 ,则索引将是列;否则,索引将是列。  相反,如果选项是 axis = 0 ,那么它们将是行索引。  例如,如果要将矩阵分为三个部分,其中第一部分将包括第一列,第二部分将包括第二和第三列,第三部分将包括最后一列,则必须在中指定三个索引以下方式。

>>> [A1,A2,A3] = np.split(A,[1,3],axis=1)>>> A1array([[ 0],       [ 4],       [ 8],       [12]])>>> A2array([[ 1,  2],       [ 5,  6],       [ 9, 10],       [13, 14]])>>> A3array([[ 3],       [ 7],       [11],       [15]])
>>> [A1,A2,A3] = np.split(A,[1,3],axis=1)
>>> A1
array([[ 0],
       [ 4],
       [ 8],
       [12]])
>>> A2
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10],
       [13, 14]])
>>> A3
array([[ 3],
       [ 7],
       [11],
       [15]])


你也可以逐行执行相同的操作。

>>> [A1,A2,A3] = np.split(A,[1,3],axis=0)>>> A1array([[0, 1, 2, 3]])>>> A2array([[ 4,  5,  6,  7],       [ 8,  9, 10, 11]])>>> A3array([[12, 13, 14, 15]])
>>> [A1,A2,A3] = np.split(A,[1,3],axis=0)
>>> A1
array([[0, 1, 2, 3]])
>>> A2
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> A3
array([[12, 13, 14, 15]])


该特征还包括functionaliti 所述的 vsplit() 和 hsplit() 函数。

Numpy的一般概念


下面内容描述了NumPy库的基本概念。副本和视图之间的区别在于它们返回值的时间。本节还介绍了在许多NumPy函数中隐式发生的广播机制。


对象的副本或视图


稍微细心一点,你在使用NumPy时就会发现,在处理数组时,你可以返回数组的副本或视图。  Numpy分配均不产生数组的副本,也不包含其中的任何元素。

>>> a = np.array([1, 2, 3, 4])>>> b = a>>> barray([1, 2, 3, 4])>>> a[2] = 0>>> barray([1, 2, 0, 4])
>>> a = np.array([1, 2, 3, 4])
>>> b = a
>>> b
array([1, 2, 3, 4])
>>> a[2] = 0
>>> b
array([1, 2, 0, 4])


如果将一个数组 a 分配给另一个数组 b ,则不是要复制它。数组 b 只是调用数组 a的 另一种方法。实际上,通过更改第三个元素的值,您也可以更改 b 的第三个值。切片数组时,返回的对象是原始数组的视图。

>>> c = a[0:2]>>> carray([1, 2])>>> a[0] = 0>>> carray([0, 2])
>>> c = a[0:2]
>>> c
array([1, 2])
>>> a[0] = 0
>>> c
array([0, 2])


如上,即使在切片时,实际上也指向同一对象。如果要生成完整且独特的数组,请使用 copy() 函数。

>>> a = np.array([1, 2, 3, 4])>>> c = a.copy()>>> carray([1, 2, 3, 4])>>> a[0] = 0>>> carray([1, 2, 3, 4])
>>> a = np.array([1, 2, 3, 4])
>>> c = a.copy()
>>> c
array([1, 2, 3, 4])
>>> a[0] = 0
>>> c
array([1, 2, 3, 4])


在这种情况下,即使更改 数组 a中的项目 ,数组 c 仍保持不变。

向量化


Vectoriz ation和广播是NumPy内部实现的基础。 矢量化是指在开发代码的过程中没有明确的循环。 这些循环实际上是不能省略的,而是在内部实现,然后在代码中被其他构造所取代。 矢量化的应用使得代码更加简洁易读,可以说在外观上会显得更加 "Pythonic"。事实上,得益于向量化,很多操作都有了更加数学化的表达方式。 例如,NumPy允许你表达两个数组的乘法,如下所示: a * b 甚至两个矩阵: A * B 在其他语言中,此类操作将通过许多嵌套循环和 for 构造来表达。例如,第一个操作将以以下方式表示:

for (i = 0; i c[i] = a[i]*b[i];}
for (i = 0; i c[i] = a[i]*b[i];}


矩阵的乘积表示如下:

for(i = 0; i for(j = 0; j c [i] [j] = a [i] [j] * b [i] [j];}
for(i = 0; i for(j = 0; j c [i] [j] = a [i] [j] * b [i] [j];}