1、NumPy数组对象
NumPy中的 ndarray 是一个多维数组对象,该对象由两部分组成:
实际的数据;
描述这些数据的元数据;
大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据。
ndarray 支持更高的维度的数组。
NumPy数组一般是同质的(但有一种特殊的数组类型例外,它是异质的),即数组中的所有元素类型必须是一致的。这样有一个好处:如果我们知道数组中的元素均为同一类型,该数组所需的存储空间就很容易确定下来。
与Python中一样,NumPy数组的下标也是从 0 开始的。数组元素的数据类型用专门的对象表示。
2、np.arange()创建一维数组
- # coding=utf-8
- import numpy as np
-
- #NumPy创建0~4的数组
- a = np.arange(5)
- print("a的值为:",a)
-
- #查看a的数据类型
- print("a的类型为:",a.dtype)
-
- #输出a的向量的维度
- print("a的向量的维度为:",a.shape)
输出:
a的值为: [0 1 2 3 4]
a的类型为: int32
a的向量的维度为: (5,)
这是一个包含5个元素的向量,取值分别为0~4的整数。
使用32位的Python,得到的结果是 int32。
数组的 shape 属性返回一个元组(tuple),元组中的元素即为NumPy数组每一个维度上的大小。
上面例子中的数组是一维的,因此元组中只有一个元素。
3、创建多维数组
- # coding=utf-8
- import numpy as np
-
- #创建一个二维数组
- #将 arange 函数创建的数组作为列表元素,把这个列表作为参数传给 array 函数,从而创建了一个2×2的数组
- m = np.array([np.arange(2),np.arange(2)])
- print("m的值为:",m)
-
- print("m的类型为:",m.dtype)
-
- print("m的向量维度为:",m.shape)
输出为:
m的值为: [[0 1]
[0 1]]
m的类型为: int32
m的向量维度为: (2, 2)
array 函数可以依据给定的对象生成数组。给定的对象应是类数组,如Python中的列表。在上面的例子中,我们传给 array 函数的对象是一个NumPy数组的列表。像这样的类数组对象是array 函数的唯一必要参数,其余的诸多参数均为有默认值的可选参数。
4、选取数组元素
- # coding=utf-8
- import numpy as np
-
- #创建二维数组,注意外层还有一个中括号,否则无法解析类型
- a = np.array([[1,2],[3,4]])
- '''
- 1 2
- 3 4
- '''
- print(a[0,0], end='')
- print(a[0,1])
- print(a[1,0], end='')
- print(a[1,1])
注意查看数据时,并不是a[0][0]这样,而是a[0,0]这样。
输出为:
12
34
5、NumPy 数据类型
Python支持的数据类型有整型、浮点型以及复数型,但这些类型不足以满足科学计算的需求,因此NumPy添加了很多其他的数据类型。在实际应用中,我们需要不同精度的数据类型,它们占用的内存空间也是不同的。在NumPy中,大部分数据类型名是以数字结尾的,这个数字表示其在内存中占用的位数。
bool
用一位存储的布尔类型(值为 TRUE 或 FALSE )
inti
由所在平台决定其精度的整数(一般为 int32 或 int64 )
int8
整数,范围为128至127
int16
整数,范围为32 768至32 767
int32
整数,范围为2 31 至2 31 1
int64
整数,范围为2 63 至2 63 1
uint8
无符号整数,范围为0至255
uint16
无符号整数,范围为0至65 535
uint32
无符号整数,范围为0至2 32 1
uint64
无符号整数,范围为0至2 64 1
float16
半精度浮点数(16位):其中用1位表示正负号,5位表示指数,10位表示尾数
float32
单精度浮点数(32位):其中用1位表示正负号,8位表示指数,23位表示尾数
float64 或 float 双精度浮点数(64位):其中用1位表示正负号,11位表示指数,52位表示尾数
complex64
复数,分别用两个32位浮点数表示实部和虚部
complex128 或 complex 复数,分别用两个64位浮点数表示实部和虚部
在NumPy中,许多函数的参数中可以指定数据类型,通常这个参数是可选的。
6、数据类型对象
#数据类型对象可以给出单个数组元素在内存中占用的字节数 print(a.dtype.itemsize)
7、 动手实践:创建自定义数据类型
- # coding=utf-8
- import numpy as np
-
- #自定义商品库存的数据类型(商品名称、商品个数、商品价格)
- t = np.dtype([('name',str,40),('numitems',int),('price',float)])
-
- #输出类型
- print(t)
-
- #查看某个字段的数据类型
- print(t['name'])
-
- items = np.array([('小猪佩奇',20,3.5),('白酒',30,80.5),('LOL俄洛依皮肤',1,210.5)])
-
- #没有指定数据类型,默认价格为浮点数类型
- print(items)
-
- #指定数据类型
- items2 = np.array([('小猪佩奇',20,3.5),('白酒',30,80.5),('LOL俄洛依皮肤',1,210.5)],dtype=t)
- print(items2)
输出为:
[(‘name’, ‘<U40’), (‘numitems’, ‘<i4’), (‘price’, ‘<f8’)]
<U40
[[‘小猪佩奇’ ’20’ ‘3.5’]
[‘白酒’ ’30’ ‘80.5’]
[‘LOL俄洛依皮肤’ ‘1’ ‘210.5’]]
[(‘小猪佩奇’, 20, 3.5) (‘白酒’, 30, 80.5) (‘LOL俄洛依皮肤’, 1, 210.5)]
我们创建了一种自定义的异构数据类型,该数据类型包括一个用字符串记录的名字、一个用整数记录的数字以及一个用浮点数记录的价格。
8、一维数组的索引和切片
- # coding=utf-8
- import numpy as np
-
- #创建0~8的数组
- a = np.arange(9)
-
- #用下标 3 ~ 7 来选取元素 3 ~ 6
- print(a[3:7])
-
- #也可以用下标 0 ~ 7 ,以 2 为步长选取元素
- print(a[:7:2])
-
- #和Python中一样,我们也可以利用负数下标翻转数组
- print(a[::-1])
输出为:
[3 4 5 6]
[0 2 4 6]
[8 7 6 5 4 3 2 1 0]
9、多维数组的索引和切片
- # coding=utf-8
- import numpy as np
-
- #用 arange 函数创建一个数组并改变其维度,使之变成一个三维数组
- #reshape 函数的作用是改变数组的“形状”,也就是改变数组的维度,其参数为一个正整数元组,分别指定数组在每个维度上的大小。
- a = np.arange(24).reshape(2,3,4)
-
- #查看各维度
- print(a.shape)
-
- #多维数组 b 中有 0 ~ 23 的整数,共 24 个元素,是一个2×3×4的三维数组
- #我们可以形象地把它看做一个两层楼建筑,每层楼有12个房间,并排列成3行4列。
- print(a)
-
- #我们可以用三维坐标来选定任意一个房间,即楼层、行号和列号。例如,选定第1层楼、第1行、第1列的房间(也可以说是第0层楼、第0行、第0列,这只是习惯问题)
- print(a[0,0,0])
-
- #如果我们不关心楼层,也就是说要选取所有楼层的第1行、第1列的房间,那么可以将第1个下标用英文标点的冒号 : 来代替
- print(a[:,0,0])
-
- #我们还可以这样写,选取第1层楼的所有房间
- print(a[0,:,:])
-
- #多个冒号可以用一个省略号( ... )来代替,因此上面的代码等价于
- print(a[0, ...])
-
- #进而可以选取第1层楼、第2排的所有房间
- print(a[0,1])
-
- #再进一步,我们可以在上面的数组切片中间隔地选定元素
- print(a[0,1,::2])
-
- #如果要选取所有楼层的位于第2列的房间,即不指定楼层和行号,用如下代码即可
- print(a[...,1])
-
- #类似地,我们可以选取所有位于第2行的房间,而不指定楼层和列号:
- print(a[:,1])
-
- #如果要选取第1层楼的所有位于第2列的房间,在对应的两个维度上指定即可
- print(a[0,:,1])
-
- #如果要选取第1层楼的最后一列的所有房间,使用如下代码
- print(a[0,:,-1])
-
- #如果要反向选取第1层楼的最后一列的所有房间,使用如下代码
- print(a[0,::-1,-1])
-
- #在该数组切片中间隔地选定元素
- print(a[0,::2,-1])
-
- #如果在多维数组中执行翻转一维数组的命令,将在最前面的维度上翻转元素的顺序,在我们的例子中将把第1层楼和第2层楼的房间交换
- print(a[::-1])
输出为:
(2, 3, 4)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]][[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
0
[ 0 12]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[4 5 6 7]
[4 6]
[[ 1 5 9]
[13 17 21]]
[[ 4 5 6 7]
[16 17 18 19]]
[1 5 9]
[ 3 7 11]
[11 7 3]
[ 3 11]
[[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]][[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]]
9、改变数组的维度
用 ravel 、 flatten 、 reshape 和 resize 函数对NumPy数组的维度进行修改
- # coding=utf-8
- import numpy as np
-
- #创建数据并标识维度
- a = np.arange(24).reshape(2,3,4)
-
- print(a)
-
- #ravel函数将数组展平,不过不分配内存,只是起到显示的作用
- print(a.ravel())
-
- #flatten函数将数组展平,与ravel函数功能相同,不过, flatten 函数会请求分配内存来保存结果,而 ravel 函数只是返回数组的一个视图(view)
- print(a.flatten())
-
- #用元组设置维度,除了可以使用 reshape 函数,我们也可以直接用一个正整数元组来设置数组的维度
- a.shape = (6,4)
- print(a)
-
- # transpose转置矩阵
- print(a.transpose())
-
- # resize 和 reshape 函数的功能一样,但 resize 会直接修改所操作的数组
- a.resize(2,12)
- print(a)
输出为:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]][[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
[[ 0 4 8 12 16 20]
[ 1 5 9 13 17 21]
[ 2 6 10 14 18 22]
[ 3 7 11 15 19 23]]
[[ 0 1 2 3 4 5 6 7 8 9 10 11]
[12 13 14 15 16 17 18 19 20 21 22 23]]
10、数组的组合
NumPy数组有水平组合、垂直组合和深度组合等多种组合方式,我们将使用 vstack 、dstack 、 hstack 、 column_stack 、 row_stack 以及 concatenate 函数来完成数组的组合。
- # coding=utf-8
- import numpy as np
-
- a = np.arange(9).reshape(3,3)
- print(a)
-
- b = a * 2
- print(b)
- print()
- '''
- 1、水平组合
- 将 ndarray 对象构成的元组作为参数,传给hstack 函数
- '''
- print("水平组合方法一:")
- print(np.hstack((a,b)))
- #也可以用 concatenate 函数来实现同样的效果
- print("水平组合方法二:")
- print(np.concatenate((a,b),axis = 1))
- print()
-
- '''
- 2、垂直组合
- 垂直组合同样需要构造一个元组作为参数,只不过这次的函数变成了vstack
- '''
- print("垂直组合方法一:")
- print(np.vstack((a,b)))
- #同样,我们将 concatenate 函数的 axis 参数设置为0即可实现同样的效果。这也是 axis 参数的默认值
- print("垂直组合方法二:")
- print(np.concatenate((a,b),axis = 0))
- print()
-
- '''
- 3、深度组合
- 将相同的元组作为参数传给 dstack 函数,即可完成数组的深度组合。
- 所谓深度组合,就是将一系列数组沿着纵轴(深度)方向进行层叠组合。
- 举个例子,有若干张二维面内的图像点阵数据,我们可以将这些图像数据沿纵轴方向层叠在一起,这就形象地解释了什么是深度组合。
- '''
- print("垂直组合方法:")
- print(np.dstack((a,b)))
- print()
-
- '''
- 4、列组合
- column_stack 函数对于一维数组将按列方向进行组合
- '''
- print("列组合:")
- oned = np.arange(2)
- print(oned)
- twice_oned = 2 * oned
- print(twice_oned)
- print(np.column_stack((oned,twice_oned)))
- #而对于二维数组, column_stack 与 hstack 的效果是相同的
- print(np.column_stack((a,b)))
- #我们可以用 == 运算符来比较两个NumPy数组
- print(np.column_stack((a,b)) == np.hstack((a,b)))
-
- '''
- 5、行组合
- row_stack对于两个一维数组,将直接层叠起来组合成一个二维数组。
- '''
- print("行组合:")
- print(np.row_stack((oned,twice_oned)))
- #对于二维数组, row_stack 与 vstack 的效果是相同的
- print(np.row_stack((a,b)))
结果:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[ 0 2 4]
[ 6 8 10]
[12 14 16]]水平组合方法一:
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]
水平组合方法二:
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]垂直组合方法一:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]
垂直组合方法二:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]垂直组合方法:
[[[ 0 0]
[ 1 2]
[ 2 4]][[ 3 6]
[ 4 8]
[ 5 10]][[ 6 12]
[ 7 14]
[ 8 16]]]列组合:
[0 1]
[0 2]
[[0 0]
[1 2]]
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]
[[ True True True True True True]
[ True True True True True True]
[ True True True True True True]]
行组合:
[[0 1]
[0 2]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]
11、数组的分割
NumPy数组可以进行水平、垂直或深度分割,相关的函数有 hsplit 、 vsplit 、 dsplit 和split 。
我们可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置。
- # coding=utf-8
- import numpy as np
- a = np.arange(9).reshape(3,3)
-
- print(a)
-
- print("水平分割:")
- #下面的代码将把数组沿着水平方向分割为3个相同大小的子数组
- print(np.hsplit(a,3))
- #调用 split 函数并在参数中指定参数 axis=1 ,结果一样
- print(np.split(a,3,axis = 1))
- print()
-
- #vsplit 函数将把数组沿着垂直方向分割
- print("垂直分割:")
- print(np.vsplit(a,3))
- #同样,调用 split 函数并在参数中指定参数 axis=0 ,也可以得到同样的结果
- print(np.split(a,3,axis = 0))
- print()
-
- #dsplit 函数将按深度方向分割数组
- print("深度分割")
- c = np.arange(27).reshape(3,3,3)
- print(c)
- print(np.dsplit(c,3))
-
结果为:
[[0 1 2]
[3 4 5]
[6 7 8]]
水平分割:
[array([[0],
[3],
[6]]), array([[1],
[4],
[7]]), array([[2],
[5],
[8]])]
[array([[0],
[3],
[6]]), array([[1],
[4],
[7]]), array([[2],
[5],
[8]])]垂直分割:
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]深度分割
[[[ 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]]]
[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]]])]
12、数组的属性
- # coding=utf-8
- import numpy as np
-
- a = np.arange(24).reshape(2,12)
-
- print(a)
-
- #ndim 属性,给出数组的维数,或数组轴的个数
- print("a的维度为:",a.ndim)
-
- # size 属性,给出数组元素的总个数
- print("a的元素个数为:",a.size)
-
- #itemsize 属性,给出数组中的每个元素在内存中所占的字节数
- print("a的元素占用内存字节数:",a.itemsize)
-
- #整个数组所占的存储空间,可以用 nbytes 属性来查看。这个属性的值其实就是 itemsize 和 size 属性值的乘积
- print("a所有元素所占存储空间:",a.nbytes)
-
- # flat 属性将返回一个 numpy.flatiter 对象,这是获得 flatiter 对象的唯一方式
- # 我们无法访问 flatiter 的构造函数。
- # 这个所谓的“扁平迭代器”可以让我们像遍历一维数组一样去遍历任意的多维数组
- b = np.arange(4).reshape(2,2)
- print(b)
- f = b.flat
- for item in f:
- print(item,end='')
-
- print()
- #还可以用 flatiter 对象直接获取一个数组元素
- print(a.flat[2])
- #获取多个元素
- print(a.flat[[1,3]])
- #flat 属性是一个可赋值的属性。对 flat 属性赋值将导致整个数组的元素都被覆盖
- b.flat = 7
- print(b)
- b.flat[[1,3]] = 1
- print(b)
输出为:
[[ 0 1 2 3 4 5 6 7 8 9 10 11]
[12 13 14 15 16 17 18 19 20 21 22 23]]
a的维度为: 2
a的元素个数为: 24
a的元素占用内存字节数: 4
a所有元素所占存储空间: 96
[[0 1]
[2 3]]
0123
2
[1 3]
[[7 7]
[7 7]]
[[7 1]
[7 1]]
13、数组转换成列表
- c = np.arange(4)
- #将NumPy数组转换成Python列表
- c.tolist()
- print(c)
- #astype函数可以在转换的时候指定数据类型
- c.astype(int)
- print(c)
输出:
[0 1 2 3]
[0 1 2 3]