到目前为止,我们已经尝试过用索引和切片方法从数组中选择或抽取一部分元素。这些方法使用数值形式的索引。另外一种从数组中有选择性地抽取元素的方法是使用条件表达式和布尔运算符。
我们来详细看一下这种方法。
例如,你想从由0到1之间的随机数组成的4×4型矩阵中选取所有小于0.5的元素。
>>> import numpy as np
>>> A=np.random.random((4,4))
>>> A
array([[0.26288902, 0.91378047, 0.05893288, 0.53372499],
[0.72051782, 0.93821126, 0.2717436 , 0.01271198],
[0.60817428, 0.67697924, 0.46701427, 0.36443741],
[0.40490635, 0.127423 , 0.13512739, 0.91059487]])
>>>
创建随机数矩阵后,如果使用表示条件的运算符,
比如这里的小于号,你将会得到由布尔值组成的数组。
对于原数组中条件满足的元素,布尔数组中处于同等位置(也就是小于0.5的元素所处的位置)的元素为True.
>>> A<0.5
array([[ True, False, True, False],
[False, False, True, True],
[False, False, True, True],
[ True, True, True, False]])
>>>
实际上,从数组中选取一部分元素时,隐式地用到了布尔数组。
其实,直接把条件表达式置于方括号中,也能抽取所有小于0.5的元素,组成一个新数组。
>>> A[A<0.5]
array([0.26288902, 0.05893288, 0.2717436 , 0.01271198, 0.46701427,
0.36443741, 0.40490635, 0.127423 , 0.13512739])
>>>
创建二维数组时,你已经见过用 reshape()函数把一维数组转换为矩阵。
>>> a=np.random.random(12)
>>> a
array([0.02374194, 0.41772368, 0.42033455, 0.70119921, 0.35049738,
0.39545048, 0.55200348, 0.35408728, 0.19674586, 0.96499994,
0.91922038, 0.7985178 ])
>>> A=a.reshape(3,4)
>>> A
array([[0.02374194, 0.41772368, 0.42033455, 0.70119921],
[0.35049738, 0.39545048, 0.55200348, 0.35408728],
[0.19674586, 0.96499994, 0.91922038, 0.7985178 ]])
reshape()函数返回一个新数组,因而可用来创建新对象。
然而,如果想通过改变数组的形状来改变数组对象,需把表示新形状的元组直接赋给数组的 shape属性。
>>> a.shape=(3,4)
>>> a
array([[0.02374194, 0.41772368, 0.42033455, 0.70119921],
[0.35049738, 0.39545048, 0.55200348, 0.35408728],
[0.19674586, 0.96499994, 0.91922038, 0.7985178 ]])
>>>
由输出结果来看,上述操作改变了原始数组的形状,而没有返回新对象。
改变数组形状的操作是可逆的, ravel()函数可以把二维数组再变回一维数组。
>>> a=a.ravel()
>>> a
array([0.02374194, 0.41772368, 0.42033455, 0.70119921, 0.35049738,
0.39545048, 0.55200348, 0.35408728, 0.19674586, 0.96499994,
0.91922038, 0.7985178 ])
>>>
甚至直接改变数组 shape属性的值也可以。
>>> a.shape=(12)
>>> a
array([0.02374194, 0.41772368, 0.42033455, 0.70119921, 0.35049738,
0.39545048, 0.55200348, 0.35408728, 0.19674586, 0.96499994,
0.91922038, 0.7985178 ])
另外一种重要的运算是交换行列位置的矩阵转置。 NumPy的 transpose()函数实现了该功能。
>>> A.transpose()
array([[0.02374194, 0.35049738, 0.19674586],
[0.41772368, 0.39545048, 0.96499994],
[0.42033455, 0.55200348, 0.91922038],
[0.70119921, 0.35408728, 0.7985178 ]])
>>>
往往需要用已有数组创建新数组,这里学习一下如何通过连接或切分已有数组创建新数组
你可以把多个数组整合在一起形成一个包含这些数组的新数组。
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.]])
>>>
另外另个用于多个数组之间栈操作的函数是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]])
>>>
上面讲了使用栈操作把多个数组组装到一起的方法。接下来看一下它的逆操作:把一个数组分为几部分。在 NumPy中,该操作要用到切分方法。
同理,我们也有一组函数,水平切分用 hsplit()函数,垂直切分用 vsplit()函数。
>>> 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]])
水平切分数组的意思是把数组按照宽度切分为两部分,例如4×4矩阵将被切分为两个4×2矩阵。
>>> [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]])
>>>
反之,垂直切分指的是把数组按照高度分为两部分,如4×4矩阵将被切为两个2×4矩阵
>>> [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()函数更为复杂,可以把数组分为几个不对称的部分。此外,除了传入数组作为参数外,还得指定被切分部分的索引。
如果指定axis=1,索引为列索引;
如果axis=0,索引为行索引
例如,要把矩阵切分为三部分,第一部分为第一列,第二部分为第二列、第三列,而第三部
分为最后一列。你需要像下面这样指定索引值。
>>> [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]])
>>> A#
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> A3
array([[ 3],
[ 7],
[11],
[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]])
>>>
split()函数还具有 vsplit()函数和 hsplit()函数的功能