NumPy基础:数组和矢量计算

Numerical Python简称,高性能科学计算和数据分析的基础包。几乎所有高级工具的构建基础。部分公能如下:

  • ndarray:一个具有矢量算数运算和复杂广播能力的快速且节省空间的多维数组;
  • 用于对整组数据进行快速运算的标准数学函数;
  • 用于读写磁盘数据的工具以及用于操作内存映射文件的工具;
  • 线性代数、随机数生成以及傅里叶变换功能;
  • 用于集成CC++Fortran等语言编写的代码的工具。

np本身并没有提供很高级的数据分析能力,理解numpy数组以及面向数组的计算有助于更高效的使用类似pandas的工具。

对于大部分数据分析应用而言,最关注的功能主要集中在:

  • 用于数据整理、子集构造和过滤、转换等快速的矢量化数组运算;
  • 常用的数组算法,如排序、唯一化、集合运算等;
  • 高效的描述统计和数据聚合/摘要运算;
  • 用于异构数据集的合并/连接运算的数据对齐和关系型数据运算;
  • 讲条件逻辑表述为数组表达式(而不是带有if-elif-else分支的循环);
  • 数据的分组运算(聚合、转换、函数应用等)。

NumPy的ndarray:一种多维数组对象

  • ndarray对象可以对整块数据执行一些数学运算;
  • 通用的同构数据多维容器,即其中所有元素必须是相同类型的;
  • 每个数组都有一个shape(一个表示各维度大小的元组),和一个dtype(一个用于说明数组数据类型的对象)。

虽然大多数数据分析工作不需要深入理解numpy,但精通面向数组的编程和思维方式很关键。

创建ndarray:

  • 使用array函数:它接受一切序列型的对象(包括数组),然后产生一个新的含有传入数据的NumPy数组;嵌套序列(比如由一组等长列表组成的列表)将会被转换为一个多维数组(维度arr.ndim,各维度arr.shape);除非显示说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型,基本都是float64浮点型(保存在arr.dtype对象中);
  • zeros创建指定长度或形状的全0数组,ones创建全1的数组:np.zeros(10) np.zeros((3,6));
  • empty创建一个没有任何具体值的数组:np.empty((2, 3, 2)) 返回一些未初始化的垃圾值而不是0;
  • arange是Python内置函数range的数组版:np.arange(15);
  • eyeidentity:创建一个正方的N * N矩阵(对角线为1,其余全为0)

ndarray的数据类型:

  • dtype(data type)是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息;dtypenumpy如此强大和灵活的原因之一,多数情况下它们直接映射到相应的机器表示。
  • 可以通过astype方法显式地转换其dtype:arr.astype(np.float64);调用astype无论如何都会创建出一个新数组(==一份拷贝==),即使新dtype和老dtype相同也是如此;

数组和标量之间的运算:

数组可以使不编写循环即可对数据执行批量运算,者通常叫做矢量化。

大小相等的数组之间的任何算数运算都会将运算应用到元素级,数组与标量的算数运算也会应用到元素;

不同大小的数组之间的运算叫做广播(broadcasting)。

基本的索引和切片:

一维数组:

  • 和Python差不多,arr[5] arr[5:8],当将一个标量赋值给一个切片时arr[5:8] = 12该值会自动传播到整个选区;
  • 和列表不同的是,数组切片是原始数组的视图,数据不会被复制,修改直接反映到源数组上;
  • 得到副本:arr[5:8].copy()

高维数组:

  • 在一个二维数组中,各索引位置上的元素不再是标量而是一维数组,因此可以对各个元素进行递归访问:arr2d[0][2]和arr2d[0, 2]等价;
  • 省略索引会返回一个维度低一点的ndarray,数组和标量都可赋值;

切片索引:

  • 数组切片是沿着一个轴向选取元素的,可以一次传入多个切片:arr2d[:2, 1:],但这样只能得到相同维数的数组视图;
  • 将整数索引和切片混合,可以得到低维度的切片:arr2d[1, :2]
  • 对切片表达式的赋值操作也会扩散到整个选区;

布尔型索引:

  • names == 'Bob'产生一个布尔型数组,可用于数组索引,且可以跟切片、整数混用,!= & |
    通过布尔型索引选取数组中的数据,将总是创建数据的副本;
  • data中所有负值都设置为0data[data < 0] = 0

花式索引(Fancy indexing):

指利用整数数组进行索引。

  • 以特定顺序选取行子集,传入一个指定顺序的整数列表或ndarrayarr[[4,3,0,6]],负数从末尾开始选取;
  • 一次传入多个索引数组会返回一个一维数组,其中的元素对应各个索引元组:arr[[1,5,7,2],[0,3,1,2]]选出的是元素(1,0)(5,3)(7,1)(2,2)
  • 花式索引和切片不一样,它总是将数据复制到新数组中;

数组转置(transpose)和轴对换:

  • 转置是重塑的一种特殊形式,返回的是源数据的视图;
  • 数组不仅有transpose方法,还有一个T属性:arr.T,在进行矩阵计算时,经常需要用到该操作;
  • 对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置:arr.transpose((1,0,2));
  • 还有swapaxes方法接受一对轴编号:arr.swapaxes(1,2);swapaxes也是返回源数据的视图;

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

通用函数(ufunc)是一种对ndarray中的数据执行元素级运算的函数。

  • 许多ufunc都是简单的元素级变体:如sqrtexp,这些都是一元(unary)ufunc
  • 接受两个数组(如addmaximum),二元ufunc

利用数组进行数据处理:

用数组表达式代替循环的做法,称作矢量化。比纯python方式快上一两个数量级。

将条件逻辑表达为数组运算:

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

两个值数组xarryarr,一个布尔数组cond,想要根据cond中的值选取xarryarr的值,TruexarrFalseyarr

  • 列表推导式写法:
    result = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]
  • numpy写法:
    result = np.where(cond, xarr, yarr)

数学和统计方法:

可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。

  • summean以及标准差std等聚合计算(aggregation,通常叫做约简reduction)既可以当做数组的实例方法调用:arr.mean(),也可以当做顶级numpy函数使用:np.mean(arr);
    meansum这类的函数可以接受一个axis参数(用于计算该轴向上的统计值),结果是一个少一维的数组:arr.mean(axis=1);
  • 其他如cumsum(累计和)和cumprod(累计积)之类的方法则不聚合,而是产生一个由中间结果组成的数组;

用于布尔型数组的方法:

在以上方法中,布尔值会被强制转换成 1(True)0(False)

  • sum常被用来对布尔型数组中的True计数:(arr > 0).sum()
    bools = np.arry([False, False, True, False])
  • any用于检测数组中是否存在一个或多个Truebools.any();
  • all用于检查数组中所有值是否都是Truebools.all();
    以上两个方法也可用于非布尔型数组,所有 0 元素都会被当做False

排序:

  • sort方法就地排序:arr.sort(),
  • 多维数组可以再任何一个轴向上排序,将轴编号传给sortarr.sort(1);
  • np.sort返回的是数组的已排序副本,而就地排序则会修改数组本身。

唯一化以及其他的集合逻辑:

numpy提供了一些针对一维ndarray的基本集合运算。

  • 最常用的 np.unique(),用于找出数组中的唯一值并返回已排序的结果:
In [2]: names = np.array(['Bob', 'Joe', 'Will', 'Joe', 'Joe'])
In [3]: np.unique(names)
Out[3]: 
array(['Bob', 'Joe', 'Will'],
      dtype='<U4')
np.in1d()用于测试一个数组中的值在另一个数组中的成员资格:
In [4]: values = np.array([6, 0, 0, 3, 2, 5, 6])
In [5]: np.in1d(values, [2, 3, 6])
Out[5]: array([ True, False, False,  True,  True, False,  True], dtype=bool)

用于数组的文件输入输出

numpy能够读写磁盘上的文本数据或二进制数据。

将数组以二进制格式保存到磁盘:

np.savenp.load是读写磁盘数组数据的两个主要函数,默认情况下数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的:

In [6]: arr = np.arange(10)
In [7]: np.save('some_array', arr)
In [8]: np.load('some_array.npy')
Out[8]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 通过np.savez可以将多个数组保存到一个压缩文件中,将数组以关键字参数形式传入:
In [9]: np.savez('array_archive.npz', a=arr, b=arr)
# 加载.npz文件时,会得到一个类似字典的对象,对各个数组进行延迟加载:
In [10]: arch = np.load('array_archive.npz')
In [11]: arch['a']
Out[11]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [12]: arch['b']
Out[12]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

存取文本文件:

  • 以某种分隔符加载文本文件:arr = np.loadtxt('array_ex.txt', delimiter=','')
  • 将数组写到以某种分隔符隔开的文本文件中:np.savetxt(arr, delimiter=',').

线性代数:

线性代数(矩阵乘法、矩阵分解、行列式及其他方阵数学)是任何数组库的重要组成部分。

  • numpy提供了一个用于矩阵乘法(点积)的 dot函数(既是一个数组方法也是numpy命名空间中的一个函数):
In [13]: x = np.array([[1.,2.,3.],[4.,5.,6.]])
In [14]: y = np.array([[6.,23.],[-1,7],[8,9]])

In [15]: x.dot(y)
Out[15]: 
array([[  28.,   64.],
       [  67.,  181.]])

In [16]: np.dot(x, y)
Out[16]: 
array([[  28.,   64.],
       [  67.,  181.]])

numpylinalg中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西。

随机数生成:

numpy.random模块对python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。

python内置random模块一次只能生成一个样本值,numpy.random模块可以产生大量样本值。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容