[关闭]
@Alston 2017-06-21T02:51:18.000000Z 字数 2450 阅读 867

NumPy基础知识

Python量化


python越来越多地应用在量化领域,关键就在于其易用性以及快速处理数据的能力。这能力又是一系列以NumPy、SciPy为基础的科学计算模块赋予的。因此,学习python的量化应用,首先要学习NumPy(而不是前面几篇爬虫技术,不过我比较喜欢纯编程技术类的,所以把爬虫放到前面来讲)。今天就讲讲NumPy的基础知识及应用吧。

NumPy提供了大量的数值编程工具,可以方便地处理向量、矩阵等运算,极大地便利了人们在科学计算方面的工作。使用方面,NumPy跟Matlab很相似,可以看作Matlab的免费替代品,对于版权意识比较强不想用盗版Matlab的同学来说,Python是一门性欲比很高的语言。(当然也可以用Scilab等其他软件)

数组

NumPy的基础对象有两个:ndarray和ufunc,ndarray是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数(即对ndarray中每个数据进行操作的函数,知道概念就好了,用的时候跟普通函数一样用法)。
可以通过给array函数传递list变量创建数组,如果传递的是多层嵌套的序列,将创建多维数组(list长度必须一样):

  1. import numpy as np
  2. a = np.array([1,2,3,4,5])
  3. b = np.array([[1,2,3,4,5],[6,7,8,9,10]])
  4. print("a:\n",a)
  5. 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)查看有哪些属性。

  1. print("变量类型: ", a.dtype)
  2. print("数组维数: ", b.shape)
变量类型:  int32
数组维数:  (2, 5)

如果想要改变ndarray的维数,有两种做法,一种是用reshape方法、一种是直接改shape值(当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度):

  1. a = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]]) # 这是一个3*4的ndarray
  2. b = a.reshape((4,3))
  3. print("b:\n", b) # 改成4*3
  4. a.shape = 2,-1 # 改成行数为2的ndarray
  5. print("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也会跟着变:

  1. b[0,2] = 4 # 把b的第一行第三个数3改为4
  2. # 可以写成b[2]=4
  3. # 按行排列,跟R语言的按列排列不同
  4. print("a:\n", a) # a也变了
a:
 [[ 1  2  4  4  4  5]
 [ 6  7  7  8  9 10]]

原因是ndarray本质上都是一维的数组,只是根据需要“变”成了多维的而已。

创建ndarray

除了通过list生成ndarray外,还可以用一些特殊的函数来生成需要的数组:

  1. a = np.arange(0,10,2) # 相当于range
  2. print("a:\n", a)
  3. b = np.linspace(0, 10, 10) # 相当于matlab的linspace
  4. print("b:\n", b)
  5. c = np.logspace(0, 2, 10) # 生成10^0到10^2范围内的等比数列,长度为10
  6. print("c:\n", c)
  7. d = np.zeros((4,5)) # 生成4*5的全零数组,默认是浮点型
  8. print("d:\n", d)
  9. e = np.ones((3,4),dtype=int) # 生成3*4的全1数组,整数型
  10. print("e:\n", e)
  11. f = np.random.rand(5) # 生成0到1范围内的5个随机数
  12. 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语言类似:

整数序列

当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。

  1. x = np.arange(10,1,-1)
  2. print(x[[3, 3, 1, 8]])
[7 7 9 2]

布尔数组

当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。

  1. x = np.arange(5,0,-1)
  2. print(x[np.array([True, False, True, False, False])]) # 只能用布尔ndarray,如果直接用list,会把True当作1,False当作0
  3. print(x[x>2]) # 这是更常用的方法,跟R一样
[5 3]
[5 4 3]

鉴于推文的长度,今天先讲这么多。下次接着讲NumPy的矩阵运算。

本文主要参考官方文档量化分析师的Python日记

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注