《Python数据分析基础教程:NumPy学习指南(第2版)》笔记3:第二章 NumPy基础2——数组的索引和切片、改变数组维度

第二章 NumPy基础2

本章示例代码中的输入和输出均来自IPython会话。

2.4 一维数组的索引和切片

一维数组的切片操作与Python列表的切片操作很相似。例如,我们可以用下标3~7来选取元素3~6

In [27]: a = np.arange(9)
In [28]: a[3:7]
Out[28]: array([3, 4, 5, 6])

也可以用下标0~7,以2为步长选取元素:

In [29]: a[:7:2]
Out[29]: array([0, 2, 4, 6])

和Python中一样,我们也可以利用负数下标翻转数组:

In [30]: a[::-1]
Out[30]: array([8, 7, 6, 5, 4, 3, 2, 1, 0])

2.5 动手实践:多维数组的切片和索引

ndarray支持在多维数组上的切片操作。为了方便起见,我们可以用一个省略号(...)来表示遍历剩下的维度。

(1) 举例来说,我们先用arange函数创建一个数组并改变其维度,使之变成一个三维数组:

In [31]: b = np.arange(24).reshape(2,3,4)

In [32]: b.shape
Out[32]: (2, 3, 4)

In [33]: b
Out[33]:
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中有0~23的整数,共24个元素,是一个2×3×4的三维数组。我们可以形象地把它看做一个两层楼建筑,每层楼有12个房间,并排列成3行4列。或者,我们也可以将其看成是电子表格中工作表(sheet)、行和列的关系。你可能已经猜到,reshape函数的作用是改变数组的“形状”,也就是改变数组的维度,其参数为一个正整数元组,分别指定数组在每个维度上的大小。如果指定的维度和数组的元素数目不相吻合,函数将抛出异常。

(2) 我们可以用三维坐标来选定任意一个房间,即楼层、行号和列号。例如,选定第1层楼、第1行、第1列的房间(也可以说是第0层楼、第0行、第0列,这只是习惯问题),可以这样表示:

In [34]: b[0,0,0]
Out[34]: 0

(3) 如果我们不关心楼层,也就是说要选取所有楼层的第1行、第1列的房间,那么可以将第1个下标用英文标点的冒号:来代替:

In [35]: b[:,0,0]
Out[35]: array([ 0, 12])
In [36]: b[0]
Out[36]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

我们还可以这样写,选取第1层楼的所有房间:
I

n [37]:  b[0, :, :]
Out[37]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

多个冒号可以用一个省略号(...)来代替,因此上面的代码等价于:

In [38]: b[0, ...]
Out[38]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
       
In [39]: b[...,0]
Out[39]:
array([[ 0,  4,  8],
       [12, 16, 20]])

In [40]: b[0,...,0]
Out[40]: array([0, 4, 8])

进而可以选取第1层楼、第2排的所有房间:

In [41]: b[0,1]
Out[41]: array([4, 5, 6, 7])

(4) 再进一步,我们可以在上面的数组切片中间隔地选定元素:

In [42]: b[0,1,::2]
Out[42]: array([4, 6])

(5) 如果要选取所有楼层的位于第2列的房间,即不指定楼层和行号,用如下代码即可:

In [43]: b[...,1]
Out[43]:
array([[ 1,  5,  9],
       [13, 17, 21]])

类似地,我们可以选取所有位于第2行的房间,而不指定楼层和列号:

In [44]: b[:,1]
Out[44]:
array([[ 4,  5,  6,  7],
       [16, 17, 18, 19]])

如果要选取第1层楼的所有位于第2列的房间,在对应的两个维度上指定即可:

In [45]: b[0,:,1]
Out[45]: array([1, 5, 9])

(6) 如果要选取第1层楼的最后一列的所有房间,使用如下代码:

In [46]: b[0,:,-1]
Out[46]: array([ 3,  7, 11])

如果要反向选取第1层楼的最后一列的所有房间,使用如下代码:

In [47]: b[0,::-1, -1]
Out[47]: array([11,  7,  3])

在该数组切片中间隔地选定元素:

In [48]: b[0,::2,-1]
Out[48]: array([ 3, 11])

如果在多维数组中执行翻转一维数组的命令,将在最前面的维度上翻转元素的顺序,在我们
的例子中将把第1层楼和第2层楼的房间交换:

In [49]: b[::-1]
Out[49]:
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 动手实践:改变数组的维度

我们已经学习了怎样使用reshape函数,现在来学习一下怎样将数组展平。
(1) ravel
我们可以用ravel函数完成展平的操作:

In [50]: b
Out[50]:
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 [51]: b.ravel()
Out[51]:
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 [52]: b
Out[52]:
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 [53]: b.flatten()
Out[53]:
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 [54]: b
Out[54]:
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]]])

注:flatten 展平后是原来数据的copy 但是ravel 是原来数据的视图

In [61]: a=np.array([[1,2],[3,4]])

In [62]: a.flatten()
Out[62]: array([1, 2, 3, 4])

In [63]: a.flatten()[0]=2

In [64]: a
Out[64]:
array([[1, 2],
       [3, 4]])

In [65]: a.ravel()
Out[65]: array([1, 2, 3, 4])

In [66]: a.ravel()[0]=2

In [67]: a
Out[67]:
array([[2, 2],
       [3, 4]])

(3) 用元组设置维度
除了可以使用reshape函数,我们也可以直接用一个正整数元组来设置数组的维度,如下所示:

In [68]: b.shape = (6,4)

In [69]: b
Out[69]:
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 [70]: b.transpose()
Out[70]:
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]])

In [71]: b
Out[71]:
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]])

(5) resize
resizereshape函数的功能一样,但resize会直接修改所操作的数组:

In [72]: b.resize((2,12))

In [73]: b
Out[73]:
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]])

小结:我们用ravelflattenreshaperesize函数对NumPy数组的维度进行了修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值