@Alston
2017-06-21T02:51:18.000000Z
字数 2450
阅读 867
Python量化
python越来越多地应用在量化领域,关键就在于其易用性以及快速处理数据的能力。这能力又是一系列以NumPy、SciPy为基础的科学计算模块赋予的。因此,学习python的量化应用,首先要学习NumPy(而不是前面几篇爬虫技术,不过我比较喜欢纯编程技术类的,所以把爬虫放到前面来讲)。今天就讲讲NumPy的基础知识及应用吧。
NumPy提供了大量的数值编程工具,可以方便地处理向量、矩阵等运算,极大地便利了人们在科学计算方面的工作。使用方面,NumPy跟Matlab很相似,可以看作Matlab的免费替代品,对于版权意识比较强不想用盗版Matlab的同学来说,Python是一门性欲比很高的语言。(当然也可以用Scilab等其他软件)
NumPy的基础对象有两个:ndarray和ufunc,ndarray是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数(即对ndarray中每个数据进行操作的函数,知道概念就好了,用的时候跟普通函数一样用法)。
可以通过给array函数传递list变量创建数组,如果传递的是多层嵌套的序列,将创建多维数组(list长度必须一样):
import numpy as npa = np.array([1,2,3,4,5])b = np.array([[1,2,3,4,5],[6,7,8,9,10]])print("a:\n",a)print("b:\n",b)
a:
[1 2 3 4 5]
b:
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
可以查看ndarray的变量类型dtype、维数shape等属性,可以用dir(a)查看有哪些属性。
print("变量类型: ", a.dtype)print("数组维数: ", b.shape)
变量类型: int32
数组维数: (2, 5)
如果想要改变ndarray的维数,有两种做法,一种是用reshape方法、一种是直接改shape值(当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度):
a = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]]) # 这是一个3*4的ndarrayb = a.reshape((4,3))print("b:\n", b) # 改成4*3a.shape = 2,-1 # 改成行数为2的ndarrayprint("a:\n", a)
b:
[[ 1 2 3]
[ 4 4 5]
[ 6 7 7]
[ 8 9 10]]
a:
[[ 1 2 3 4 4 5]
[ 6 7 7 8 9 10]]
这里需要注意的是,虽然看上去a数组被变动了,但是实际上a和b是同一个变量,如果改变b的值,a也会跟着变:
b[0,2] = 4 # 把b的第一行第三个数3改为4# 可以写成b[2]=4# 按行排列,跟R语言的按列排列不同print("a:\n", a) # a也变了
a:
[[ 1 2 4 4 4 5]
[ 6 7 7 8 9 10]]
原因是ndarray本质上都是一维的数组,只是根据需要“变”成了多维的而已。
除了通过list生成ndarray外,还可以用一些特殊的函数来生成需要的数组:
a = np.arange(0,10,2) # 相当于rangeprint("a:\n", a)b = np.linspace(0, 10, 10) # 相当于matlab的linspaceprint("b:\n", b)c = np.logspace(0, 2, 10) # 生成10^0到10^2范围内的等比数列,长度为10print("c:\n", c)d = np.zeros((4,5)) # 生成4*5的全零数组,默认是浮点型print("d:\n", d)e = np.ones((3,4),dtype=int) # 生成3*4的全1数组,整数型print("e:\n", e)f = np.random.rand(5) # 生成0到1范围内的5个随机数print("f:\n", f)
a:
[0 2 4 6 8]
b:
[ 0. 1.11111111 2.22222222 3.33333333 4.44444444
5.55555556 6.66666667 7.77777778 8.88888889 10. ]
c:
[ 1. 1.66810054 2.7825594 4.64158883 7.74263683
12.91549665 21.5443469 35.93813664 59.94842503 100. ]
d:
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]
e:
[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]
f:
[ 0.98134181 0.33911958 0.50097573 0.77695307 0.82603383]
跟list一样,ndarray也可以用下标、切片等方式访问元素,但是要注意,用切片得到的数据跟原ndarray共享一块内存,所以改动其中一个,另一个也会跟着变。
此外,NumPy还提供了两种高级访问元素的方式。跟matlab或R语言类似:
当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。
x = np.arange(10,1,-1)print(x[[3, 3, 1, 8]])
[7 7 9 2]
当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。
x = np.arange(5,0,-1)print(x[np.array([True, False, True, False, False])]) # 只能用布尔ndarray,如果直接用list,会把True当作1,False当作0print(x[x>2]) # 这是更常用的方法,跟R一样
[5 3]
[5 4 3]
鉴于推文的长度,今天先讲这么多。下次接着讲NumPy的矩阵运算。
本文主要参考官方文档和量化分析师的Python日记