本文实例讲述了Python Numpy库常见用法。分享给大家供大家参考,具体如下:
1、简介
Numpy是一个常用的Python科学技术库,通过它可以快速对数组进行操作,包括形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等。许多Python库和科学计算的软件包都使用Numpy数组作为操作对象,或者将传入的Python数组转化为Numpy数组,因此在Python中操作数据离不开Numpy。
Numpy的核心是ndarray对象,由Python的n维数组封装而来,但通过C语言预编译相关的数组操作,因此比原生Python具有更高的执行效率,但仍然使用Python语言编码,这样就同时具有简洁的代码和高效的运行速度。ndarry与数组有些区别值得注意,numpy数组中的元素都具有相同的类型,并且在创建时就确定了固定的大小,这与Python数组对象可以动态增长不同。
2、数组对象
2.1、属性
Numpy对象的形式是同构多维数组,数组的维度称为轴(axis),每个维度上元素的个数称为轴的长度。例如下面是一个2×3的二维数组arr,第一轴长度为3,第二轴长度为2
1
2
|
arr = [[ 1. , 0. , 0. ], [ 0. , 1. , 2. ]] |
arr数组对象常用的属性如下:
1
2
3
4
5
6
7
8
9
10
|
# 数组轴的个数 arr.ndim # 数组维度及长度,例如2×3的数组其shape为(2, 3) arr.shape # 数组元素的总个数 arr.size # 数组中元素的数据类型 arr.dtype # 数组中元素所占字节数 arr.itemsize |
2.2、创建数组
可以通过array()方法包裹普通python数组将其转化为numpy数组,通过dtype=规定元素的数据类型。数组可以是二维等高维数组,也可以是元组的形式。
如果需要填充已知大小的数组可以使用函数zeros(),将元素都填充为0,或者ones()将元素填充为1,empty()将元素填充为随机数
arange(a,b,c)函数用于从a到b每隔c长度生成一个数组元素。linspace(a,b,c)函数用于在a到b之间生成c个数组元素
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
27
28
29
30
31
|
# 普通数组转化为numpy数组 a1 = np.array([ 2 , 3 , 4 ], dtype = float ) print (a1) # 将元组数组转化为二维numpy数组 a2 = np.array([( 1 , 2 , 3 ), ( 3 , 4 , 5 )]) print (a2) # 将3×3的数组用1填充 a3 = np.ones(( 3 , 3 )) print (a3) # 从1到10,每隔2生成一个元素 a4 = np.arange( 1 , 10 , 2 ) print (a4) # 在1到12之间生成4个元素 a5 = np.linspace( 1 , 12 , 4 , dtype = int ) print (a5) ''' 普通数组转化为numpy对象: [2. 3. 4.] 元组数组: [[1 2 3] [3 4 5]] 用1填充数组: [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] 从1到10每隔2生成一个元素: [1 3 5 7 9] 在1到12之间生成4个元素: [ 1 4 8 12] ''' |
2.3、数组操作
算术运算符可以直接运用在矩阵上,其结果是将运算应用到每个元素上,例如矩阵A*B就是每个元素对应相乘,矩阵的乘法运算使用的是@符号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
A = np.array([[ 1 , 1 ], [ 0 , 1 ]]) B = np.array([[ 2 , 0 ], [ 3 , 4 ]]) print (A * B) print (A @ B) ''' 矩阵元素对应相乘: [[2 0] [0 4]] 矩阵的乘法: [[5 4] [3 4]] ''' |
numpy中有些函数应用于整个数组,例如求和sum、最大值max、最小值min。如果在这些参数中指定了某个轴,则应用于指定轴。
还有一些函数应用于数组中的具体元素,例如求sin、cos、exp、开方sqrt等,这些函数叫做通函数(ufunc)
1
2
3
4
5
6
|
a = np.array([[ 0 , 1 , 2 , 3 ], [ 4 , 5 , 6 , 7 ], [ 8 , 9 , 10 , 11 ]]) print (a. max ()) # 求整体的最大值,结果为11 print (a. sum (axis = 0 )) # 求每一列的和,结果为:[12 15 18 21] print (np.sqrt(a)) # 数组每个元素求开方 |
numpy中的数组同python中的list一样可以进行索引、切片和迭代操作。数组a[x]代表访问数组a下标为x的元素,一维数组a[x:y]代表访问数组从x到y的元素,如果省略x代表从头开始,省略y代表直到结尾。a[x:y:a]代表从x到y每隔a个元素取一个值,如果a为负数,代表逆序取值。
1
2
3
|
a = np.array([ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]) print (a[ 1 : 3 ]) # 输出下标为1到3的元素:[1 2] print (a[:: - 2 ]) # 逆序每隔两个元素选一个值:[9 7 5 3 1] |
如果是多维数组,则索引之间用逗号分隔。可以使用...代表省略某几个维度,如果省略则会被认为是该维度全部输出,例如x[...,3]
等效于 x[:,:,:,:,3]
。
可以通过for循环迭代多为数组,其内容为低一维度的子数组,如果希望遍历每一个子元素,可以使用flat属性。
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
27
28
29
30
31
32
33
|
a = np.array([[ 0 , 1 , 2 , 3 ], [ 10 , 11 , 12 , 13 ], [ 40 , 41 , 42 , 43 ]]) # 输出a第一维(行)的前三个,第二维(列)下标的1~3 print (a[ 1 : 3 , 0 : 3 ]) # 输出行的所有,下标为2的列 print (a[ 2 , ...]) # 遍历数组 for row in a: print (row) # 遍历每个子元素 for item in a.flat: print (item) ''' 后两行的1~3列: [[10 11 12] [40 41 42]] 第三行的所有列: [40 41 42 43] 遍历数组: [0 1 2 3] [10 11 12 13] [40 41 42 43] 遍历每个元素: 0 1 2 ...... 41 42 43 ''' |
除了使用具体数字作为索引,还可以使用numpy数组作为索引。例如使用数组i作为一维数组a的索引,输出a[i]。当数组i为多维数组时,从a中选出元素填到i数组的对应位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
a = np.arange( 12 ) * * 2 print (a) i = np.array([ 1 , 3 , 5 ]) print (a[i]) # 多维数组索引j j = np.array([[ 3 , 4 ], [ 9 , 7 ]]) print (a[j]) ''' [ 0 1 4 9 16 25 36 49 64 81 100 121] 数组a的1、3、5个元素 [ 1 9 25] 通过多为索引j取出a的数据填到对应位置 [[ 9 16] [81 49]] ''' |
如果a是多维数组,索引数组的单个元素代表选中数组a的第一个维度
如果对多维数组在多个维度上进行索引,则传入多个索引数组i,j并用逗号分隔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
a = np.array(([[ 0 , 1 , 2 , 3 ], [ 4 , 5 , 6 , 7 ], [ 8 , 9 , 10 , 11 ]])) # 多维数组的单元素索引 i = np.array([ 0 , 1 ]) print (a[i]) # 对多维数组提供多维度索引,同时提供i,j代表取出a的[0,2]、[1,3]两个元素 j = np.array([ 2 , 3 ]) print (a[i, j]) ''' 选择多维数组a的第0、1两行: [[0 1 2 3] [4 5 6 7]] a的[0,2]、[1,3]两个元素: [2 7] ''' |
2.4、改变维度
数组的reshape()方法可以将原数组重构成目标维度的数组,例如将一个2×6的数组重构为3×4的数组,
数组在重构时不会修改原数组,而是返回修改后的结果数组
值得注意的是数组在重构和打印时都是从最右边的维度开始往左进行,例如下面的3×4的数组b,先按行排列4个,然后再换行,排列这样的3行。如果是多维,则按这样的行列继续输出。如果数组维度为-1,则会自动计算该维度的大小,例如含有12个元素的数组,第二、第三维是3×2,则第一维就是2
ravel()函数可以将数组展成一维数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
a = np.array([[ 1 , 2 , 3 , 4 , 5 , 6 ], [ 7 , 8 , 9 , 10 , 11 , 12 ]]) b = a.reshape( 3 , 4 ) print (b) # 多维数组,自动计算 print (a.reshape( - 1 , 3 , 2 )) # 展开数组 flatted = b.ravel() print (flatted, end = ' ' ) ''' [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] 2×3×2的多维数组: [[[ 1 2] [ 3 4] [ 5 6]] [[ 7 8] [ 9 10] [11 12]]] 展开数组: [ 1 2 3 4 5 6 7 8 9 10 11 12] ''' |
numpy的hstack()函数可以在水平方向上合并多个数组,vstack()函数可以在垂直方向上合并多个数组
相反地,hsplit()、vsplit()可以拆分为指定数量的数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
a = np.array([ 1 , 2 , 3 ]) b = np.array([ 4 , 5 , 6 ]) # 垂直方向合并 c = np.vstack((a,b)) print (c) # 水平方向合并 print (np.hstack((a,b))) # 水平方向拆分 print (np.hsplit(c, 3 )) ''' 垂直堆叠 [[1 2 3] [4 5 6]] 水平合并 [1 2 3 4 5 6] 水平拆分为三个1×2的: [array([[1], [4]]), array([[2], [5]]), array([[3], [6]])] ''' |
2.5、数组的复制
当一个数组对象赋值给一个新的变量时,是新开辟一个存储空间还是只是传递一个引用?答案是引用。
例如执行语句b=a,只是将一个引用传给了b,对b执行的操作会直接影响a。查看a、b两个对象的节点id也是一样的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
a = np.array([ 1 , 2 , 3 ]) b = a # 修改b b[ 0 ] = 0 print (a) # 输出a、b对象的id print ( id (a), id (b)) ''' 修改b,a也发生了变化 [0 2 3] 查看二者的id 2290013812656 2290013812656 ''' |
通过切片返回数组的视图,修改视图的形状不会影响原数组,但是在视图上修改数据原数组也会改变。在执行del a之后,由于c引用了a,a依旧会存在内存中不会被删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
c = a[:] # 修改视图的形状 c.shape = 3 , 1 print (c, a) # 修改视图c的数据 c[ 0 ] = 1 print (a[ 0 ]) ''' 对视图c的形状做修改,a不会受到影响 [[ 0 ] [ 2 ] [ 3 ]] [ 0 2 3 ] 修改c的数据,a也会随之改变: 1 |
通过copy()方法可以生成数据的副本,因此对副本的操作完全不会影响原数组
1
2
3
4
|
d = a.copy() d[ 0 ] = 5 # 修改数组的副本d,a不受影响,输出a:[1 2 3] print (a) |
希望本文所述对大家Python程序设计有所帮助。
原文链接:https://blog.csdn.net/theVicTory/article/details/103011188