ndarray简介
多维数组对象(ndarray)在运算上非常灵活,同长度的数组之间运算为各对应元素间的运算,而数组与标量间的运算,则会把标量应用至数组内的每个元素。
一个ndarray 内所有元素类型一致
ndarray创建
np.array() 及np.asarray 可以接受格式各样的数据,列表字典数组或其它序列类型
np.array()及np.asarray()间的区别在于,当传入的数据本身为一个数组时np.asarray()是不会对其复制的。(暂时没想明白asarray这种特性使用的实际场景)
np.zero(), np.ones(), np.empty() 分别创建全0,全1,全空的数组(空不是0)。此外还有np.ones_like()等用于以其它对象限定shape。
np.arange() 与np.array(range()) 结果一致,但是range的步长为小数时会报错。
ndarray数据类型
这一部分感觉不需要了解太多,用一般的数据类型int, float, str, bool就可以,python会帮你匹配好对应格式。
使用astype可以转换dtype。(创建新的数组,不管dtype有没有变,跟前文np.array是一样的)
当数组本身为float类型时,使用astype转换则小数部分会被去除。
如果数组为str类型,而表示的全是数字,可用astype转换为数值。(就是excel里文本类型单元格的转换为数字功能)
ndarray基本索引及切片
ndarray的切片可直接赋值一个标量,广播到整个切片,这是list无法做到的。
数组的切片是一个视图,对其做的任何改变都会反映在原数组上,而list的切片则是副本,如果要对数组复制为副本,则需使用copy()。
注意上例中以b[:] 来表示对b的切片选取,直接写b = 2的话是直接重新定义变量b。
高维数组的索引切片:
简单的理解,高维数组的索引是从高维到低维选取的。
实际上a[1,2] 的选取是等价于 a[1][2]的。
布尔值索引
之前提到的索引方式都是基于数据所在位置进行选取,工作中遇到的很多条件筛选是基于判断的,比如说大于100,或者说是否是17年内的。这种时候需要用布尔值索引选取。
比如一组数中选取大于100的。
本质是a > 100 本身产生了一组布尔值的数组,随后a[a > 100]选取了True索引对应的值。比如说我又另一组50个的数组b,则可以选取这个a > 100的条件,去看看对应的b的值是多少。
这里顺便提一下,书上P93上的图4-2,其中shape那里有几个shape是(3,)这样表示的,可能会感到疑惑,我这个shape明明是一维的呀。实际上这是因为shape是tuple,而tuple是不能接受(3)这种形式的,否则就是产生数字(list就没有这种限制)。当然,你可以使用tuple([3]),这样的话产生的结果就是(3,)。
书上94页在否定这里写的是负号表示条件否定,现在被波浪号替代了,记得用括号把条件圈起来,尤其是涉及& | 的时候务必看清楚。(and or 在布尔型数组中无效)
此处注意,通过布尔型选出的数据,为数据副本。
花式索引
在一维上,花式索引实际上就是指可以不连续、无顺序的取多个索引值。
对于多维数组,花式索引为索引元素间一一对应的选取。看文字可能比较难以理解,其实看代码表现形式就很容易。
很容易理解,此处选取的即[1,2], [3,4], [5,6] 三个数。而如果想要1,3,5行和2,4,6行的交叉取出的矩形,则应把行列分开选取:
或者使用np.ix_(跟pandas中的ix相似)
花式索引的结果为副本。
数组转置与轴对换
二维的转置比较简单,很容易理解。
对于多维数组的转置,感觉书上写的不是很清楚。其实就是把原有的轴重新排序,比如说一个三维数组,他的原有的轴就是(0,1,2), 转置为(1,0,2)时, 即把原先索引为(2,1,3)的数,转移到(1,2,3)的位置上。而直接使用T属性,即为转置为反向索引(0,1,2)转置为(2,1,0)
看a.transpose((0, 2, 1)的输出结果可以看到,最高纬度不变,二三维做了个转置。
T即所有轴反向排列。
ndarray 的swapaxes方法,接受一对轴编号,将这两个轴互换。
注意:所有的转置操作都是返回一个源数据的视图。
通用函数
通用函数就是应用于整个数组内的所有元素的函数,这个跟人的思维习惯比较相符,你写代码的时候肯定更愿意写abs(array) 而不是 nd.array([abs(i) for i in array])
具体函数名称不用多看,根据需求在遇到的时候搜索下即可。
利用数组进行数据处理
这里有个很方便的函数:np.where,使用方式跟excel的if一致,很实用。
布尔值在数学计算中会被强制转换为0、1,所以可以通过这个特性直接给筛选值计数。
ndarray的排序和list一样,可以通过sort方法就地排序。
若只想创建一个副本,则需要使用函数np.sort
唯一化及其它集合逻辑
去重:unique
选取交集:intersect1d
选取并集:union1d
查看从属关系(元素):in1d(x,y) x中的元素在y中是否包含的布尔数组。
选取集合差:setdiff1d(x, y) 在x中,不在y中的元素集合。
选取集合对称差:setxor1d(x, y) 在一个集合,且不在另一集合的元素集合。
文件输入输出
np.save保存单数组,np.savez保存多数组。save保存后缀默认npy,savez默认保存后缀npz,savez保存的时候将数组类似于字典进行保存。
用np.load读取npz文件时,输出结果为一段内存代码,需要通过索引调取的形式展示内容。
线性代数
之前提过,shape相同的ndarray之间的加减乘除是元素级的,如果想要对矩阵进行点积,则要使用dot函数。
随机数
np.random.seed(),书上的说法是确定随机数生成器的种子。举个例子,我每次输入np.random.randn(5),每次产生的数组是不一致的。而每次输入np.random.seed(5);np.random.randn(5) 产生的结果会是一模一样的。但要注意,在每次产随机数前都加上seed,否则除第一组随机数外,后续的随机数并不由seed指定。
np.random.permutation,接受一个序列或一个数字(数字其实默认代表的np.arange(x)),对其重排,不会影响原有序列。shuffle只能接受序列,就地随机排列。
np.random.rand产生均匀分布样本值,np.random.randint产生范围内整数随机值,np.random.randn产生正态分布样本值。np.random.normal也产生正太分布,主要区别在于normal可调节scale,即正太分布那个峰的胖瘦。
np.random.randn(5)实际上与np.random.normal(loc = 0, scale = 1,size = (1, 5)) 是一致的。np.random.uniform产生设定上下限的均匀分布样本值。np,random.rand(5) 与 np.random.uniform(low = 0, high = 1, size = (1, 5))一致。
随机漫步
这个地方不难理解,照着书上敲就可以明白。书中xrange在python3里被整合到range去了,还有书中random.randint(0, 1)不知道在python2中是否取值是[0,1]中的整数,在python3中,取值是[0,1),这样会导致照着书得到的结果是一条斜率为-1的直线,改成random,randint(0, 2)就好了。另外可以学习下这里if的用法,比较简便一些。
.