量化分析师的Python日记【第3天:一大波金融Library来袭之numpy篇】
接下来要给大家介绍的系列中包含了Python在量化金融中运用最广泛的几个Library:
numpy
scipy
pandas
matplotlib
会给初学者一一介绍
NumPy 简介
一、NumPy是什么?
量化分析的工作涉及到大量的数值运算,一个高效方便的科学计算工具是必不可少的。Python语言一开始并不是设计为科学计算使用的语言,随着越来越多的人发现Python的易用性,逐渐出现了关于Python的大量外部扩展,NumPy (Numeric Python)就是其中之一。NumPy提供了大量的数值编程工具,可以方便地处理向量、矩阵等运算,极大地便利了人们在科学计算方面的工作。另一方面,Python是免费,相比于花费高额的费用使用Matlab,NumPy的出现使Python得到了更多人的青睐。
我们可以简单看一下如何开始使用NumPy:
import numpy numpy.version.full_version
'1.8.0'
我们使用了"import"命令导入了NumPy,并使用numpy.version.full_version查出了量化实验室里使用的NumPy版本为1.8.0。在往后的介绍中,我们将大量使用NumPy中的函数,每次都添加numpy在函数前作为前缀比较费劲,在之前的介绍中,我们提及了引入外部扩展模块时的小技巧,可以使用"from numpy import *"解决这一问题。
那么问题解决了?慢!Python的外部扩展成千上万,在使用中很可能会import好几个外部扩展模块,如果某个模块包含的属性和方法与另一个模块同名,就必须使用import module来避免名字的冲突。即所谓的名字空间(namespace)混淆了,所以这前缀最好还是带上。
那有没有简单的办法呢?有的,我们可以在import扩展模块时添加模块在程序中的别名,调用时就不必写成全名了,例如,我们使用"np"作为别名并调用version.full_version函数:
import numpy as np np.version.full_version
'1.8.0'
二、初窥NumPy对象:数组¶
NumPy中的基本对象是同类型的多维数组(homogeneous multidimensional array),这和C++中的数组是一致的,例如字符型和数值型就不可共存于同一个数组中。先上例子:
a = np.arange(20)
这里我们生成了一个一维数组a,从0开始,步长为1,长度为20。Python中的计数是从0开始的,R和Matlab的使用者需要小心。可以使用print查看:
print a
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
我们可以通过"type"函数查看a的类型,这里显示a是一个array:
type(a)
numpy.ndarray
通过函数"reshape",我们可以重新构造一下这个数组,例如,我们可以构造一个4*5的二维数组,其中"reshape"的参数表示各维度的大小,且按各维顺序排列(两维时就是按行排列,这和R中按列是不同的):
a = a.reshape(4, 5) print a
[[ 0 1 2 3 4][ 5 6 7 8 9][10 11 12 13 14][15 16 17 18 19]]
构造更高维的也没问题:
a = a.reshape(2, 2, 5) print a
[[[ 0 1 2 3 4][ 5 6 7 8 9]][[10 11 12 13 14][15 16 17 18 19]]]
既然a是array,我们还可以调用array的函数进一步查看a的相关属性:"ndim"查看维度;"shape"查看各维度的大小;"size"查看全部的元素个数,等于各维度大小的乘积;"dtype"可查看元素类型;"dsize"查看元素占位(bytes)大小。
a.ndim
3
a.shape
(2, 2, 5)
a.size
20
a.dtype
dtype('int64')
三、创建数组¶
数组的创建可通过转换列表实现,高维数组可通过转换嵌套列表实现:
raw = [0,1,2,3,4] a = np.array(raw) a
array([0, 1, 2, 3, 4])
raw = [[0,1,2,3,4], [5,6,7,8,9]] b = np.array(raw) b
array([[0, 1, 2, 3, 4],[5, 6, 7, 8, 9]])
一些特殊的数组有特别定制的命令生成,如4*5的全零矩阵:
d = (4, 5) np.zeros(d)
array([[ 0., 0., 0., 0., 0.],[ 0., 0., 0., 0., 0.],[ 0., 0., 0., 0., 0.],[ 0., 0., 0., 0., 0.]])
默认生成的类型是浮点型,可以通过指定类型改为整型:
d = (4, 5) np.ones(d, dtype=int)
array([[1, 1, 1, 1, 1],[1, 1, 1, 1, 1],[1, 1, 1, 1, 1],[1, 1, 1, 1, 1]])
[0, 1)区间的随机数数组:
np.random.rand(5)
array([ 0.29527786, 0.5790265 , 0.80226103, 0.8242678 , 0.4318122 ])
四、数组操作¶
简单的四则运算已经重载过了,全部的'+','-','*','/'运算都是基于全部的数组元素的,以加法为例:
a = np.array([[1.0, 2], [2, 4]]) print "a:" print a b = np.array([[3.2, 1.5], [2.5, 4]]) print "b:" print b print "a+b:" print a+b
a: [[ 1. 2.][ 2. 4.]] b: [[ 3.2 1.5][ 2.5 4. ]] a+b: [[ 4.2 3.5][ 4.5 8. ]]
这里可以发现,a中虽然仅有一个与元素是浮点数,其余均为整数,在处理中Python会自动将整数转换为浮点数(因为数组是同质的),并且,两个二维数组相加要求各维度大小相同。当然,NumPy里这些运算符也可以对标量和数组操作,结果是数组的全部元素对应这个标量进行运算,还是一个数组:
print "3 * a:" print 3 * a print "b + 1.8:" print b + 1.8
3 * a: [[ 3. 6.][ 6. 12.]] b + 1.8: [[ 5. 3.3][ 4.3 5.8]]
类似C++,'+='、'-='、'*='、'/='操作符在NumPy中同样支持:
a /= 2 print a
[[ 0.5 1. ][ 1. 2. ]]
开根号求指数也很容易:
print "a:" print a print "np.exp(a):" print np.exp(a) print "np.sqrt(a):" print np.sqrt(a) print "np.square(a):" print np.square(a) print "np.power(a, 3):" print np.power(a, 3)
a: [[ 0.5 1. ][ 1. 2. ]] np.exp(a): [[ 1.64872127 2.71828183][ 2.71828183 7.3890561 ]] np.sqrt(a): [[ 0.70710678 1. ][ 1. 1.41421356]] np.square(a): [[ 0.25 1. ][ 1. 4. ]] np.power(a, 3): [[ 0.125 1. ][ 1. 8. ]]
需要知道二维数组的最大最小值怎么办?想计算全部元素的和、按行求和、按列求和怎么办?for循环吗?不,NumPy的ndarray类已经做好函数了:
a = np.arange(20).reshape(4,5) print "a:" print a print "sum of all elements in a: " + str(a.sum()) print "maximum element in a: " + str(a.max()) print "minimum element in a: " + str(a.min()) print "maximum element in each row of a: " + str(a.max(axis=1)) print "minimum element in each column of a: " + str(a.min(axis=0))
a: [[ 0 1 2 3 4][ 5 6 7 8 9][10 11 12 13 14][15 16 17 18 19]] sum of all elements in a: 190 maximum element in a: 19 minimum element in a: 0 maximum element in each row of a: [ 4 9 14 19] minimum element in each column of a: [0 1 2 3 4]
科学计算中大量使用到矩阵运算,除了数组,NumPy同时提供了矩阵对象(matrix)。矩阵对象和数组的主要有两点差别:一是矩阵是二维的,而数组的可以是任意正整数维;二是矩阵的'*'操作符进行的是矩阵乘法,乘号左侧的矩阵列和乘号右侧的矩阵行要相等,而在数组中'*'操作符进行的是每一元素的对应相乘,乘号两侧的数组每一维大小需要一致。数组可以通过asmatrix或者mat转换为矩阵,或者直接生成也可以:
a = np.arange(20).reshape(4, 5) a = np.asmatrix(a) print type(a)b = np.matrix('1.0 2.0; 3.0 4.0') print type(b)
<class 'numpy.matrixlib.defmatrix.matrix'> <class 'numpy.matrixlib.defmatrix.matrix'>
再来看一下矩阵的乘法,这使用arange生成另一个矩阵b,arange函数还可以通过arange(起始,终止,步长)的方式调用生成等差数列,注意含头不含尾。
b = np.arange(2, 45, 3).reshape(5, 3) b = np.mat(b) print b
[[ 2 5 8][11 14 17][20 23 26][29 32 35][38 41 44]]
有人要问了,arange指定的是步长,如果想指定生成的一维数组的长度怎么办?好办,"linspace"就可以做到:
np.linspace(0, 2, 9)
array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
回到我们的问题,矩阵a和b做矩阵乘法:
print "matrix a:" print a print "matrix b:" print b c = a * b print "matrix c:" print c
matrix a: [[ 0 1 2 3 4][ 5 6 7 8 9][10 11 12 13 14][15 16 17 18 19]] matrix b: [[ 2 5 8][11 14 17][20 23 26][29 32 35][38 41 44]] matrix c: [[ 290 320 350][ 790 895 1000][1290 1470 1650][1790 2045 2300]]
五、数组元素访问¶
数组和矩阵元素的访问可通过下标进行,以下均以二维数组(或矩阵)为例:
a = np.array([[3.2, 1.5], [2.5, 4]]) print a[0][1] print a[0, 1]
1.5 1.5
可以通过下标访问来修改数组元素的值:
b = a a[0][1] = 2.0 print "a:" print a print "b:" print b
a: [[ 3.2 2. ][ 2.5 4. ]] b: [[ 3.2 2. ][ 2.5 4. ]]
现在问题来了,明明改的是a[0][1],怎么连b[0][1]也跟着变了?这个陷阱在Python编程中很容易碰上,其原因在于Python不是真正将a复制一份给b,而是将b指到了a对应数据的内存地址上。想要真正的复制一份a给b,可以使用copy:
a = np.array([[3.2, 1.5], [2.5, 4]]) b = a.copy() a[0][1] = 2.0 print "a:" print a print "b:" print b
a: [[ 3.2 2. ][ 2.5 4. ]] b: [[ 3.2 1.5][ 2.5 4. ]]
若对a重新赋值,即将a指到其他地址上,b仍在原来的地址上:
a = np.array([[3.2, 1.5], [2.5, 4]]) b = a a = np.array([[2, 1], [9, 3]]) print "a:" print a print "b:" print b
a: [[2 1][9 3]] b: [[ 3.2 1.5][ 2.5 4. ]]
利用':'可以访问到某一维的全部数据,例如取矩阵中的指定列:
a = np.arange(20).reshape(4, 5) print "a:" print a print "the 2nd and 4th column of a:" print a[:,[1,3]]
a: [[ 0 1 2 3 4][ 5 6 7 8 9][10 11 12 13 14][15 16 17 18 19]] the 2nd and 4th column of a: [[ 1 3][ 6 8][11 13][16 18]]
稍微复杂一些,我们尝试取出满足某些条件的元素,这在数据的处理中十分常见,通常用在单行单列上。下面这个例子是将第一列大于5的元素(10和15)对应的第三列元素(12和17)取出来:
a[:, 2][a[:, 0] > 5]
array([12, 17])
可使用where函数查找特定值在数组中的位置:
loc = numpy.where(a==11) print loc print a[loc[0][0], loc[1][0]]
(array([2]), array([1])) 11
六、数组操作¶
还是拿矩阵(或二维数组)作为例子,首先来看矩阵转置:
a = np.random.rand(2,4) print "a:" print a a = np.transpose(a) print "a is an array, by using transpose(a):" print a b = np.random.rand(2,4) b = np.mat(b) print "b:" print b print "b is a matrix, by using b.T:" print b.T
a: [[ 0.73405579 0.26554639 0.35149432 0.55072272][ 0.24976217 0.1432836 0.02280897 0.96363208]] a is an array, by using transpose(a): [[ 0.73405579 0.24976217][ 0.26554639 0.1432836 ][ 0.35149432 0.02280897][ 0.55072272 0.96363208]] b: [[ 0.50191358 0.43575713 0.21853438 0.35257304][ 0.73577449 0.57833658 0.65631312 0.91946705]] b is a matrix, by using b.T: [[ 0.50191358 0.73577449][ 0.43575713 0.57833658][ 0.21853438 0.65631312][ 0.35257304 0.91946705]]
矩阵求逆:
import numpy.linalg as nlg a = np.random.rand(2,2) a = np.mat(a) print "a:" print a ia = nlg.inv(a) print "inverse of a:" print ia print "a * inv(a)" print a * ia
a: [[ 0.24986812 0.64203429][ 0.68509577 0.89203528]] inverse of a: [[-4.11144764 2.95917709][ 3.15765019 -1.15165815]] a * inv(a) [[ 1.00000000e+00 -1.11022302e-16][ 0.00000000e+00 1.00000000e+00]]
求特征值和特征向量
a = np.random.rand(3,3) eig_value, eig_vector = nlg.eig(a) print "eigen value:" print eig_value print "eigen vector:" print eig_vector
eigen value: [-0.32257267 1.51331428 0.71559965] eigen vector: [[-0.23964687 0.65384676 -0.42020057][ 0.88862492 0.47277525 -0.1893484 ][-0.39104365 0.59073512 0.88745629]]
按列拼接两个向量成一个矩阵:
a = np.array((1,2,3)) b = np.array((2,3,4)) print np.column_stack((a,b))
[[1 2][2 3][3 4]]
在循环处理某些数据得到结果后,将结果拼接成一个矩阵是十分有用的,可以通过vstack和hstack完成:
a = np.random.rand(2,2) b = np.random.rand(2,2) print "a:" print a print "b:" print a c = np.hstack([a,b]) d = np.vstack([a,b]) print "horizontal stacking a and b:" print c print "vertical stacking a and b:" print d
a: [[ 0.35141277 0.54723877][ 0.39645303 0.88763732]] b: [[ 0.35141277 0.54723877][ 0.39645303 0.88763732]] horizontal stacking a and b: [[ 0.35141277 0.54723877 0.42007564 0.80002737][ 0.39645303 0.88763732 0.3000728 0.61844297]] vertical stacking a and b: [[ 0.35141277 0.54723877][ 0.39645303 0.88763732][ 0.42007564 0.80002737][ 0.3000728 0.61844297]]
七、缺失值¶
缺失值在分析中也是信息的一种,NumPy提供nan作为缺失值的记录,通过isnan判定。
a = np.random.rand(2,2) a[0, 1] = np.nan print np.isnan(a)
[[False True][False False]]
nan_to_num可用来将nan替换成0,在后面会介绍到的更高级的模块pandas时,我们将看到pandas提供能指定nan替换值的函数。
print np.nan_to_num(a)
[[ 0.18218581 0. ][ 0.26662401 0.05607354]]
NumPy还有很多的函数,想详细了解可参考链接http://wiki.scipy.org/Numpy_Example_List 和http://docs.scipy.org/doc/numpy
最后献上NumPy SciPy Pandas Cheat Sheet
http://q.datayes.com
量化分析师的Python日记【第3天:一大波金融Library来袭之numpy篇】相关推荐
- 量化分析师的Python日记【第4天:一大波金融Library来袭之scipy篇】
####一.SciPy概述 前篇已经大致介绍了NumPy,接下来让我们看看SciPy能做些什么.NumPy替我们搞定了向量和矩阵的相关操作,基本上算是一个高级的科学计算器.SciPy基于NumPy提供 ...
- 量化分析师的Python日记 系列
量化分析师的Python日记 系列 转发,原作者 薛昆Kelvin 为方便学习,整理一下学习材料.持续更新. [第1天:谁来给我讲讲Python?] https://uqer.io/community ...
- 量化分析师的Python日记-CSDN公开课-专题视频课程
量化分析师的Python日记-7882人已学习 课程介绍 以完全初学者的角度入手来认识Python这个在量化领域日益重要的语言. 课程收益 课程先从介绍Python本身一些基本 ...
- 量化分析师的Python日记【Q Quant兵器谱之偏微分方程2】
这是量化分析师的偏微分方程系列的第二篇,在这一篇中我们将解决上一篇显式格式留下的稳定性问题.本篇将引入隐式差分算法,读者可以学到: 隐式差分格式描述 三对角矩阵求解 如何使用scipy加速算法实现 在 ...
- python量化分析系列(第一篇)_量化分析师的 Python 日记 [第 1 天:谁来给我讲讲 Python?]...
45 条回复 • 2016-05-25 11:10:23 +08:00 1 2015-04-08 21:42:42 +08:00 这里竟然有Quant 2 2015-04-08 22:49:51 +0 ...
- 量化分析师的python日记_量化分析师的Python日记【第1天:谁来给我讲讲Python?】...
"谁来给我讲讲Python?" 作为无基础的初学者,只想先大概了解一下Python,随便编个小程序,并能看懂一般的程序,那些什么JAVA啊.C啊.继承啊.异常啊通通不懂怎么办,于是 ...
- 量化分析师的Python日记【第1天:谁来给我讲讲Python?】
作为无基础的初学者,只想先大概了解一下Python,随便编个小程序,并能看懂一般的程序,那些什么JAVA啊.C啊.继承啊.异常啊通通不懂怎么办,于是我找了很多资料,写成下面这篇日记,希望以完全初学者的 ...
- 量化分析师的Python日记【Q Quant兵器谱 -之偏微分方程1】
从今天开始我们将进入一个系列 -- 偏微分方程.作为这一系列的开篇,我们以热传导方差为引子,引出: 如何提一个偏微分方程的初边值问题: 利用差分格式将偏微分方程离散化: 显示差分格式: 显示差分格式的 ...
- 量化分析师的Python日记【Q Quant 之初出江湖】
本篇中,作为Quant中的Q宗(P Quant 和 Q Quant 到底哪个是未来?),我们将尝试把之前的介绍的工具串联起来,小试牛刀. 您将可以体验到: 如何使用python内置的数学函数计算期权的 ...
最新文章
- (转) 理解WebKit和Chromium
- Dynamics 365-关于Solution的那些事(一)
- scp时候出现ssh Connection refused的解决方案
- linux命令11,每日一个linux命令11-more
- OpenGL toon shading卡通着色的实例
- iBatis.Net(C#)SQL数据映射
- shell脚本实现无密码交互的SSH自动登陆
- 堆排序java实例_堆排序(示例代码)
- 程序员谈 JavaScript 数组 Array 的学习
- innodb存储引擎的基本架构
- lopatkin俄大神精简中文系统Windows 7 Professional SP1 7601.24540 x64 ZH-CN LITE10
- DUMP-CX_SY_OPEN_SQL_DB-DBSQL_DUPLICATE_KEY_ERROR
- 华为路由器忘记密码怎么恢复
- html 单元格拆分及合并,一键轻松搞定合并和拆分单元格-excel拆分单元格
- ubuntu18.04未发现wifi适配器,安装wifi无线网卡驱动-RTL8822BE、RTL8822CE、RTL8821CE、RTL8723DE
- 【金明的预算方案】解题报告
- EPSON RC+ 7.0 使用记录一
- IOT-Studio 物联网应用开发实例
- 在c语言中pwm的作用,详细注解的PWM c程序初学者适用
- 【Java爬虫】Jsoup
热门文章
- perl两个构建系统,Makefile.PL/Build.PL
- 普元信息 服务器,普元配置服务器
- 【快直播】libLebConnectionSDK
- ROC曲线详解以及在R中的实现
- shell 脚本处理多行文本的记录 -- awk
- STM32F103VBT6 使用16M晶振和8M晶振 RCC设置有何不同?
- 揭秘家用路由器0day漏洞挖掘技术-Chapter1-读书笔记
- 从0开始安装OpenMediaVault
- 论文阅读《How Does Knowledge Graph Embedding Extrapolate to Unseen Data: A Semantic Evidence View》
- 35岁太年轻,我打算找一批40左右,甚至50岁的产品人聊聊……