文章目录
简介
Numpy
NumPy是Python的一种开源的数值计算扩展,可用来存储和处理大 型矩阵,比Python自身的列表结构要高效得多。NumPy底层使用 BLAS 作为向量,各种运算的速度也得到大幅提升。它主要包括:
-
强大的N维数组对象Array;
-
比较成熟的(广播)函数库;
-
用于整合C、C++和Fortran代码的工具包;
-
实用的线性代数、傅里叶变换和随机数生成函数,使 NumPy 和 稀疏矩阵运算包SciPy的配合使用更加方便。 另外,NumPy中的数据类型在 Pandas、Scikit-Learn、StatsModels 等库中被作为基本数据类型使用。
Pandas
Python 之所以能成为强力的数据分析工具,和 Pandas 库有很大的 关系。Pandas 的主要应用环境如下:
-
数据的导入与导出;
-
数据清理;
-
数据挖掘与探索;
-
为分析做数据处理与准备;
-
结合Scikit-Learn、StatsModels进行分析。
用得最多的Pandas对象是DataFrame,它是一个两维数据 表结构,包含多行多列。
相对于 R等统计软件,Pandas借鉴了 R的数据结构,因此拥有了 R 的很多方便的数据操作特性;在语法设计上,Pandas比R和Stata更严谨 且更简洁易用;基于Python自动管理内存的能力,以及在很多细节上的 优化(比如在数据操作过程中的数据复制和引用),Pandas拥有了更好 的管理和计算大数据的能力。
Pandas的底层基于NumPy搭建,因此Pandas拥有了NumPy的全部优 点,比如Pandas定义的数据结构可以支持NumPy已经定义的计算,相当 于拥有了MATLAB的矩阵计算能力;NumPy原生的C接口也为扩展 Pandas的计算性能带来了很大的方便。 对于金融用户来讲,Pandas提供了一系列适用于金融数据的高性能 时间序列与工具,例如Panel、时间Series等。
Matplotlib
Matplotlib是Python最著名的绘图库,提供了一整套和MATLAB相 似的命令API,十分适合进行交互式制图。我们也可以很方便地将它作 为绘图控件,嵌入GUI应用程序中Matplotlib 的文档相当完备,而且在 Gallery 页面中有上百幅缩略图,打开后都有源程序。因此,如果需要绘制某种类型的图,则只需在这个页面中浏览、 复制、粘贴,就基本可以搞定。
Seaborn
Seaborn其实是在Matplotlib的基础上进行了更高级的API封装,从而 使作图更容易。在大多数情况下使用 Seaborn 就能制作出非常有吸引力的图,而使用Matplotlib就能制作出具有更多特色的图。但是应该把Seaborn视为Matplotlib的补充,而不是替代物。
Seaborn默认的浅灰色背景与白色网络线的灵感来源于Matplotlib, 却比Matplotlib的颜色更加柔和。我们发现,图对于传播信息很有用, 几乎在所有情况下,人们喜欢图更甚于表。
SciPy
SciPy 包含致力于解决科学计算中常见问题的各个工具箱。它的不 同子模块相当于不同的应用,例如插值、积分、优化、图像处理、特殊 函数等。SciPy可以与其他标准科学计算程序库进行比较,比如GSL(GNU C或C++科学计算库)或者 MATLAB 工具箱。SciPy 是Python 中科学计 算程序的核心包,用于有效地计算NumPy矩阵,让NumPy和SciPy协同 工作。
Scikit-Learn
Scikit-Learn 是基于 Python 的机器学习模块,基于 BSD 开源许可 证。Scikit-Learn 的基本功能主要被分为6部分:分类、回归、聚类、数 据降维、模型选择和数据预处理,具体可以参考官方网站上的文档。
对具体的机器学习问题的解决,通常可以分为三步:
-
数据准备与预处理;
-
模型选择与训练;
-
模型验证与参数调优。
Scikit-Learn 封装了这 些步骤,使建模的过程更方便、简单和快捷。
Numpy 基础教程
安装
pip install numpy
numpy 的引用
import numpy as np
使用 ndarray 创建数组
NumPy 的主要对象是 ndarray,该对象是一个快速、灵活的大数据容器。在此需要注意,在ndarray与Python中内置的list、tuple并不相同。在Python中,元素的数据类型可以不同;而在ndarray中,所有元素的数据类型必须相同。
data1 = [1,2,3,4]
data2 = [5,6,7,8]
arr1 = np.array(data1)
arr1
Output:
array([1, 2, 3, 4])
创建一个 4 × 2 数 组 4 \times 2 数组 4×2数组
arr2 = np.array([data1,data2])
arr2
Output:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
创建全0的数组
np.zeros((3,3))
Output:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
创建全1的数组
np.ones((3,3))
Output:
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
创建1-10 且为 2 的等差数列
np.arange(1,10,2)
Output:
array([1, 3, 5, 7, 9])
创建1-10且长度为4的等差数列
np.linspace(1,10,4)
Output:
array([ 1., 4., 7., 10.])
数组索引、切片、赋值
索引切片的操作类似于Python的内置函数list,只不过是从一维拓展到多维而已。首先,我们创建一个 3 × 3 3 \times 3 3×3 的 ndarray:
arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2
Output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
选取行
arr2[1]
Output:
array([4, 5, 6])
选取给定的行列值
arr2[1,1]
Output:
5
选取前几行
arr2[:2]
Output:
array([[1, 2, 3],
[4, 5, 6]])
选取前几行与前几列
arr2[:2,:2]
Output:
array([[1, 2],
[4, 5]])
基本的数组运算
ndarray 的一大特色就是可以将代码向量化。所谓向量化,就是对 一个复杂的对象进行整体操作,而不是对其中的单个元素进行循环。NumPy 的大部分代码都是由 C 语言编写的,并且进行了高度优化,这 大大加快了计算速度。
简单的数学运算可以直接在ndarray上运行,例如:
arr3 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr3
Output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
矩阵的加法
arr3 + arr3
Output:
array([[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]])
矩阵中对应元素相乘
arr3 * arr3
Output:
array([[ 1, 4, 9],
[16, 25, 36],
[49, 64, 81]])
矩阵中每一个元素乘以系数
arr3 * 2
Output:
array([[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]])
矩阵中每一个元素进行幂运算
arr3 ** 0.5
Output:
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974],
[2.64575131, 2.82842712, 3. ]])
在 NumPy 中还有一些内置的数学函数,可以帮助我们快速地对数
据进行统计计算,比如sum、max、mean、std等。
求和:
arr3.sum()
Output:
45
求标准差:
arr3.std()
Output:
2.581988897471611
求最大值:
arr3.max()
Output:
9
基本的数组统计方法
方法 | 说明 |
---|---|
sum | 对数组的全部或者轴向数据求和 |
mean | 算术平均数 |
std var | 标准差,方差 |
min max | 最大值和最小值 |
argmin argmax | 最小元素和最大元素的索引 |
cumsum cumprod | 所有元素累计求和 所有元素累计求积 |
随机数
NumPy还可以用来生成伪随机数,负责这一功能的是其子库 numpy.random。
首先,导入 numpy.random。为了更直观地展示随机数的生成过程,这里同时导入了Matplotlib,以将结果可视化:
import numpy.random as npr
import matplotlib.pyplot as plt
%matplotlib inline
例如,npr.rand函数可以用来生成 [ 0 , 1 ) [0,1) [0,1)的随机多维数组:
npr.rand(3,2)
Output:
array([[0.45788024, 0.57343845],
[0.2763168 , 0.68187916],
[0.91109262, 0.40315501]])
通过简单的线性变换,即可将将随机区间转化为 [ 2 , 4 ) [2,4) [2,4)
npr.rand(3,2)*2+2
Output:
array([[3.06512178, 2.78121736],
[3.06268945, 3.4561032 ],
[3.08663582, 2.52355033]])
下表展示了生成简单随机数的函数及其参数和描述。
函数 | 参数 | 描述 |
---|---|---|
round | d0,d1 | 生成半开区间 [ 0 , 1 ) [0,1) [0,1)内的多维随机数 |
randn | d0,d1 | 生成来自正态分布的多个样本 |
randint | low,high,size | 生成半开区间 [ l o w , h i g h ) [low,high) [low,high)内的随机样本整数 |
chioce | a,size,raplace,p | 生成在给定的一维数组中的随机样本 |
size = 1000
rn1 = npr.rand(size,2)
rn2 = npr.randn(size)
rn3 = npr.randint(0,10,size)
rang = [0,10,20,30,40]
rn4 = npr.choice(rang,size = size)
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows = 2, ncols = 2, figsize = (10, 10))
ax1.hist(rn1, bins = 25, stacked = True)
ax1.set_title('rand')
ax1.set_ylabel('frequency')
ax1.grid(True)
ax2.hist(rn2, bins = 25)
ax2.set_title('randn')
ax2.grid(True)
ax3.hist(rn3, bins = 25)
ax3.set_title('randint')
ax3.set_ylabel('frequency')
ax3.grid(True)
ax4.hist(rn4, bins = 25)
ax4.set_title('choice')
ax4.grid(True)
许多金融模型,例如 BSM 模型、跳跃扩散模型、平方根扩散模型等,都依赖于正态分布。我们可以通过生成相应的随机数,来将原本连续的金融模型离散化,从而进行近似模拟。在npr.random模块中内置了很多分布函数,具体内容可以查阅NumPy的文档。
作为例子,我们将如下分布的随机数进行可视化。
- n=100、P=0.3的二项分布。
- 均值为10、标准差为2的正态分布。
- 自由度为0.5的卡方分布。
- λ为2的泊松分布。
rn5 = npr.binomial(100, 0.3, size)
rn6 = npr.normal(10, 20, size)
rn7 = npr.chisquare(0.5, size)
rn8 = npr.poisson(2.0, size)
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows = 2, ncols = 2, figsize = (10, 10))
ax1.hist(rn5, bins = 25)
ax1.set_title('binomial')
ax1.set_ylabel('frequency')
ax1.grid(True)
ax2.hist(rn6, bins = 25)
ax2.set_title('normal')
ax2.grid(True)
ax3.hist(rn7, bins = 25)
ax3.set_title('chisquare')
ax3.set_ylabel('frequency')
ax3.grid(True)
ax4.hist(rn8, bins = 25)
ax4.set_title('poisson')
ax4.grid(True)
Pandas 基础教程
Pandas 是基于 NumPy 衍生出的一种工具,用于解决数据分析问 题,它纳入了大量的库和一些标准的数据模型,提供了可用于高效操作 大型数据集的工具,是使 Python 成为强大而高效的数据分析工具的重 要因素之一。
安装
pip install dataframe
Pandas 引用
import pandas as pd
Pandas 数据结构
Pandas 的数据结构主要分为三种:Series(一维数组)、 DataFrame(二维的表格型数据结构)和Panel(三维数组)。
Series
Series指一维数组,与 NumPy中的一维 Array类似。Series、Array与 Python基本的数据结构List也很相近,其区别是:在List中的元素可以是 不同的数据类型,而在Array和Series中则只允许存储相同的数据类型, 这样可以更有效地使用内存,提高运算效率,Series增加了对应的标签(label)以用于索引,可以包含0个或者多 个任意数据类型的实体。其中,标签索引赋予了Series强大的存取元素 功能。除通过位置外,Series还允许通过索引标签进行元素存取:
obj = pd.Series([40,12,-3,25])
obj
Output:
0 40
1 12
2 -3
3 25
dtype: int64
Series 的字符串表现形式为:索引在左边,值在右边。因为在建立 过程中没有指定索引,所以Python会自动为我们加入一个0~n的整数索 引,我们可以通过数字获取具体位置上的元素:
obj[0]
Output:
40
可以通过index与values获取Series的索引与数据:
obj.index # 获取索引
obj.values
Output:
array([40, 12, -3, 25], dtype=int64)
当然,也可以在Series建立时就指定索引:
obj = pd.Series([40,12,-3,25],index = ['a','b','c','d'])
obj
Output:
a 40
b 12
c -3
d 25
dtype: int64
可以直接通过索引获取数值:
obj['c']
Output:
-3
对于Series的各种计算,其结果也会保留index:
obj[obj>15]
Output:
a 40
d 25
dtype: int64
另外,Series可以被转换为字典:
obj.to_dict()
Output:
{'a': 40, 'b': 12, 'c': -3, 'd': 25}
DataFrame
DataFrame 指二维的表格型数据结构。在 DataFrame 有很多功能与 R 中的 data.frame类似,我们可以将DataFrame理解为Series的容器,也 就是说,在DataFrame中,多个Series共用了一个索引index。 在以字典或Series的字典的结构构建DataFrame时,最外面的字典对 应DataFrame的列,内嵌的字典及Series则是其中的每个值,例如:
d = {'one':pd.Series([1,2,3],index=['a','b','c']),
'two':pd.Series([1,2,3,4],index=['a','b','c','d'])}
df = pd.DataFrame(d)
df
Output:
one | two | |
---|---|---|
a | 1.0 | 1 |
b | 2.0 | 2 |
c | 3.0 | 3 |
d | NaN | 4 |
从字典的列表中构建 DataFrame 时,其中的每个字典代表的是每条 记录(DataFrame中的一行),字典中每个值对应的是这条记录的相关 属性。同时可以看到,当由多个Series组成DataFrame时,Pandas会自动按 照index对齐数据,如果某个Series的index缺失,则Pandas会将其自动填 写为np.nan。
Pandas 输出设置
在 Pandas 中可以通过 set_option 设置 Pandas 的输出格式,例如最 多显示的行数、列数等:
pd.set_option('display.max_rows',1000) # 显示的最大列数
pd.set_option('display.max_columns',20) # 显示的最大列数
pd.set_option('precision',7) # 显示小数点后的位数
pd.set_option('large_repr','truncate')
Pandas 数据的读取与写入
Pandas可以方便地读取本地文件如csv、txt、xlsx等,例如:
a = pd.read_csv('closeprice.csv')
a
Output:
Unnamed:0 | ticker | secShortName | tradeDate | closePrice | |
---|---|---|---|---|---|
0 | 0 | 1 | 平安银行 | 2017/6/20 | 9.12 |
1 | 1 | 2 | 万科A | 2017/6/20 | 21.03 |
2 | 2 | 4 | 国农科技 | 2017/6/20 | 27.03 |
3 | 3 | 5 | 世纪星源 | 2017/6/20 | 5.45 |
4 | 4 | 6 | 深振业A | 2017/6/20 | 8.87 |
5 | 5 | 7 | 全新好 | 2017/6/20 | 15.87 |
我们可自行输入pd.read_,使用代码补全功能查看Pandas可以读取的数据类型。
同理,可以使用to_,将DataFrame输出到文件中:
DataFrame 排序
data = pd.DataFrame({'group':['a','a','a','b','b','b','c','c','c'],'ounce':[4,3,12,6,7.5,8,3,5,6]})
data.sort_values(by=['group','ounce'],inplace=True)
上述代码的作用就是先按照group降序排列,当group相同时再按照 ounces升序排列。参数中的 inplace=True 直接将排序后的结果存在 data,即直接用排序好的数据覆盖原始数据。
DataFrame 去重
在大多数时候,在数据中会有重复的数据,在做分析前需要进行去 重
data = pd.DataFrame({'k1':['one']*3+['two']*4,'k2':[3,2,1,3,3,4,4]})
data
Output:
k1 | k2 | |
---|---|---|
0 | one | 3 |
1 | one | 2 |
2 | one | 1 |
3 | two | 3 |
4 | two | 3 |
5 | two | 4 |
6 | two | 4 |
data.drop_duplicates()
Output:
k1 | k2 | |
---|---|---|
0 | one | 3 |
1 | one | 2 |
2 | one | 1 |
3 | two | 3 |
5 | two | 4 |
在不加任何参数时,Pandas会将完全相同的行去重:
data = pd.DataFrame({'k1':['one']*3+['two']*4,'k2':[3,2,1,3,3,4,4]})
data.drop_duplicates(subset=['k1'],keep='last')
Output:
k1 | k2 | |
---|---|---|
2 | one | 1 |
6 | two | 4 |
当设置 subset为 k1时,只要 k1重复,Pandas就认为是重复的,可以 通过 keep参数确定需要保留哪个,一般在使用keep时先排序。 另外,如果需要查看重复的行,则可以进行如下操作:
data = pd.DataFrame({'k1':['one']*3+['two']*4,'k2':[3,2,1,3,3,4,4]})
data[data.duplicated()]
Output:
k1 | k2 | |
---|---|---|
4 | two | 3 |
6 | two | 4 |
Pandas 替换数据
如果想批量替换数据中的指定数值,则可以使用 replace:
import numpy as np
a.replace(1,np.nan)
Output:
Unnamed:0 | ticker | secShortName | tradeDate | closePrice | |
---|---|---|---|---|---|
0 | 0.0 | NaN | 平安银行 | 2017/6/20 | 9.12 |
1 | NaN | 2.0 | 万科A | 2017/6/20 | 21.03 |
2 | 2.0 | 4.0 | 国农科技 | 2017/6/20 | 27.03 |
3 | 3.0 | 5.0 | 世纪星源 | 2017/6/20 | 5.45 |
4 | 4.0 | 6.0 | 深振业A | 2017/6/20 | 8.87 |
5 | 5.0 | 7.0 | 全新好 | 2017/6/20 | 15.87 |
如果想批量替换数据中的指定数值,则可以使用 replace:
也可以重命名某些列:
a.rename(columns={'Unnamed:0':'id'})
Output:
id | ticker | secShortName | tradeDate | closePrice | |
---|---|---|---|---|---|
0 | 0.0 | NaN | 平安银行 | 2017/6/20 | 9.12 |
1 | NaN | 2.0 | 万科A | 2017/6/20 | 21.03 |
2 | 2.0 | 4.0 | 国农科技 | 2017/6/20 | 27.03 |
3 | 3.0 | 5.0 | 世纪星源 | 2017/6/20 | 5.45 |
4 | 4.0 | 6.0 | 深振业A | 2017/6/20 | 8.87 |
5 | 5.0 | 7.0 | 全新好 | 2017/6/20 | 15.87 |
切片与筛选
DataFame 有三种切片方法,分别问 loc,iloc和ix (注意: == pandas的1.0.0版本开始,移除了Series.ix and DataFrame.ix 方法 ==)
df.loc的第 1个参数是行标签,第 2个参数为列标签(为可选参数, 默认为所有列标签),这两个参数既可以是列表,也可以是单个字符。 如果这两个参数都为列表,则返DataFrame,否则返回Series:
a.loc[:,['ticker','closePrice']]
Output:
ticker | closePrice | |
---|---|---|
0 | 1 | 9.12 |
1 | 2 | 21.03 |
2 | 4 | 27.03 |
3 | 5 | 5.45 |
4 | 6 | 8.87 |
5 | 7 | 15.87 |
a.loc中的 :
表示所有的行。
df.loc的第 1个参数是行的位置,第 2个参数是列的位置(为可选参 数,默认为所有列标签),这两个参数既可以是列表,也可以是单个字符。如果两个参数都是列表,则返回DataFrame,否则返回Series:
a.iloc[:4,[1,4]]
Output:
ticker | closePrice | |
---|---|---|
0 | 1 | 9.12 |
1 | 2 | 21.03 |
2 | 4 | 27.03 |