第一章
(1) 创建一个多维数组。
(2) 显示该数组的维度。
In: m = array([arange(2), arange(2)])
In: m
Out: array([[0, 1],
[0, 1]])
In: m.shape
Out: (2, 2)
索引元素:
In: a[0,0]
Out: 1
In: a[0,1]
Out: 2
nunpy数据类型:
定义类型:
In: arange(7, dtype=uint16)
Out: array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)
数据类型对象是numpy.dtype类的实例。如前所述,NumPy数组是有数据类型的,更确切 地说,NumPy数组中的每一个元素均为相同的数据类型。数据类型对象可以给出单个数组元素在 内存中占用的字节数,即dtype类的itemsize属性
In: a.dtype.itemsize
Out: 8
2.2.4 字符编码
NumPy可以使用字符编码来表示数据类型,这是为了兼容NumPy的前身Numeric。我不推荐 使用字符编码,但有时会用到,因此下面还是列出了字符编码的对应表。读者应该优先使用dtype 对象来表示数据类型,而不是这些字符编码
下面的代码创建了一个单精度浮点数数组:
In: arange(7, dtype='f')
Out: array([ 0., 1., 2., 3., 4., 5., 6.], dtype=float32])
2.4 一维数组的索引和切片
一维数组的切片操作与Python列表的切片操作很相似。例如,我们可以用下标3~7来选取元 素3~6:
In: a = arange(9)
In: a[3:7]
Out: array([3, 4, 5, 6])
#也可以用下标0~7,以2为步长选取元素:
In: a[:7:2] Out: array([0, 2, 4, 6])
#和Python中一样,我们也可以利用负数下标翻转数组:
In: a[::-1]
Out: array([8, 7, 6, 5, 4, 3, 2, 1, 0])
2.5 多维数组的切片和索引
ndarray支持在多维数组上的切片操作。为了方便起见,我们可以用一个省略号(…)来 表示遍历剩下的维度。
(1) 举例来说,我们先用arange函数创建一个数组并改变其维度,使之变成一个三维数组
In: b = arange(24).reshape(2,3,4)
In: b.shape
Out: (2, 3, 4)
In: b
Out: 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]]])
(2) 我们可以用三维坐标来选定任意一个房间
In: b[0,0,0]
Out: 0
(3) 如果我们不关心楼层,也就是说要选取所有楼层的第1行、第1列的房间,那么可以将第1 个下标用英文标点的冒号:来代替:
In: b[:,0,0] Out: array([ 0, 12])
In: b[0]
Out: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9,10,11]])
我们还可以这样写,选取第1层楼的所有房间:
In: b[0, :, :]
Out: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9,10,11]])
多个冒号可以用一个省略号(…)来代替,因此上面的代码等价于:
In: b[0, ...]
Out: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
进而可以选取第1层楼、第2排的所有房间:
In: b[0,1] Out: array([4, 5, 6, 7])
(4) 再进一步,我们可以在上面的数组切片中间隔地选定元素:
In: b[0,1,::2] Out: array([4, 6])
(5) 如果要选取所有楼层的位于第2列的房间,即不指定楼层和行号,用如下代码即可:
In: b[...,1]
Out: array([[ 1, 5, 9], [13,17,21]])
类似地,我们可以选取所有位于第2行的房间,而不指定楼层和列号
In: b[:,1]
Out: array([[ 4, 5, 6, 7], [16,17,18,19]])
如果要选取第1层楼的所有位于第2列的房间,在对应的两个维度上指定即可:
In: b[0,:,1]
Out: array([1, 5, 9])
(6) 如果要选取第1层楼的后一列的所有房间,使用如下代码:
In: b[0,:,-1]
Out: array([ 3, 7, 11])
如果要反向选取第1层楼的后一列的所有房间,使用如下代码:
In: b[0,::-1, -1]
Out: array([11, 7, 3])
在该数组切片中间隔地选定元素:
In: b[0,::2,-1]
Out: array([ 3, 11])
如果在多维数组中执行翻转一维数组的命令,将在前面的维度上翻转元素的顺序,在我们 的例子中将把第1层楼和第2层楼的房间交换:
In: b[::-1]
Out: array([[[12,13,14,15], [16,17,18,19], [20,21,22,23], [[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9,10,11]]])
2.6 动手实践:改变数组的维度
(1) ravel 我们可以用ravel函数完成展平的操作:
In: b
Out: 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: b.ravel()
Out: 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])
(2) flatten 这个函数恰如其名,flatten就是展平的意思,与ravel函数的功能相同。 不过,flatten函数会请求分配内存来保存结果,而ravel函数只是返回数组的一个视图(view):
In: b.flatten()
Out: 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])
(3) 用元组设置维度除了可以使用reshape函数,我们也可以直接用一个正整数元组来设 置数组的维度,如下所示:
In: b.shape = (6,4)
In: b
Out: 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]],
正如你所看到的,这样的做法将直接改变所操作的数组,现在数组b成了一个6×4的多维数组。
(4) transpose 在线性代数中,转置矩阵是很常见的操作。对于多维数组,我们也可以这样做:
In: b.transpose()
Out: array([[ 0, 4, 8, 12, 16, 20], [ 1, 5, 9, 13, 17, 21], [ 2, 6,10, 14, 18, 22], [ 3, 7,11, 15, 19, 23]])
(5) resize resize和reshape函数的功能一样,但resize会直接修改所操作的数组:
In: b.resize((2,12))
In: b
Out: 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]])
2.7 数组的组合
NumPy数组有水平组合、垂直组合和深度组合等多种组合方式,我们将使用vstack、 dstack、hstack、column_stack、row_stack以及concatenate函数来完成数组的组合
首先,我们来创建一些数组:
In: a = arange(9).reshape(3,3)
In: a
Out: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
In: b = 2 * a
In: b
Out: array([[ 0, 2, 4], [ 6, 8, 10], [12, 14,16]])
(1) 水平组合 我们先从水平组合开始练习。将ndarray对象构成的元组作为参数,传给hstack函数。如下所示:
In: hstack((a, b))
Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8,10], [ 6, 7, 8,12,14,16]])
我们也可以用concatenate函数来实现同样的效果,如下所示:
In: concatenate((a, b), axis=1)
Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8,10], [ 6, 7, 8,12,14,16]])
(2) 垂直组合 垂直组合同样需要构造一个元组作为参数,只不过这次的函数变成了 vstack。如下所示:
In: vstack((a, b))
Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8,10], [12,14,16]])
同样,我们将concatenate函数的axis参数设置为0即可实现同样的效果。这也是axis参 数的默认值:
In: concatenatel((a, b), axis = 0)
Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8,10], [12,14,16]])
(3) 深度组合 将相同的元组作为参数传给dstack函数,即可完成数组的深度组合。所谓 深度组合,就是将一系列数组沿着纵轴(深度)方向进行层叠组合。举个例子,有若干张二维平 面内的图像点阵数据,我们可以将这些图像数据沿纵轴方向层叠在一起,这就形象地解释了什么 是深度组合。
In: dstack((a, b))
Out: array([[[0, 0], [1, 2], [2, 4]], [[3, 6], [4, 8], [5,10]], [[6,12], [7,14], [8,16]]])
(4) 列组合 column_stack函数对于一维数组将按列方向进行组合,如下所示:
In: oned = arange(2)
In: oned
Out: array([0, 1])
In: twice_oned = 2 * oned
In: twice_oned
Out: array([0, 2])
In: column_stack((oned, twice_oned))
Out: array([[0, 0], [1, 2]])
而对于二维数组,column_stack与hstack的效果是相同的:
In: column_stack((a, b))
Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8,10], [ 6, 7, 8,12,14,16]])
In: column_stack((a, b)) == hstack((a, b))
Out: array([[ True, True, True, True, True, True], [ True, True, True, True, True, True], [ True, True, True, True, True, True]], dtype=bool)
是的,你猜对了!我们可以用==运算符来比较两个NumPy数组,是不是很简洁?
(5) 行组合 当然,NumPy中也有按行方向进行组合的函数,它就是row_stack。对于两 个一维数组,将直接层叠起来组合成一个二维数组。
In: row_stack((oned, twice_oned)) Out: array([[0, 1], [0, 2]])
对于二维数组,row_stack与vstack的效果是相同的:
In: row_stack((a, b))
Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8,10], [12,14,16]])
In: row_stack((a,b)) == vstack((a, b))
Out: array([[ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True]], dtype=bool)
2.9 数组的分割
NumPy数组可以进行水平、垂直或深度分割,相关的函数有hsplit、vsplit、dsplit和 split。我们可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置。
(1) 水平分割 下面的代码将把数组沿着水平方向分割为3个相同大小的子数组:
In: a
Out: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
In: hsplit(a, 3)
Out: [array([[0], [3], [6]]), array ([[1], [4], [7]]), array ([[2], [5], [8]])]
对同样的数组,调用split函数并在参数中指定参数axis=1,对比一下结果:
In: split(a, 3, axis=1)
Out: [array([[0], [3], [6]]), array ([[1], [4], [7]]), array ([[2], [5], [8]])]
(2) 垂直分割 vsplit函数将把数组沿着垂直方向分割:
In: vsplit(a, 3)
Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
同样,调用split函数并在参数中指定参数axis=0,也可以得到同样的结果:
```python
In: split(a, 3, axis=0)
Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
(3) 深度分割 不出所料,dsplit函数将按深度方向分割数组。我们先创建一个三维数组:
In: c = arange(27).reshape(3, 3, 3)
In: c
Out: 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], [24,25,26]]])
In: dsplit(c, 3)
Out: [array([[[ 0], [ 3], [ 6]], [[ 9], [12], [15]], [[18], [21], [24]]]), array([[[ 1], [ 4], [ 7]], [[10], [13], [16]], [[19], [22], [25]]]), array([[[ 2], [ 5], [ 8]], [[11], [14], [17]], [[20], [23], [26]]])]