NumPy基础:数组与向量化计算

  安装numpy及使用

  pip install numpy

  PyCharm无法使用numpy

  File-->setting-->项目名-->Project Interpreter-->本地安装python-->应用

  测试代码

  import numpy as npdata = np.random.randn(2,3)print(data)

  numpy简介

  作用

  ndarry,一种高效多维数组,提供了基于数组的边界算术操作及灵活的广播功能

  对所有数据进行快速的矩阵计算,而无需编写循环程序

  对硬盘中数组数据进行读写的工具,并对内存映射文件进行操作

  线性代数、随机数生成以及傅里叶变换功能

  用于连接NumPy到C、C++和FORTRAN语言类库的C语言API

  数据分析应用

  在数据处理。清洗、构造子集、过滤、变换以及其他计算中进行快速的向量化计算。

  常见的数组算法,比如sort、unique以及set操作等

  高效的描述性统计和聚合/概述数据

  数据排列和相关数据操作,例如对异构数据进行merge和join

  使用数组表达式来表明条件逻辑,代替if-elif-else条件分支的循环

  分组数据操作(聚合、变换以及函数式操作)

  python数组计算历程

  Python中的数组计算方式要追溯到1995年,当时Jim Hugunin创造Numeric库。之后10年里,许多科研编制社区开始利用Python进行数组编程,但类库的生态在2000年之后都是碎片化的。2005年,Travis Oliphant在Numeric和Numarray项目之上打造了NumPy,将社区整合到用一个数组计算框架下。

  NumPy重要原因

  NumPy在内部将数据存储在连续的内存块上,这与其他的Python内建数据结构是不同的。NumPy的算法库是用C语言写的,所以在操作数据内存时不需要任何类型检查或者其他管理操作。NumPy数组使用的内存量也小于其他Pyhon内建序列。

  Numpy可以针对全量数组进行复杂计算而不需要写Python循环。

  性能对比代码

  # NumPy性能和Python常规对比start = time.time()my_arr = np.arange(1000000)my_arr = my_arr * 2end = time.time()print('Running time: %s Seconds'%(end-start))start = time.time()my_list = list(range(1000000))my_list = my_list * 2end = time.time()print('Running time: %s Seconds' % (end - start))

  NumPy ndarray:多维数组对象

  ndarray

  NumPy的核心特征之一就是N-维数组对象--ndarray。ndarray是Python中一个快速、灵活的大型数据集容器。数组允许你使用类似于标量的操作语法在整块数据上进行数学计算。

  一个ndarray是一个通用的多维同类数据容器,也就是说,他包含的每一个元素均为相同类型。每一个数组都有一个shape属性,用来表征数组每一维度的数量;每一个数组都有一个dtype属性,用来描述数组的数据类型。

  生成ndarray

  生成数组最简单的方式就是使用array函数。array函数接收任意的序列型对象(当然也包括其他的数组),生成一个新的包含传递数据的NumPy数组。

  属性

  ndim 数组纬度

  shape 数组纬度和数量

  dtype 数组类型

  数组生成函数

  array 将输入数据(可以是列表、元组、数组以及其他序列)转换为ndarray,如不显式指明数据类型,将自动判断;默认复制所有的输入数据。

  asarray 将输入转换为ndarray,但如果输入已经是ndarray则不再复制

  arange Python内建函数range的数组版,返回一个数组

  ones 根据给定形状和数据类型生成全1数组

  ones_like 根据所诶数组生成一个形状一样的全1数组

  zeros 根据给定形状和数据类型生成全0数组

  zeros_like 根据所给的数组生成一个形状一样的全0数组

  empty 根据给定形状生成一个没有初始化数值的空数组

  empty_like 根据所给数组生成一个形状一样但没有初始化数值的空数组

  full 根据给定的形状和数据类型生成指定数值的数组

  full_like 根据所给的数组生成一个形状一样但内容是指定数值的数组

  eye,identity 生成一个N*N特征矩阵(对角线位置都是1,其余位置都是0)

  使用np.empty 来生成一个全0数组,并不安全,有些时候他可能会返回未初始化的垃圾数值

  ndarray数据类型

  数据类型即dtype,是一个特殊的对象,他包含了ndarray需要为某一种类型数据所申明的内存块信息(也称为元数据,即表示数据的数据)

  通常不需要担心如何记住NumPy数据类型,尤其当你还是新手的时候。通常你只需要关系数据的大类,比如浮点型、整数、布尔值、字符串或者某个Python对象。当你需要在内存或者硬盘上做更深入的存取操作时,尤其大数据集时,你才真正需要了解存储的数据类型。

  数据类型

  int8,uint8 类型代码il,ul 有符号和无符号的8数位整数

  int16,uint16 类型代码i2,u2 有符号和无符号的16数位整数

  int32,uint32 类型代码i4,u4 有符号和无符号的32数位整数

  int64,uint64 类型代码i8,u8 有符号和无符号的64数位整数

  float16 类型代码f2 半精度浮点数

  float32 类型代码f4或f 标准单精度浮点数;兼容C语言float

  float64 类型代码f8或d 标准双精度浮点数;兼容C语言double和Python float

  float128 类型代码f16或g 拓展精度浮点数

  complex64,complex128,complex256 类型代码c8,c16,c32 分别基于32位、64位、128位浮点数的复数

  bool 类型代码? 布尔值,存储True或False

  object 类型代码O Python object类型

  string_ 类型代码S 修正的ASC II 字符串类型;例如生成一个长度为10的字符串类型使用S10

  unicode_ 类型代码U 修改的Unicode类型,生成一个长度为10的Unicode类型使用U10

  浮点数转换成整数则小数点后的部分将被消除

  在NumPy中,当使用numpy.string_类型作字符串数据要小心,因为NumPy会修正他的大小或者删除输入切不发出警告。pandas在处理非数值数据时有更直观的开厢型操作

  使用astype时总生成一个新的数组,即使你传入的dtype与之前一样

  NumPy数组算术

  数组之所以重要是因为他允许你进行批量操作而无需任何for循环,NumPy用户称这种特性为向量化

  带有标量计算的算术操作,会把计算参数传递给数组的每个元素

  同尺寸数组之间的比较,会产生一个布尔值数组

  不同尺寸的数组间的操作,将会用到广播特性,将会在附录A中介绍。

  基础索引与切片

  数组切片是原数组的视图,意味着数据并不是被复制了任何对于视图的修改都会反应在原数组上

  如果你还是想要一份数组切片的拷贝而不是一份视图的话,你就必须显式地复制这个数组。arr[5:8].copy()

  在一个二维数组中,每个索引值对应的元素不是一个值而是一个一维数组。

  在多维数组中,你可以省略后续索引值,返回对象将是降低一个维度的数组

  数组切片索引

  数组延着轴0进行切片,表达式arr[:2]的含义为选择arr的前两行

  如果将索引和切片混合,就可以得到维度的切片

  注意:单独一个冒号标识选择整个轴上的数组

  arr[:2, 1:] 从开始到第二行,从第一列到最后一列

  arr[2] 第三行数据

  arr[2,:] 第三行数据

  arr[2:,:] 第三行数据

  arr[:,:2] 所有行数据和首列到第二列

  布尔索引

  布尔值数组的长度和数组轴索引长度一致。你甚至还可以用切片或者整数值对布尔值数组进行混合匹配

  当布尔值数组的长度不正确时,布尔值选择数据的方法并不会报错,因此建议在使用该特性要注意

  为了选择除条件以外的其他数据,你可以使用!=或者在条件表达式前使用~对条件取反

  使用布尔值索引选择数据时,总是生成数据的拷贝,即使返回的数组并没有任何变化。

  Python中的关键字and或or对布尔值数据并没有用,要使用&(and)和|(or)来代替

  神奇索引

  神奇索引时NumPy中的术语,用于描述使用整数数组进行数据索引。

  神奇搜索与切片不同,他总是将数据复制到一个新的数组中。

  正数数组从前索引,负数数组从后索引

  数组转置和换轴

  转置是一种特殊的数据重组形式,可以返回底层数据的视图而不需要复制任何内容。数组拥有transpose方法,也有特殊的T属性。

  T属性就是数据反转

  计算矩阵内积会使用np.dot

  对于更高维度数组,transpose方法可以接收包含轴编号的元组,用于置换轴。

  使用.T进行转置是换轴的一个特殊案例,ndarray有一个swapaxes方法,该方法接收一个对轴编号作为参数,并对轴进行调整用于重组数据

  swapaxes返回的是数据视图,而没有对数据进行复制

  通用函数:快速的逐元素数组函数

  含义

  通用函数,也可以称为ufunc,是一种ndarray数据中进行逐元素操作的函数。

  某些简单函数接收一个或者多个标量数值,并产生一个或者多个标量结果,而通过函数就是对这些简单函数的向量化封装

  一元通用函数

  abs、fabs 逐元素地计算整数、浮点数或者复数的绝对值

  sqrt 计算每个元素的平方根(与arr ** 0.5相等)

  square 计算每个元素的平方(与arr ** 2相等)

  exp 计算每个元素的自然数指数值ex

  log、log10、log2、log1p 分别对应:自然数对数(e为底)、对数10位底、对数2为底、log(1+x)

  sign 计算每个元素的符号值:1(整数)、0(0)、-1(负数)

  ceil 计算每个元素的最高整数值(即大于等于给定数值的最小整数)

  floor 计算每个元素的最小整数值(即小于等于给定元素的最大整数)

  rint 将元素保留整数位,并保持dtype

  modf 分别将数组的小数部分和整数部分按数组形式返回

  isnan 返回数组中的元素是否是一个NaN(不是一个数值),形式为布尔值数组

  isfinite、isinf 分别返回数组中的元素是否有限(非inf、非NaN)、是否无线的,形式为布尔值数组

  cos、cosh、sin、sinh、tan、tanh 常规的双曲三角函数

  arccos、arccosh、arcsin、arcsinh、arctan、arctanh 反三角函数

  logical_not 对数组的元素按位取反(与~arr效果一致)

  二元通用函数

  add 将数组的对应元素相加

  subtract 在第二个数组中,将第一个数组中包含的元素去除

  multiply 将数组的对应元素相乘

  divide、floor_divide 除或者整除(放弃余数)

  power 将第二个数组的元素作为第一个数组对应元素的幂次方

  maximum、fmax 逐个元素计算最大值,fmax忽略NaN

  minmum、fmin 逐个元素计算最小值,fmin忽略NaN

  mod 按元素的求摸计算(即求除法的余数)

  copysign 将第一个数组的符号值改为第二个数组的符号值

  greater、greater_equal、less、less_equal、equal、not_equal 进行逐个元素的比较,返回布尔值数组(与数学操作符>、>=、<、<=、==、!=效果一致)

  logical_and、logical_or、logical_xor 进行逐个元素的逻辑操作(与逻辑操作符&、|、^效果一致)

  使用数组进行面向数组编程

  含义

  使用NumPy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无需写些大量循环。这种利用数组表达式来替代显式循环的方法称为向量化

  向量化的数组操作会比纯Python的等价实现在速度上快一到两个数量级(甚至更多),这对多有种类的数值计算产生了最大的影响

  将条件逻辑作为数组操作

  numpy.where函数是三元表达式 x if condition else y的向量化版本

  np.where 的第一个参数是条件,第二个和第三个参数并不一定是数组可以是标量

  where在数据分析中一个典型的用法是根据一个数组来生成一个新的数组

  传递给np.where的数组即可以是同等大小的数组,也可以是标量

  数学和统计方法

  许多关于计算整个数组统计值或者关于轴向数据的数学函数,可以作为数组类型的方法被调用。你可以使用聚合函数(通常也叫缩减函数),比如sum、mean和std(标准差),即可以直接调用数组实例的方法,也可以使用顶层的NumPy函数。

  基础数组统计方法

  sum 沿着轴向计算所有元素的累和,0长度的数组,累和为0

  mean 数学平均,0长度的数组平均值为NaN

  std、var 标准差和方差,可以选择自由度调整(默认分母n)

  min、max 最小值和最大值

  armin、armax 最小值和最大值的位置

  cumsum 从0开始元素累积和

  cumprod 从1开始元素累积积

  布尔值数组的方法

  布尔值会被强制为1(True)和0(False)。

  可以通过sum用于计算布尔值数组中True的个数

  any检查数组中是否至少有一个True

  all检查是否每个值都是True

  排序郑州人流医院 http://m.zzzy120.com/

  和Python的内建列表类型相似,NumPy数组可以使用sort方法按位置排序。

  在多维数组中根据传递的axis值,沿着轴向对每个一维数据段进行排序

  顶层的np.sort方法返回的是已经排序号的数组拷贝,而不是对原数组按位置排序

  唯一值与其他集合逻辑

  NumPy包含一些针对一维ndarray的基础集合操作。

  数组集合操作

  unique(x) 计算x的唯一值并排序

  intersect1d(x,y) 计算x和y的交集,并排序

  union1d(x,y) 计算x和y的并集,并排序

  inld(x,y) 计算x中的元素是否包含在y中,返回一个布尔值数组

  setdiff1d(x,y) 差集,在x中但不在y中的x元素

  setxor1d(x,y) 异或集,在x或y中,但不属于x、y交集的元素

  使用数组进行文件输入和输出

  NumPy可以在硬盘中将数据以文本或者二进制文件的形式进行存入银盘或者由硬盘载入。

  大部分用户更倾向于与使用pandas或者其他工具来载入文本或者表格型数据

  np.save和np.load是高效存取硬盘数据的两大工具函数。数组在默认情况下是以未压缩的格式进行存储的,后缀名.npy

  压缩好的数据可能会想要使用numpy.savez_compressed将数据存入已经压缩的文件中

  线性代数

  线性代数比如矩阵乘法、分解、行列式等方阵数学,是所有数组类库的重要组成部分

  NumPy的线性代数中所不同的是 * 是矩阵的逐元素乘积而不是矩阵的点乘积,因此NumPy的数组方法和numpy命名空间中都有一个函数dot

  numpy.linalg 拥有一个矩阵分解标准的函数集,以及其他常用函数。

  数组.T.dot(数组) 计算的是数组和它的转置矩阵数组.T的点乘积

  特殊符号@也作为中缀操作符,用于点乘矩阵操作

  常用numpy.linalg函数

  diag 讲一个方阵的对角(或非对角)元素作为一维数组返回,或者将一维数组换成一个方阵,并且在非对角线上又零点

  dot 矩阵点乘

  trace 计算对角元素和

  eig 计算方阵的特征值和特征向量

  inv 计算方阵的逆矩阵

  pinv 计算矩阵的Moore-Penrose伪逆

  qr 计算QR分解

  svd 计算奇异值分解(SVD)

  solve 求解x的线性系统Ax = b ,其中A是方阵

  lstsq 计算Ax = b 的最小二乘解

  伪随机数生成

  numpy.random模块填补了Python内建在random模块的不足,可以高效地生成多种概率分布下的完整样本值数组

  Python内建random模块一次中能生成一个值

  伪随机数他们是由具有确定性行为的算法根据随机数生成器中的随机数种子生成,可以通过np.random.seed更改NumPy的随机数种子

  numpy.random中的数据生成函数使用一个全局随机数种子。为了避免全局状态,你可以使用numpy.random.RandomState创建一个随机数生成器,使数据独立于其他的随机数状态

  numpy.random中的部分函数

  seed 向随机数生成器传递随机状态种子

  permutation 返回一个序列的随机排列,或者返回一个乱序的整数范围序列

  shuffle 随机排列一个序列

  rand 从均匀分布中抽取样本

  randint 根据给定的由低到高的范围抽取随机整数

  randn 从均值0方差1的正态分布中抽取样本(MATLAB型接口)

  binomial 从二项分布中抽取样本

  normal 从正态(高斯)分布中抽取样本

  beta 从beta分布中抽取样本

  chisquare 从卡方分布中抽取样本

  gamma 从伽马分布中抽取样本

  uniform 从均匀[0,1)分布中抽取样本

  示例:随机漫步

  随机漫步模型提供了一个适用数组操作的说明性应用

  一次性模拟多次随机漫步

  # 模拟多次随机漫步,比如说5000步,如果传入一个2个元素的元组# numpy.random中的函数可以生成一个二维抽取数组,并且我们可# 以一次性地跨行计算出全部5000个随机不的累积和n = 5000ns = 1000d = np.random.randint(0,2,size=(n,ns))s = np.where( d > 0,1,-1)w = s.cumsum(1)print(w)# 现在我们可以计算出这些随机步的最大值和最小值print(w.max())print(w.min())# 让我们在这些随机步中计算出30或者-30的最小穿越时间。这有点辣手# 因为我们不是所有的5000都达到了30.我们可以使用any方法来检查hi30 = (np.abs(w) >= 30).any(1)print(hi30)print(hi30.sum())# 我们可以使用布尔值数组来选出绝对不输超过30的步所在的行,并使用# argmax从轴向1上获取时间c_time = (np.abs(w[hi30]) >= 30).argmax(1)print(c_time.mean())