Numpy是数值计算最重要的基础包
部分功能如下:
①一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组
②用于对整租数据进行快速运算的标准数学函数
③用于读写磁盘数据的工具以及用于操作内存映射文件的工具
④线性代数、随机数生成以及傅里叶变换功能
⑤用于集成C、C++、Fortran等语言编写的代码的AC API
①用于数据整理和清理、子集构造和过滤、转换等快速的矢量化数组运算
②常用的数组算法。如排序、唯一化、集合运算等
③高效的描述统计和数据聚合、摘要运算
④用于异构数据集得到合并/连接运算的数据对齐和关系型数据运算
⑤将条件逻辑表述为数组表达式(而不是带有if-elif-else分支循环)
⑥数据的分组运算(聚合、转换、函数应用等)
Numpy可以高效处理大数组的数据:
①是在一个连续的内存块中存储数据,独立于其它Python内置对象。比起Python的内置序列,Numpy数组使用的内存更少。
②可以在整个数组上执行复杂计算,而不需要for循环
很明显的差距在于
以下代码中涉及np均为numpy的重命名
NP重要的特点就暗示其N维数组对象(Ndarry)
该对象是一个快速而灵活的大数据集容器。
shape(一个表示各维度大小的元组)
dtype(一个用于说明数组数据类型的对象)
①创建数组最简单是利用array函数
②产生一个新的含有传入数据的Numpy数组
示例为以一个列表的转换为例
嵌套序列(转换为一个多维数组)
ndim:查看维度
zeors和ones分别可以创建指定长度或者形状的全0或者全1的数组
empty可以创建一个没有任何具体值的数组(都是一些未初始化的垃圾值)
要用这些方法创建多维数组。只需要传入一个表示形状的元组即可:
arange是python内置函数range的数组版
如果没有特别指定,数据类型基本都是float64(浮点数)
dtype(是一个特殊的对象):ndarray将一块内存解释为特定数据类型所需的信息
通过ndarray的astype方法明确地将一个数组从一个dtype转换成另一个dtype:
浮点数–>整数
小数部分将被删除
字符表示数字–>数值形式
矢量化(vectorization):数组使我们不用编写循环即可对数据执行批量运算。大小相等的数组之间的任何算术运算会将运算应用到元素级:
Numpy数组的索引是一个内容丰富的主题,因为选取数据子集或者单个元素的方式有很多。其基本功能与Python的列表功能差不多:
上图所示如果将一个标量值赋值给一个切片时,该值会自动传播。也就是数据不会被复制,视图上的任何修改都会直接反应到源数组上
注:跟列表最重要的区别在于,数组切片是原始数组的视图
如果想要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作:
arr[5:8].copy
二维数组中,各索引位置上的元素不再是标量而是看作一维数组
如果需要单个访问
创建一个2* 2 * 3的3维数组:
对三维数组仍可以赋值
注:如何对三维数组进行索引赋值
访问索引以(1,0)开头的值(一维数组的形式返回)
ndarray的切片语法与Python列表这样的一维对象差不多:
二维数组arr2d
就是切片是沿着一个轴向选取元素的。也就是选取arr2d的前两行
可以一次传入多个切片,就像传入多个索引:
第二行,前两列
第三列,前两行
假设一个用于存储数据的数组和一个存储姓名的数组
布尔型数组的长度必须与被索引的轴长度一致。否则就会出错
可以使用不等号符号(!=),也可以通过~对条件进行否定:
~操作符的另类用法
通过一维布尔数组设置正行或者列的值
是一个Numpy的术语。即是利用整数数组进行索引
如果以特定选取行子集,只需要传入一个用于指定顺序的整数列表或者ndarray即可
一次传入多个索引数组会有一点特别。返回的是一个一维数组
最终命令选取的是元素(1, 0), (5, 3), (7, 1), (2, 2)
无论数组使多少维,花式索引总是一堆
花式索引的行为可能会跟用户预期不一样,选取矩阵的行列子集应该是矩阵区域形式
转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作)
数组还有一个特殊属性T
在进行矩阵计算时,经常需要用到此操作。如np.dot计算矩阵內积
而对于高维数组,transpose需要得到一个由轴编号组成的元组才能对轴进行转置
ndarray还有一个方法,那么它需要的则是接受一对轴编号
通用函数(ufanc)是一种对ndarray中的数据执行元素级运算函数。也可以看做简单函数(接受一个或者多个标量值,并产生一个或者多个标量值)的矢量化包装器
有很多ufunc都是简单的元素级变体 sqrt和exp
这些都是一元(unary) ufunc 另外一些(add maximum) 接受2个数组(也叫二元(binary) ufunc)
有些ufunc可以返回多个数组。modf就是一个例子,它是Python内置函数divmod的矢量化版本,它会返回浮点数数组的小数和整数部分:
Numpy数组可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环)
数组表达式代替循环的做法通常被称为矢量化(矢量化数组运算要比等价的纯Python方式快上一两个数量级)
np.meshgrid函数接受两个一维数组,并产生两个二维矩阵
对z进行可视化:
numpy.where函数是三元表达式x if condition else y的矢量化版本
假设一个布尔数组和两个值数组:
从cond中的值选取xarr和yarr的值:当cond中的值为True时,选取xarr,否则yarr
问题:
①对大数组的处理速度不是很快
②无法用于多维数组
如果使用numpy中的where则会简单的多
也就是根据条件condition返回x, y的值
以下是where的源码解释
np.where第二第三个不必是数组,可以是标量值
where通常用于根据另一个数组而产生一个新的数组
假设我一个随机数据组成的矩阵。
正值->2
负值->-2
除此之外,我们还可以将标量和数组结合起来
使用常数2替换arr中所有正的值
传递给where的数组大小可以不相等,甚至可以是标量值
np.where(arr > 2, 2 ,arr)
array([[ 1.35292807, -1.69130737, -0.63246009, 0.47447935],
[-2.24412903, 1.33376022, 2. , -0.9872501 ],
[-1.05792462, 1.89962045, -1.00555539, 0.03813778],
[-1.00300124, -0.98632211, 2. , -0.79404154]])
可以通过数组上的一组数学函数对整个数组或者某个轴向的数据进行统计计算。sum、mean(平均值)以及标准差std等聚合计算(aggregation, 通常叫做简约(reduction)),既可以当做数组的实例方法调用,也可以当做顶级numpy函数使用。
arr = np.random.randn(5, 4)
arr
array([[ 0.21929806, 0.82766319, -0.19853262, -0.48856812],
[-0.57560005, -0.5690485 , 0.76227888, -1.89554634],
[ 0.94413424, 0.34954764, 0.96017848, 0.67297606],
[ 1.00209404, -1.92063271, 0.13285016, -0.63891863],
[-0.73532205, 0.21795081, -1.72661335, -2.06045955]])
arr.mean()
-0.23601351804108656
np.mean(arr)
-0.23601351804108656
arr.sum()
-4.720270360821731
mean和sum这类函数可以接受一个axis选项参数,用于计算该轴向上的统计值,最终结果是一个少一维的数组:
arr.mean(axis=1)
array([ 0.08996513, -0.569479 , 0.73170911, -0.35615179, -1.07611104])
arr.sum(axis = 0)
array([ 0.85460424, -1.09451957, -0.06983845, -4.41051658])
以上两行代码 arr.mean(1)是计算行的平均值 arr.sum(0)计算每列的和
其他如cumsum何cumprod之类的方法则不聚合,而是产生一个由中间结果组成的数组:
arr = np.array([1, 2, 3, 4])
arr.cumsum()
array([ 1, 3, 6, 10], dtype=int32)
在多维数组中,累加函数(如cumsum)返回的是同样大小的数组。但是会根据每个低维切片沿着标记轴计算部分聚类:
上述的方法中,布尔值会被强制转化为1(True)和0(Flase)
因此,sum经常被用来对布尔型数组中的True值计数
还有两个方法any和all,对布尔型数组很有用
any用于测试数组中是否存在一个或者多个True,而all则检查数据中所有值是否都为True
与python内置的列表类型相同,Numpy数组可通过sort排序
多维数组可以在任何一个向上进行排序,只需要将轴编号传给Sort即可
顶级方法np.sort返回的是数组已排序副本,而就地排序则会修改数组本身
计算数组分位数最简单的办法就是对其进行排序,然后选取特定位置的值
Numpy提供了一些针对一维ndarray的基本集合运算
np.unique 用于找出数组汇中的唯一值并返回已排序的结果
np.in1d用于测试一个数组中的值在另一个数组中的成员资格,返回的是布尔型的数组
np.save和np.load是读写磁盘数组数据的两个主要函数
默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件
np.savez可以将多个数组保存到一个未压缩文件中,将数组以关键字参数的形式传入即可
然后加载.npz文件时,会得到一个类似字典的对象,对象会对各个数组进行延迟加载
线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分
numpy提供了一个用于矩阵乘法的dot函数(矩阵乘法)
x.dot(y) = np.dot(x, y)
一个二维数组跟一个大小合适的一维数组的矩阵点积运算之后将会得到一个一维数组
也可使用 x @ np.ones(3)
diag 以一维数组的形式返回方阵对角线,或将一维数组转换为方阵
dot 矩阵乘法
trace 计算对角线元素的和
det 计算矩阵行列式
eig 计算方阵的本征值和本征向量
inv 计算方阵的逆
pinv 计算矩阵的Moore-Penrose伪逆
qr 计算QR分解
svd 计算奇异值分解(SVD)
solve 解线性方程组Ax=b,其中A为一个方阵
lstsq 计算Ax=b的最小二乘解
numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数
使用normal来得到一个标准正态分布4*4样本数组
python内置的random模块智能一次生成一个样本值。从下面的测试结果汇总可以看出,如果需要产生大量样本值,numpy.random快了不止一个数量级
numpy.random的数据生成函数使用了全局的随机种子
如果要避免全局状态,可以使用numpy.random.RandomState创建一个与其他隔离的随机数生成器
通过模拟随机漫步来说明如何运算数组运算。
首先从0开始,步长1和-1出现的概率相等
通过一个random模块以纯python的方式实现1000步的随机漫步
`import matplotlib.pyplot as plt`
`import random`
`position = 0`
`walk = [position]`
`steps = 1000`
`for i in range(steps):`
`step = 1 if random.randint(0, 1)else -1`
`position += step`
`walk.append(position)`
`plt.plot(walk[:100])`
其实漫步就是各步的累计和,可以用一个数组运算来实现
np.random模块一次性随机产生100个抛硬币的结果,两数中任选一个
将其分别设置为1或者-1,然后计算累计和
根据这些数据,也可以沿着漫步路径做一些统计工作,如求取最大最小值
nsteps = 1000
draws = np.random.randint(0, 2, size = nsteps)
steps = np.where(draws > 0, 1, -1)
walk = steps.cumsum()#表示本行之前的数之和加至本行
假设我们想要知道本次随机漫步需要多久才能距离初始0点至少10步远(任一方向均可)
(np.abs(walk) >= 10).argmax()
上述代码可以得到一个布尔型数组,他表示的是距离是否达到或者超过10
argmax返回的就是该布尔型数组第一个最大值的索引(True就是最大值)
如果希望模拟多个随机漫步过程(如5000)
只需要给numpy.random的函数传入一个二元元祖就可以产生一个二维数组,然后就可以一次性计算5000个随机漫步过程(一行一个)
所有随机漫步过程汇总的最大值最小值
walks.max()
110
walks.min()
-127
我们可以使用any方法对此进行检查
我们利用这个布尔型数组选出了哪些穿越30(绝对值)的随机漫步,并调用了argmax在轴1上获取穿越时间