第一部分:Numpy模块的简介
这个模块具有以下特性:
1:强大的多维数组类型
2:实用的函数
3:C/C++/Fortran语言作为底层实现
4:线性代数、傅里叶变换和随机数的支持
5:高效的数据存储容器
使用前导入该模块:
该模块的源代码放在Github上面
里面就是源代码
官方地址为:
numpy的官方地址
第二部分:数组基础
该部分是Numpy的核心部分,整个模块都是围绕它来构建的,数组的全称是N维数组(N-dimensional Array,ndarray),它是一个大小和形状固定的多维容器
1:使用np.array()函数构造,它的参数可以是列表、元组、也可以是另一个数组(这个np是我们导入Numpy模块是代替的缩写,命名可以自定义)
我们知道列表是不能进行加法的,但是用这个N维数组就可以实现很多种数学操作:
- 数组的属性
1:形状(.shape)
对于N维数组,属性.shape返回一个大小为N的元组,每个元素对应每个维度的大小,同时我们也可以利用np.shape()函数来查看数组的形状
这个函数不仅可以用于数组,也可以用于其他的类型:
多维列表:
单个元素:
2:数据类型(.dtype)(只用于数组)
3:所占字节数(.itemsize)(只用于数组)
4:查看元素总数(.size)(只用于数组)
5:查看元素总数(.shape()函数)(这个可以用于非数组的)
6:查看数组元素所占空间(.nbytes)(这个就是items和size的乘积,因为数组的内存空间是连续的)
7:查看数组的维度(.ndim)
8:数组类型和传参不一致时python会按照已有的类型进行转换(利用.fill()进行传参)
- 数组的类型
通过查看复数数组的实部和虚部会发现有趣的东西:
对于字符串和数字类型结合的Numpy会将他们转化为字符串:
当更复杂的类型混合到一起的时候,Numpy会将他转化为最基本的类型:object
- 数组类型的指定(即在创建数组的时候指定它的类型)
其中,dtype可以接受多种参数如下所示:
类型 | 可用的Numpy类型 | 备注 |
---|---|---|
布尔型 | bool | |
整型 | int8,int16,int32,int64,int128,int | int默认64或者32 |
无符号类型 | uint8,uint16,uint32,uint64,uint128,uint | uint默认64或者32 |
浮点数 | float16,float32,float64,float128,float,longfloat | float默认64 |
复数 | complex64,complex128,complex,longcomplex | complex默认128 |
字符串 | string,unicode | S4表示最长为4 |
对象 | object | 任意类型 |
时间 | datetime,timedelta64 |
其中最常用的就是object,python中所有的对象都是object:
这样的数组同样支持乘法操作:
- 数组类型的转换
利用np.asarray()函数可以将一个对象按照指定的类型转换为N维数组,如下:
1:如果传入的参数是一个数组
不同的是利用np.array()则会产生一个新的数组:
2:指定dtype参数
同样的np.array()可以指定类型,但是区别在于np.asarray()会返回对象本身,而np.array()则是返回一个复制的新数组,这样可能会造成资源浪费
3:用.astype()方法返回一个指定类型的数组
尽管转换的类型相同,它还是会复制一个新的数组出来:
4:利用.view()方法将数组的内存换一种解析方式
(8bit(位)=1Byte(字节))
-
Numpy中的特殊值(不合法数字(np.nan)和无穷大(np.inf))
Numpy的除0操作不会抛出异常,而是返回正负无穷或者非法数字 -
数组的生成
1:将类似数组的对象转化为数组
np.array()还可以将以序列的序列为元素的序列转化为三维数组:
2:产生特定形式的数组
如果想要使用浮点数的情况下保证能包括结尾的元素,那么可以使用.linspace()函数
如果使用了这个函数还是不想要结尾的话,可以加一个额外参数:
我们可以使用np.empty()函数产生一个指定形状和类型的数组,但是它只是让系统分配指定大小的内存,且没有给初始化和里面的值是随机的:
-
数组的索引
1:一维数组的索引(索引和切片统称为索引)
2:多维数组的索引
-
数组的迭代
数组也是一个支持迭代的对象
1:一维数组的迭代
2:多维数组的迭代
这多维数组的迭代和多维列表的迭代一样,每次进行一个维度的迭代,依次递减维度,例如:
我们可以使用.ndenumerate()函数来迭代多维数组中的每一个元素并返回这些元素的索引:
第三部分:数组的操作
-
求和
也可以利用np.sum()方法进行求和,同时这个方法还支持将一个非数组类型的对象进行求和,返回一个数组:
-
求积(同求和一样,不过换成求积)
-
最值(max、min)(亦同求和差不多)
-
最值位置(调用.argmax()、argmin()方法得到)
-
均值(调用.mean()方法)
-
标准差和方差(.std()和.var()方法)
-
数据截断(.clip()方法)
-
近似值(.round()方法)
-
逻辑操作(.any()和.all())(前者是只要有一个元素为真就返回true,后者是当且仅当数组的元素全为真时返回true)
第四部分:数组形状的操作
-
使用.shape属性修改数组的形状
-
使用.reshape()方法改变数组的形状(不改变原数组的,返回一个新数组)
但是设置的参数必须与数组大小相对应,否则抛出异常:
同时这个参数可以设置为负数(-1),当某个维度为-1时,python会自动根据其他维度来计算这个维度:
也可以用np.reshape()实现相同的效果:
-
使用.resize()方法修改数组自身的形状(会改变原本的数组)
解决以上问题可以这样做:
-
增加维度的np.newaxis()方法
-
用.squeeze()方法去除数组中大小为1的维度
-
用.T属性或者.transpose()方法进行数组的转置
对于多维数组的转置则是原来的第一维变成最后一维度,反之也成立:
对于transpose()方法和.T属性差不多:
不同的是,这个transpose()方法在处理维度的转置时可以指定交换任意维度:
-
使用.flat属性或者.flatten()方法和.ravel()方法进行数组降维
1:.flat属性
2:.flatten()方法
3:.ravel()方法
第五部分:数组的拼接操作
1:使用函数np.concatenate()进行拼接
(不指定维度拼接)
(指定维度拼接)
2:使用np.atleast_xd()函数进行拼接
针对上面的函数,它有如下规则:
- 该函数对于大于或等于x维的数组不起作用
- 可以将单个数字转化为一个一维数组
- 对于形状为(N,)的数组,当x=2时就变成(1,N);当x=3时,就变成(1,N,1)
- 对于形状(M,N)的数组,当x=3时就变成(M,N,1)
- 该函数的参数可以接受列表和多维列表,同时支持多个参数同时进行转换,然后返回一个列表
利用上面这些性质,我们可以尝试做低维数组拼接出更高维或者两个形状不同的数组进行拼接:
首先看普通拼接下抛出异常的例子
1:(我们利用np.concatenate()函数对两个形状一样,但是不具备维度为2的数组拼接时抛出异常,原因是a和b数组本身不存在维度2)
2(形状不相同的时抛出异常)
现在我们使用该函数完成这个两个操作:
1:
2:
- 使用函数np.vstack()、np.hstack()、np.dstack()分别进行竖直、水平、深度连接
第六部分:数组的四则运算、点乘和矩阵
-
加减乘除
-
点乘
因为二维数组可以看成一个矩阵,一维数组可以看成是一个向量,所以上面的点乘可以分解成这样:
这个是矩阵乘法规则
上述点乘满足以下规则:
1:形状为(M,N)的数组和形状为(N,P)数组点乘后为一个形状(M,P)的数组
2:形状为(M,N)的数组和形状为(N,)的数组点乘后为一个形状(M,)的数组
3: 两个形状为(N,)的一维数组点乘后为一个标量(向量点积) -
矩阵类型
矩阵是一个特殊的二维数组,可以使用np.mat()函数来构造一个矩阵
可通过np.multiply()函数实现矩阵元素之间的相乘
矩阵还支持幂运算:
第七部分:数组内的数学操作
- 圆周率
- 三角函数
从上图可以看出,这个np.cos()函数将余弦函数作用到了数组的每一个元素上。于此类似的还有以下的函数: - np.sinh(x)、np.conh(x)、np.tanh(x)(双曲正弦、余弦、正切函数)
- np.arccos(x)、np.arctan(x)、np.arcsin(x)(反余弦、正切、正弦函数)
- 等等很多
第八部分:数组的比较和逻辑操作
1:数组和一个数进行比较(下面展示的是<,同理>、>=、<=、==、!=)
2:数组和数组的比较(下面展示的是<=,同上支持其他操作)
3:因为比较后返回的是一个数组,如果想要知道两个数组是否相等,不能使用==来做比较,应该使用np.all()函数:
4:因为浮点数会存在精度问题,所以关于浮点数数组的比较应该使用np.allclose()函数:
第九部分:数组的广播机制
如果我们再改变a的形状呢?
上述这种情况就叫做数组的广播机制,就是两个数组进行二元操作时,Numpy会对他们的形状进行检查,当形状匹配时Numpy会按照一定的队则将两个数组变成两个形状相同的数组再进行二元操作,在广播机制下,两个数组的匹配规则如下:
1:两个数组的形状完全一致
2:两个数组的维度数一样,对于每个维度,两者大小相同,或者其中一个大小为1
3:两个数组的维度数不同时,在低维的数组前增加大小为1的维度直到与较大的数组维度相等为止
根据这三条队则我们就可以解释上面为什么改变a或b的形状结果还是不会改变:
对于第一个a+b,显然他们的形状完全一致:
a:43
b:43
所以根据规则1匹配成功,故而答案是4*3
对于第二个a+b,可以看出b的维度数为1,而a为2,所以根据规则2
a:43
b:03
根据规则2,应该在b前面增加大小为1的维度数
b:1*3
所以答案是4*3
对于第三个a+b,和第二个一样
a:4*1
b:0*3
根据规则2
b:1*3
所以答案是;4*3
第十部分:数组的进阶索引
对于该部分的索引分为两个方面,一个是基础索引,另一个是高级索引
- 基础索引
1:对象是整数
2:对象是slice对象
3:对象是两个的混合对象构成的元组
4利用基础索引修改数组的值
改单个值
用单个数字改一整行
用一维数组改多行
- 高级索引
1:对象时非元组的序列
2:对象是整数或者布尔型的数组
第十二部份:数组的读写
- 数组的读取(使用np.loadtxt()函数)
先新建一个这样的文本
然后读取出来:
如果写文件的时候不是以空格分隔,那么可以在读取的时候指定分割符:
- 数组的写入(使用np.savetxt(),写入时默认用科学计数法保存数字)
可以使用fmt参数修改写入格式:
还可以使用delimiter参数指定分隔符:
- 数组的二进制读写(这个比文本形式读取和写入速度更快)
1:利用np.save(file,arr):保存单个数组,是.npy格式的
2:用np.savez(file,arr),这个是用于保存多个数组,是无压缩的.npz格式
当然我们也可以指定键值:
第十三部份:结构数组
当我希望保存一些像表格一样的信息,例如下面这个表格:
name | age | weight | |
---|---|---|---|
0 | dan | 1 | 23.1 |
1 | ann | 2 | 25.1 |
2 | sam | 0 | 8.3 |
对于上面这些数据,如果直接用数组来保存的话,在输出的时候数字也会变成字符串,这样我们就可以用结构型数组来保存这些数据:
我们可以这样对生成的数组进行各种索引:
使用.itemsize属性查看数组的字节数:
特殊的结构化数组–复数
- 结构化数组的赋值
- 结构化数组的文件读写
这章多维数组终于结束了,比较复杂,最近又要忙java的学习了,实习马上来,我这个蛇皮不知道有没有要呢?