【Numpy】数组的操作1
python中的固定类型数组python提供的内置的数组array模块可以用于创建同一类型的密集数组 1 import array 2 3 l = list(range(10)) 4 5 a = array.array("i",l) 6 7 a 8 Out[20]: array(‘i‘,[0,1,2,3,4,5,6,7,8,9]) 这里的 ‘i‘ 是一个数据类型码,表示数据为整型 更实用的是Numpy包中的ndarray对象 python的数组对象提供了数组型数据的有效存储,而Numpy为该数据加上了高效的操作 1 import numpy as np 从Python列表创建数组1 import numpy as np 2 3 np.array([1,3]) 4 Out[24]: array([1,3]) 注意:不同于python列表,Numpy要求数组必须包含同一类型的数据 若类型不匹配,Numpy将会向上转移(如果可行),这里的整型被转换为浮点型: 1 np.array([3.14,3]) 2 Out[25]: array([3.14,4.,2.,3. ]) 如果希望明确设置数组的数据类型,可以用dtype关键字: 1 np.array([1,4],dtype="float32") 2 Out[26]: array([1.,3.,4.],dtype=float32) Numpy数组可以被指定为多维的 1 # 嵌套列表构成的多维数组 2 3 np.array([range(i,i+3) for i in [2,6]]) 4 Out[28]: 5 array([[2,4],6 [4,6],7 [6,8]]) 从头创建数组1 # 创建一个长度为10的数组,数组值都为0 2 3 np.zeros(10,dtype=int) 4 Out[30]: array([0,0]) 5 6 # 创建一个 3 * 5 的浮点型数组,数组的值都为1 7 8 np.ones((3,5),dtype=float) 9 Out[32]: 10 array([[1.,1.,1.],11 [1.,12 [1.,1.]]) 13 14 # 创建一个 3 * 5 的浮点型数组,数组的值都是3.14 15 16 np.full((3,3.14) 17 Out[34]: 18 array([[3.14,3.14,3.14],19 [3.14,20 [3.14,3.14]]) 21 22 # 创建一个线性序列数组; 23 # 从0开始,到20结束,步长为2 24 # (它的内置的range函数类似) 25 26 np.arange(0,20,2) 27 Out[38]: array([ 0,10,12,14,16,18]) 28 29 # 创建一个5个元素的数组,这5个数均匀地分配到0-1 30 31 np.linspace(0,5) 32 Out[40]: array([0.,0.25,0.5,0.75,1. ]) 33 34 # 创建一个 3 * 3 的,在0-1均匀分布的随机数组成的数组 35 36 np.random.random((3,3)) 37 Out[43]: 38 array([[0.7019541,0.00787364,0.41495839],39 [0.13411158,0.95440426,0.99184209],40 [0.32671128,0.80212981,0.35702935]]) 41 42 # 创建一个3 * 3的,均值为0,标准差为1正态分布的随机数数组 43 44 np.random.normal(0,(3,3)) 45 Out[45]: 46 array([[-0.76169057,-0.74273207,0.19062862],47 [ 0.422799,-0.94405275,-0.33567806],48 [ 0.52447272,1.55895324,-0.49119638]]) 49 50 # 创建一个 3 * 3 的,[0,10)区间的随机整型数组 51 52 np.random.randint(0,3)) 53 Out[47]: 54 array([[9,5],55 [4,56 [9,5]]) 57 58 # 创建一个 3*3的单位矩阵 59 60 np.eye(3) 61 Out[49]: 62 array([[1.,0.,0.],63 [0.,1.,64 [0.,1.]]) 65 66 # 创建一个由三个整型组成的未初始化的数组 67 # 数组的值是内存空间的任意值 68 69 np.empty(3) 70 Out[52]: array([1.,1.]) Numpy标准数据类型?Numpy数组包含同一类型的值,因此详细了解数据类型及其限制是非常重要的 Numpy是在C语言基础上开发的,因此运用的都是C语言的数据类型 1 np.zeros(10,dtype=‘int16‘) 2 Out[53]: array([0,0],dtype=int16) 3 4 np.zeros(10,dtype=np.int16) #用numpy对象来指定 5 Out[54]: array([0,dtype=int16) 二、Numpy数组操作1.数组的属性:确定数组的大小,形状,存储大小,数据类型 2.数组的索引:获取和设置数组各个元素的值 3.数组的切分:在大的数组中获取或设置更小的子数组 4.数组的变形:改变给定数组的形状 5.数组的拼接和分裂:将多个数组合并为一,以及将一个数组分裂成多个 Numpy数组的属性定义三个随机数组:一个一维数组,一个二维数组,一个三维数组,将Numpy的随机数生成器设置一组种子值,以确保每次程序执行时都可以生成相同的数组 1 import numpy as np 2 3 np.random.seed(0) # 设置随机数种子 4 5 x1 = np.random.randint(10,size=6) # 一维数组 6 7 x2 = np.random.randint(10,size=(3,4)) # 二维数组 8 9 x3 = np.random.randint(10,5)) # 三维数组 每个数组有ndim(数组维度),shape(数组每个维度的大小),和size(数组的总大小)属性: 1 print("x1 nidm:",x1.ndim) 2 x1 nidm: 1 3 4 print("x3 shape:",x3.shape) 5 x3 shape: (3,5) 6 7 print("x2 size:",x3.size) 8 x2 size: 60 另一个有用的属性dtype,数组的数据类型: 1 print("dtype:",x3.dtype) 2 dtype: int32 其他的属性包括表示每个数组元素字节大小的itemsize,以及表示数组总字节大小的属性nbytes: 1 print("itemsize:",x3.itemsize,"bytes") 2 itemsize: 4 bytes 3 4 print("nbytes:",x3.nbytes,"bytes") 5 nbytes: 240 bytes 一般来说,可以认为nbytes跟itemsize和size的乘积大小相等 Numpy数组索引:获取单个元素与Python标准列表索引一样的使用方式 1 x1 2 Out[70]: array([5,9]) 3 4 x1[0] 5 Out[71]: 5 6 7 x1[4] 8 Out[72]: 7 为获取数组末尾的索引,可以用负值索引: 1 x1[-1] 2 Out[73]: 9 3 4 x1[-2] 5 Out[74]: 7 在多维数组中,可以使用逗号分隔的索引元组获取元素 1 x2 2 Out[75]: 3 array([[3, 4 [7,8], 5 [1,7]]) 6 7 x2[0,0] 8 Out[76]: 3 9 10 x2[2,0] 11 Out[77]: 1 12 13 x2[2,-1] 14 Out[78]: 7 可以用以上索引方式修改元素值 1 x2[0,0] = 12 2 3 x2 4 Out[80]: 5 array([[12,6 [ 7,7 [ 1,7]]) 与python列表不同,Numpy数组是固定的类型,当插入一个浮点型到整型数组中去,浮点值会被截短成整形,这种方式是自动完成的,不会提示或者警告,所以需要注意 1 x1[0] = 3.1415926 2 3 x1 4 Out[82]: array([3,9]) Numpy数组切片:获取子数组正如前面使用中括号获取数组单个元素,我们也可以使用切片符号获取子数组,切片符号用冒号(:)表示 Numpy切片语法和python列表的标准切片语法相同 1 x[start:stop:step]
默认值start = 0,stop = 维度的大小(size of dimension)和step = 1 1.一维子数组 1 x = np.arange(10) 2 3 x 4 Out[8]: array([0,9]) 5 6 x[:5] # 前五个元素 7 Out[9]: array([0,4]) 8 9 x[5:] # 索引5之后的元素 10 Out[10]: array([5,9]) 11 12 x[4:7] # 中间的子数组 13 Out[11]: array([4,6]) 14 15 x[::2] # 每隔一个元素 16 Out[12]: array([0,8]) 17 18 x[1::2] # 每隔一个元素,从索引1开始 19 Out[13]: array([1,9]) 20 21 x[::-1] # 所有元素,逆序的 22 Out[14]: array([9,1,0]) 23 24 x[5::-2] # 从索引5开始每隔一个元素逆序 25 Out[15]: array([5,1]) 2.二维子数组 多维切片也采用同样的方式处理,用逗号隔开 1 x2 = np.random.randint(10,4)) 2 3 x2 4 Out[17]: 5 array([[4,2], 6 [6,9], 7 [8,9]]) 8 9 x2[:2,:3] # 两行,三列 10 Out[18]: 11 array([[4,12 [6,3]]) 13 14 x2[:3,::2] # 所有行,每每隔一列 15 Out[19]: 16 array([[4,17 [6,3],18 [8,3]]) 19 20 x2[::-1,::-1] # 逆序 21 Out[20]: 22 array([[9,23 [9,24 [2,4]]) 3.获取数组的行和列 常见的需求是获取数组的单行和单列,可以将索引和切片结合起来实现,用一个冒号(:)表时空切片 1 x2 2 Out[21]: 3 array([[4, 4 [6, 5 [8,9]]) 6 7 print(x2[:,0]) # x2的第一行 8 [4 6 8] 9 10 print(x2[0,:]) # x2的第一列 11 [4 1 4 2] 12 13 print(x2[0]) # 可以省略空的切片,效果一样 14 [4 1 4 2] 4.非副本视图的子数组 python列表中,切片是值的副本 与python列表切片不同,数组切片返回的是数组数据的视图,而不是数值数据的副本 1 x2 2 Out[30]: 3 array([[4,9]]) 6 7 x2_sub = x2[:2,:2] 8 9 print(x2_sub) 10 [[4 1] 11 [6 7]] 12 13 x2_sub[0,0] = 99 # 修改子数组 14 15 print(x2_sub) 16 [[99 1] 17 [ 6 7]] 18 19 x2 # 原始数组也被修改了 20 Out[35]: 21 array([[99,22 [ 6,23 [ 8,9]]) 5.创建数组的副本 复制数组里的数据或子数组可以通过copy( )方法实现 1 x2_sub_copy = x2[:2,:2].copy() 2 3 print(x2_sub_copy) 4 [[99 1] 5 [ 6 7]] 6 7 x2_sub_copy[0,0] = 42 # 子数组的元素被修改 8 9 print(x2_sub_copy) 10 [[42 1] 11 [ 6 7]] 12 13 x2 # 原始数组对应元素不发生变化 14 Out[40]: 15 array([[99,16 [ 6,17 [ 8,9]]) 数组的变形通过reshape( )函数来实现数组变形 例如:将数字1~9放入到3 * 3 矩阵中,可以采用以下方法: 1 grid = np.arange(1,10).reshape((3,3)) 2 3 print(grid) 4 [[1 2 3] 5 [4 5 6] 6 [7 8 9]] 注意:若希望此方法可行,那么原始数组大小必须和变型后的数组大小一致,如果满足,reshape方法将会用到原始数组的一个非副本视图 另一个变形模式是将一个一维数组转变为二维的行或列的矩阵,也可以通过reshape方法实现或者简单地在一个切片操作中利用newwaxis关键字 1 x = np.array([1,3]) 2 3 x.reshape((1,3)) # 通过变型获得的行向量 4 Out[52]: array([[1,3]]) 5 6 x[np.newaxis,:] # 通过newaxis获取的行向量 7 Out[53]: array([[1,3]]) 8 9 x.reshape((3,1)) # 通过变型获得的列向量 10 Out[54]: 11 array([[1],12 [2],13 [3]]) 14 15 x[:,np.newaxis] # 通过newaxis获取的列向量 16 Out[56]: 17 array([[1],18 [2],19 [3]]) ?数组拼接和分裂以上所有的操作都是针对的单一数组的,但有时候需要将多个数组合并为一个,或将一个数组分裂成多个。 1.数组的拼接 拼接或连接Numpy中的两个数组主要是由np.concatenate、np.vstack和np.hstack例程实现 np.concatenate 将数组元组或者数组列表作为第一个参数: 1 x = np.array([1,3]) 2 3 y = np.array([3,1]) 4 # np.concatenate 将数组元组或者数组列表作为第一个参数 5 np.concatenate([x,y]) 6 Out[60]: array([1,1]) 7 8 np.concatenate((x,y)) 9 Out[61]: array([1,1]) 10 11 z = [99,99,99] 12 # 一次性拼接两个以上的数组 13 print(np.concatenate([x,y,z])) 14 [ 1 2 3 3 2 1 99 99 99] 15 16 # np.concatenate应用于二维数组的拼接 17 grid = np.array([[1,3],[4,6]]) 18 19 #沿第一个轴拼接 20 np.concatenate([grid,grid]) 21 Out[65]: 22 array([[1,23 [4,24 [1,25 [4,6]]) 26 # 沿着第二个轴拼接(从0开始索引) 27 np.concatenate([grid,grid],axis=1) 28 Out[67]: 29 array([[1,30 [4,6]]) 沿着固定维度处理数组时,使用np.vstack(垂直栈)和np.hstack(水平栈)函数更简洁: 1 x = np.array([1,3]) 2 3 grid = np.array([[9,7],[6,4]]) 4 5 #垂直栈数组 6 np.vstack([x,grid]) 7 Out[70]: 8 array([[1, 9 [9,7],10 [6,4]]) 11 12 y = np.array([[99],[99]]) 13 14 #水平栈数组 15 np.hstack([grid,y]) 16 Out[72]: 17 array([[ 9,99],18 [ 6,99]]) 与此类似,np.dstack将沿着第三个维度拼接数组 2.数组的分裂 与拼接相反的是分裂 分裂通过np.split、np.hsplit、np.vsplit函数实现 可以向以上函数传递一个索引列表作为参数,索引列表记录的是分裂点位置 1 x = [1,1] 2 3 x1,x2,x3 = np.split(x,[3,5]) 4 5 print(x1,x3) 6 [1 2 3] [99 99] [3 2 1] 值得注意的是N个分裂点会得到N+1个子数组 1 grid = np.arange(16).reshape((4,4)) 2 3 grid 4 Out[78]: 5 array([[ 0, 6 [ 4, 7 [ 8,9,11], 8 [12,13,15]]) 9 10 upper,lower = np.vsplit(grid,[2]) 11 12 print(upper) 13 [[0 1 2 3] 14 [4 5 6 7]] 15 16 print(lower) 17 [[ 8 9 10 11] 18 [12 13 14 15]] 19 20 left,right = np.hsplit(grid,[2]) 21 22 print(left) 23 [[ 0 1] 24 [ 4 5] 25 [ 8 9] 26 [12 13]] 27 28 print(right) 29 [[ 2 3] 30 [ 6 7] 31 [10 11] 32 [14 15]] 同样,np.dsplit将数组沿着第三个维度分裂 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |