Numpy的对象是同质的多维数组,数组的元素属于同一类型,数组索引是一个正整数元组。在numpy中,维度即是轴。
Numpy的数组类叫做ndarray。ndarray类有如下一些属性:
1、 ndarray.ndim:数组轴的个数。
2、 ndarray.shape:数组的维度,这是一个整数元组,元组的元素表明了数组的每一个维度的大小。元组的元素个数即是维度的数目。
3、 ndarray.size:数组元素的个数。
4、 ndarray.dtype:一个描述数组元素的类型的对象,通常为int32,int16,float64。
5、 ndarray.itemsize:每一个元素所占的字节数。
6、 ndarray.data:数组中实际元素的备份。通常无需使用这个属性,因为我们可以直接使用索引来访问数组中的元素。
创建数组
创建数组有以下几种方式:
1、 从Python的列表或者元组来创建数组,需要使用函数array(),这个函数返回一个ndarray类的对象;调用这个函数时常见的错误是使用一系列的数字来调用,而不是一个序列(列表或者元组);使用函数array()创建数组时,包含序列的序列会被转换为二维数组,含有多个包含序列的序列会被转换为三维数组。在创建数组时,数组元素的类型可以被指定。
2、 在创建数组时,通常我们知道数组的大小,但是不知道数组的具体元素,我们可以创建一个指定大小的数组,其元素全部为0或1。ones()函数可创建一个元素全部为0的数组,调用这个函数时,需要将数组的维度以元组形式传入,如:ones((2,3))创建了一个2行3列的二维数组,ones((2,3,4))创建了一个2层3行4列的数组;zeros()函数与ones()类似,可以创建一个初始元素全为0的数组,其调用方法与ones()相同,在调用这个函数时也可以指定元素的类型。empty()函数可以创建一个初始值由内存状态决定的随机的数组。
3、 函数arange()可以创建一个数字序列,这一点同python里的函数range()类似;不同的是range()函数返回的是一个列表,而arange()函数返回的是一个一维数组。arange()函数在调用时可以指定起始起始值和终止值以及步长。由于浮点数在存储时的精度有限,因此在传入函数arange()的参数为浮点数的情况下,数组中的元素个数可能无法预测。linspace()函数为我们解决了这个问题,linspace()的第三个参数是元素的个数,而不是步长,这样数组的元素个数就是我们想要的个数。
打印数组
第一行从左到右输出;每行依次自上而下输出;每个切片通过一个空行与下一个隔开;一维数组被打印成行,二维数组成矩阵,三维数组成矩阵列表。
基本运算
1、 数组的算术运算是逐元素的,例如:加、减、乘、除。算术运算会创建一个新的数组,并以算术运算的结果来填充这个新的数组。
2、 需要注意的是,在numpy里,*(乘法)也是逐元素的,如果需要实现矩阵乘法,需要使用矩阵点乘函数dot(),如:A.dot(B)表示矩阵A与矩阵B做矩阵乘法运算,也可以表示为np.dot(A,B)。
3、 +=,*=等运算则是直接在原数组的基础上做修改,并不会创建新的数组。
4、 当不同类型的数组做运算时,运算的结果会与更精确的那个类型相关(向上转换)。
5、 许多一元运算,如求数组元素的和,求最大值,最小值等,将这个运算作为ndarray这个类的一个方法来使用,如:A.sum()。这种运算似乎将这个数组当作一个列表来处理,然而你也可以在运算时指定轴的值,此时运算将会沿着特定的轴进行。
通用函数
Numpy提供了例如sin、cos、exp等函数,在numpy中他们被称为通用函数。这些函数对数组逐元素运算,产生一个数组作为输出。
索引、分片和迭代
1、 一维数组可以进行索引、分片和迭代,类似于列表和python中的其他序列。
2、 多维数组中每一个轴有一个索引,可以使用多个索引。当给定的索引数目比数组的维度小时,其他丢失索引的维度上被认为是访问整片。例如对于一个二维数组B,B[1]与B[1,:]相同,即访问第一行的所有元素。也可以在索引中写省略号,下面的这些写法效果是相同的:x[1,2,...]和x[1,2,:,:,:];x[...,3]和x[:,:,:,:,3];x[4,...,5,:]和 x[4,:,:,5,:]。
3、 多维数组的迭代在数组的第一个轴上进行,例如:B[[0,1,2,3],[4,5,6,7]],for row in B:print(row),打印结果是逐行打印的。
4、 可以使用flat属性来逐个访问数组中的元素,B.flat是一个遍历B中所有元素的迭代器。
形状操作
1、 改变数组的形状有多种方法,下面这三种方法返回一个经过修改的数组,但原数组未发生改变。ravel()方法返回一个展开的一维数组;reshape()方法返回一个修改过的数组,在这个方法中需要指定改变后的形状,即每一维度上的长度,改变形状后数组的元素个数不能发生改变,否则会报错;T属性,返回数组的转置。
2、 resize()函数返回经过修改的数组,但不是创建一个新的数组,而是在原数组上改变。
3、 reshape()函数中如果指定一个参数为-1,则这个维度的长度会自动计算。
拷贝和视图
1、 完全不拷贝:简单的赋值不会拷贝数组对象和它们的数据;
2、 视图和浅拷贝:视图方法会创建一个新数组对象,这个新对象看向原数组中的数据,对创建的这个新对象变换形状不会改变原数组的形状,但是由于新对象和原数组对象共享相同的数据,因此如果对新数组对象中的元素做更改,原数组中的元素也会发生相应的改变;
3、 深拷贝:完全复制原数组及其数据,这是两个不同的数组,对新数组做的任何操作都不会影响到原数组。
广播规则
每一个通用函数以数组作为输入,通过逐元素的运算输出一个数组。标准的广播规则被应用到不同形状的输入数组,这样这些不同形状的输入数组就可以进行运算了。广播的四个规则:
1、 维度较小的数组会在前面追加一个长度为 1 的维度。
2、 输出数组的每个维度的大小是输入数组该维度大小的最大值。
3、 如果输入在每个维度中的大小与输出大小匹配,或其值正好为 1,则在计算中可它。
4、 如果输入的某个维度大小为 1,则该维度中的第一个数据元素将用于该维度的所有计算。
如果一些数组经过上面的规则广播后可以产生有效的结果,那么这些数组就是可被广播的,例如:
1、 所有的数组拥有相同的形状;
2、 所有的数组有相同的维度,并且每一个维度的长度是相同的或者是1;
3、 维度太少的数组可以通过追加维度并使追加维度的长度为1;
索引技巧
1、 使用索引数组进行索引,当被索引的数组是一个多维数组时,单值索引会指向数组的第一个维度;
2、 我们也可以在多个维度上进行索引,此时这多个索引数组的形状必须是相同的(P19),只需将这多个数组写成列表的形式即可索引;
3、 argmax()方法可以取出数组中的最大值的索引,在方法中可以指定轴,沿着某一个方向去寻找最大值;
4、 使用数组索引进行赋值,但是当索引中有重复的值时,元素会被重复赋值,元素最终的结果是最后一次赋值的结果;
5、 使用布尔型数组索引,布尔型索引用的较多的是与原数组有着相同形状这样的数组,使用这样的布尔型索引数组可以挑选原数组中的一些值并进行操作,如访问、赋值、;我们也可以使用一维的布尔型数组来选取数组中我们想要的部分;需要注意的是,这个一维数组的长度必须要和待选取的数组相应维度一致;
6、 ix_():接收n个一维数组作为输入,这n个数组的形状可以不同,其输出为一个元组,元组的元素个数为n,每一个元素都是一个n维数组;假设输入的第k个一维数组的长度为m,那么这个数组的形状为(1,1,…,m,…1),即第k个维度的长度为m,其他维度上的长度为1;
线性代数
Numpy中含有线性代数模块,可以很方便地使用它来进行矩阵计算。
其他
1、 数组形状变换时,可以将其中的一个维度的长度指定为-1,程序会自动计算这个维度的长度;
2、 可以使用numpy绘制直方图,对于给定的一个数组,使用histogram()函数后会返回一组向量,一个是直方图,另一个是bins。关于bins的官方文档解释是这样的:if bins is an int, it defines the number of equal-width bins in the given range (10, by default). If bins is a sequence, it defines the bin edges, including the rightmost edge, allowing for non-uniform bin widths.在matplotlib中也有绘制直方图的功能,但是numpy中的功能与之是由区别的,区别在于:matplotlib会自动绘制直方图,而numpy不会,需要我们使用matplotlib中的命令来绘制直方图。