【手把手教你】玩转Python金融量化利器之Pandas

简介: 前言“手把手教你”系列将为Python初学者一一介绍Python在量化金融中运用最广泛的几个库(Library): NumPy(数组、线性代数)、SciPy(统计)、pandas(时间序列、数据分析)、matplotlib(可视化分析)。

前言
“手把手教你”系列将为Python初学者一一介绍Python在量化金融中运用最广泛的几个库(Library): NumPy(数组、线性代数)、SciPy(统计)、pandas(时间序列、数据分析)、matplotlib(可视化分析)。建议安装Anaconda软件(自带上述常见库),并使用Jupyter Notebook交互学习。

Pandas的数据结构类型:
Series (序列:一维列表)

DataFrame (数据框:二维表)

  1. Series
    定义:数据表中的一列或一行,观测向量为一维数组,对于任意一组个体某一属性的观测可抽象为Series的概念。Series默认由index和values构成。
import pandas as pd
import numpy as np    

1.1 Series的创建
创建Series 创建一个Series的基本格式是s = Series(data, index=index, name=name)

np.random.seed(1)     #使用随机种子,这样每次运行random结果一致,
A=np.random.randn(5)  
print("A is an array:\n",A)
S = pd.Series(A)
print("S is a Series:\n",S)
print("index: ", S.index)  #默认创建索引,注意是从0开始
print("values: ", S.values)
A is an array:
 [ 1.62434536 -0.61175641 -0.52817175 -1.07296862  0.86540763]
S is a Series:
 0    1.624345
1   -0.611756
2   -0.528172
3   -1.072969
4    0.865408
dtype: float64
index:  RangeIndex(start=0, stop=5, step=1)
values:  [ 1.62434536 -0.61175641 -0.52817175 -1.07296862  0.86540763]

可以在创建Series时添加index,并可使用Series.index查看具体的index。需要注意的一点是,
当从数组创建Series时,若指定index,那么index长度要和data的
长度一致

np.random.seed(2)
s=Series(np.random.randn(5),index=['a','b','c','d','e'])
print (s)
s.index
a   -0.416758
b   -0.056267
c   -2.136196
d    1.640271
e   -1.793436
dtype: float64

Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

通过字典(dict)来创建Series。

stocks={'中国平安':'601318','格力电器':'000651','招商银行':'600036',
        '中信证券':'600030','贵州茅台':'600519'}
Series_stocks = Series(stocks)
print (s)
中国平安    601318
格力电器    000651
招商银行    600036
中信证券    600030
贵州茅台    600519
dtype: object

使用字典创建Series时指定index的情形(index长度不必和字典相同)。

Series(stocks, index=['中国平安', '格力电器', '招商银行', '中信证券',
                       '工业富联'])
#注意,在原来的stocks(dict)里没有‘工业富联’,因此值为‘NaN’
中国平安    601318
格力电器    000651
招商银行    600036
中信证券    600030
工业富联       NaN
dtype: object

给数据序列和index命名:

Series_stocks.name='股票代码'        #注意python是使用.号来连接和调用
Series_stocks.index.name='股票名称'
print(Series_stocks)
股票名称
中国平安    601318
格力电器    000651
招商银行    600036
中信证券    600030
贵州茅台    600519
Name: 股票代码, dtype: object

1.2 Series数据的访问
Series对象的下标运算同时支持位置和标签两种方式

np.random.seed(3)
data=np.random.randn(5)
s = Series(data,index=['a', 'b', 'c', 'd', 'e'])
s
a    1.624345
b   -0.611756
c   -0.528172
d   -1.072969
e    0.865408
dtype: float64
s[:2]   #取出第0、1行数据
a   -0.670228
b    0.488043
dtype: float64
s[[2,0,4]]  #取出第2、0、4行数据
c   -0.528172
a    1.624345
e    0.865408
dtype: float64
s[['e', 'a']] #取出‘e’、‘a’对应数据
e    0.865408
a    1.624345
dtype: float64

1.3 Series排序函数

np.random.seed(3)
data=np.random.randn(10)
s = Series(data,index=['j','a', 'c','b', 'd', 'e','h','f','g','i'])
s
j    1.788628
a    0.436510
c    0.096497
b   -1.863493
d   -0.277388
e   -0.354759
h   -0.082741
f   -0.627001
g   -0.043818
i   -0.477218
dtype: float64
#排序
s.sort_index(ascending=True) #按index从小到大,False从大到小
a    0.436510
b   -1.863493
c    0.096497
d   -0.277388
e   -0.354759
f   -0.627001
g   -0.043818
h   -0.082741
i   -0.477218
j    1.788628
dtype: float64
s.sort_values(ascending=True)
b   -1.863493
f   -0.627001
i   -0.477218
e   -0.354759
d   -0.277388
h   -0.082741
g   -0.043818
c    0.096497
a    0.436510
j    1.788628
dtype: float64
s.rank(method='average',ascending=True,axis=0) #每个数的平均排名
j    10.0
a     9.0
c     8.0
b     1.0
d     5.0
e     4.0
h     6.0
f     2.0
g     7.0
i     3.0
dtype: float64
#返回含有最大值的索引位置: 
print(s.idxmax())
#返回含有最小值的索引位置: 
print(s.idxmin())
j
b

根据索引返回已排序的新对象:
Series.sort_index(ascending=True)

根据值返回已排序的对象,NaN值在末尾:
Series.sort_values(ascending=True)

为各组分配一个平均排名:
Series.rank(method='average',ascending=True,axis=0)
rank的method选项:
'average':在相等分组中,为各个值分配平均排名
'max','min':使用整个分组中的最小排名
'first':按值在原始数据中出现的顺序排名

返回含有最大值的索引位置:
Series.idxmax()

返回含有最小值的索引位置:
Series.idxmin()

2 Pandas数据结构:DataFrame
DataFrame是一个二维的数据结构,通过数据组,index和columns构成

2.1 DataFrame数据表的创建
DataFrame是多个Series的集合体。
先创建一个值是Series的字典,并转换为DataFrame。

#通过字典创建DataFrame
d={'one':pd.Series([1.,2.,3.],index=['a','b','c']),
   'two':pd.Series([1.,2.,3.,4.,],index=['a','b','c','d']),
   'three':range(4),
   'four':1.,
   'five':'f'}
df=pd.DataFrame(d)
print (df)
   one  two  three  four five
a  1.0  1.0      0   1.0    f
b  2.0  2.0      1   1.0    f
c  3.0  3.0      2   1.0    f
d  NaN  4.0      3   1.0    f
#可以使用dataframe.index和dataframe.columns来查看DataFrame的行和列,
#dataframe.values则以数组的形式返回DataFrame的元素
print ("DataFrame index:\n",df.index)
print ("DataFrame columns:\n",df.columns)
print ("DataFrame values:\n",df.values)
DataFrame index:
 Index(['a', 'b', 'c', 'd'], dtype='object')
DataFrame columns:
 Index(['one', 'two', 'three', 'four', 'five'], dtype='object')
DataFrame values:
 [[1.0 1.0 0 1.0 'f']
 [2.0 2.0 1 1.0 'f']
 [3.0 3.0 2 1.0 'f']
 [nan 4.0 3 1.0 'f']]
#DataFrame也可以从值是数组的字典创建,但是各个数组的长度需要相同:
d = {'one': [1., 2., 3., 4.], 'two': [4., 3., 2., 1.]}
df = DataFrame(d, index=['a', 'b', 'c', 'd'])
print df
   one  two
a  1.0  4.0
b  2.0  3.0
c  3.0  2.0
d  4.0  1.0
#值非数组时,没有这一限制,并且缺失值补成NaN
d= [{'a': 1.6, 'b': 2}, {'a': 3, 'b': 6, 'c': 9}]
df = DataFrame(d)
print df
     a  b    c
0  1.6  2  NaN
1  3.0  6  9.0
#在实际处理数据时,有时需要创建一个空的DataFrame,可以这么做
df = DataFrame()
print (df)
Empty DataFrame
Columns: []
Index: []
#另一种创建DataFrame的方法十分有用,那就是使用concat函数基于Series
#或者DataFrame创建一个DataFrame
a = Series(range(5))   #range(5)产生0到4 
b = Series(np.linspace(4, 20, 5)) #linspace(a,b,c)
df = pd.concat([a, b], axis=1)
print (df)
   0     1
0  0   4.0
1  1   8.0
2  2  12.0
3  3  16.0
4  4  20.0

其中的axis=1表示按列进行合并,axis=0表示按行合并,
并且,Series都处理成一列,所以这里如果选axis=0的话,
将得到一个10×1的DataFrame。下面这个例子展示了如何按行合并
DataFrame成一个大的DataFrame:

df = DataFrame()
index = ['alpha', 'beta', 'gamma', 'delta', 'eta']
for i in range(5):
    a = DataFrame([np.linspace(i, 5*i, 5)], index=[index[i]])
    df = pd.concat([df, a], axis=0)
print (df)
         0    1     2     3     4
alpha  0.0  0.0   0.0   0.0   0.0
beta   1.0  2.0   3.0   4.0   5.0
gamma  2.0  4.0   6.0   8.0  10.0
delta  3.0  6.0   9.0  12.0  15.0
eta    4.0  8.0  12.0  16.0  20.0

2.2 DataFrame数据的访问

#DataFrame是以列作为操作的基础的,全部操作都想象成先从DataFrame里取一列,
#再从这个Series取元素即可。
#可以用datafrae.column_name选取列,也可以使用dataframe[]操作选取列
df = DataFrame()
index = ['alpha', 'beta', 'gamma', 'delta', 'eta']
for i in range(5):
    a = DataFrame([np.linspace(i, 5*i, 5)], index=[index[i]])
    df = pd.concat([df, a], axis=0)
print('df: \n',df)
print ("df[1]:\n",df[1])
df.columns = ['a', 'b', 'c', 'd', 'e']
print('df: \n',df)
print ("df[b]:\n",df['b'])
print ("df.b:\n",df.b)
print ("df[['a','b']]:\n",df[['a', 'd']])
df: 
          0    1     2     3     4
alpha  0.0  0.0   0.0   0.0   0.0
beta   1.0  2.0   3.0   4.0   5.0
gamma  2.0  4.0   6.0   8.0  10.0
delta  3.0  6.0   9.0  12.0  15.0
eta    4.0  8.0  12.0  16.0  20.0
df[1]:
 alpha    0.0
beta     2.0
gamma    4.0
delta    6.0
eta      8.0
Name: 1, dtype: float64
df: 
          a    b     c     d     e
alpha  0.0  0.0   0.0   0.0   0.0
beta   1.0  2.0   3.0   4.0   5.0
gamma  2.0  4.0   6.0   8.0  10.0
delta  3.0  6.0   9.0  12.0  15.0
eta    4.0  8.0  12.0  16.0  20.0
df[b]:
 alpha    0.0
beta     2.0
gamma    4.0
delta    6.0
eta      8.0
Name: b, dtype: float64
df.b:
 alpha    0.0
beta     2.0
gamma    4.0
delta    6.0
eta      8.0
Name: b, dtype: float64
df[['a','b']]:
          a     d
alpha  0.0   0.0
beta   1.0   4.0
gamma  2.0   8.0
delta  3.0  12.0
eta    4.0  16.0
#访问特定的元素可以如Series一样使用下标或者是索引:
print (df['b'][2])       #第b列,第3行(从0开始算)
print (df['b']['gamma']) #第b列,gamma对应行
4.0
4.0
##### df.loc['列或行名'],df.iloc[n]第n行,df.iloc[:,n]第n列
#若需要选取行,可以使用dataframe.iloc按下标选取,
#或者使用dataframe.loc按索引选取
print (df.iloc[1])    #选取第一行元素
print (df.loc['beta'])#选取beta对应行元素
a    1.0
b    2.0
c    3.0
d    4.0
e    5.0
Name: beta, dtype: float64
a    1.0
b    2.0
c    3.0
d    4.0
e    5.0
Name: beta, dtype: float64
#选取行还可以使用切片的方式或者是布尔类型的向量:
print ("切片取数:\n",df[1:3])
bool_vec = [True, False, True, True, False]
print ("根据布尔类型取值:\n",df[bool_vec]) #相当于选取第0、2、3行
切片取数:
          a    b    c    d     e
beta   1.0  2.0  3.0  4.0   5.0
gamma  2.0  4.0  6.0  8.0  10.0
根据布尔类型取值:
          a    b    c     d     e
alpha  0.0  0.0  0.0   0.0   0.0
gamma  2.0  4.0  6.0   8.0  10.0
delta  3.0  6.0  9.0  12.0  15.0
#行列组合起来选取数据:
print (df[['b', 'd']].iloc[[1, 3]])
print (df.iloc[[1, 3]][['b', 'd']])
print (df[['b', 'd']].loc[['beta', 'delta']])
print (df.loc[['beta', 'delta']][['b', 'd']])
         b     d
beta   2.0   4.0
delta  6.0  12.0
         b     d
beta   2.0   4.0
delta  6.0  12.0
         b     d
beta   2.0   4.0
delta  6.0  12.0
         b     d
beta   2.0   4.0
delta  6.0  12.0
#如果不是需要访问特定行列,而只是某个特殊位置的元素的话,
#dataframe.at和dataframe.iat
#是最快的方式,它们分别用于使用索引和下标进行访问
print(df)
print (df.iat[2, 3])  #相当于第3行第4列
print (df.at['gamma', 'd'])
         a    b     c     d     e
alpha  0.0  0.0   0.0   0.0   0.0
beta   1.0  2.0   3.0   4.0   5.0
gamma  2.0  4.0   6.0   8.0  10.0
delta  3.0  6.0   9.0  12.0  15.0
eta    4.0  8.0  12.0  16.0  20.0
8.0
8.0

2.3创建时间序列
pandas.date_range(start=None, end=None, periods=None, freq='D',
tz=None, normalize=False, name=None, closed=None, **kwargs)

dates=pd.date_range('20180101',periods=12,freq='m')
print (dates)
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30',
 '2018-05-31', '2018-06-30', '2018-07-31', '2018-08-31', '2018-09-30',
  '2018-10-31', '2018-11-30', '2018-12-31'], dtype='datetime64[ns]', 
  freq='M')
np.random.seed(5)
df=pd.DataFrame(np.random.randn(12,4),index=dates,
                 columns=list('ABCD'))
df

image

#查看数据头n行 ,默认n=5
df.head()

image

#查看数据最后3行
df.tail(3)

image

#查看数据的index(索引),columns (列名)和数据
print(df.index)
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30',
 '2018-05-31', '2018-06-30', '2018-07-31', '2018-08-31', '2018-09-30',
  '2018-10-31', '2018-11-30', '2018-12-31'], dtype='datetime64[ns]', 
  freq='M')
print(df.columns)
Index(['A', 'B', 'C', 'D'], dtype='object')
print(df.values)
[[ 0.44122749 -0.33087015  2.43077119 -0.25209213]
 [ 0.10960984  1.58248112 -0.9092324  -0.59163666]
 [ 0.18760323 -0.32986996 -1.19276461 -0.20487651]
 [-0.35882895  0.6034716  -1.66478853 -0.70017904]
 [ 1.15139101  1.85733101 -1.51117956  0.64484751]
 [-0.98060789 -0.85685315 -0.87187918 -0.42250793]
 [ 0.99643983  0.71242127  0.05914424 -0.36331088]
 [ 0.00328884 -0.10593044  0.79305332 -0.63157163]
 [-0.00619491 -0.10106761 -0.05230815  0.24921766]
 [ 0.19766009  1.33484857 -0.08687561  1.56153229]
 [-0.30585302 -0.47773142  0.10073819  0.35543847]
 [ 0.26961241  1.29196338  1.13934298  0.4944404 ]]
#数据转置
# df.T

根据索引排序数据排序:(按行axis=0或列axis=1)

df.sort_index(axis=1,ascending=False)

image

#按某列的值排序
df.sort_values('A')  #按A列的值从小到大排序

image

#数据选取loc和iloc
df.loc[dates[0]]
A    0.441227
B   -0.330870
C    2.430771
D   -0.252092
Name: 2018-01-31 00:00:00, dtype: float64
df.loc['20180131':'20180430',['A','C']]  #根据标签取数

image

df.iloc[1:3,1:4]  #根据所在位置取数,注意从0开始数

image
image
image
数据筛选isin()

df2=df.copy() #复制df数据
df2['E']=np.arange(12)
df2

image

df2[df2['E'].isin([0,2,4])]

image

  1. 缺失值处理
    缺失值用NaN显示
date3=pd.date_range('20181001',periods=5)
np.random.seed(6)
data=np.random.randn(5,4)
df3=pd.DataFrame(data,index=date3,columns=list('ABCD'))
df3

image

df3.iat[3,3]=np.NaN  #令第3行第3列的数为缺失值(0.129151)
df3.iat[1,2]=np.NaN  #令第1行第2列的数为缺失值(1.127064)
df3

image
image
填充缺失值
fillna 还可以使用 method 参数
method 可以使用下面的方法
1 . pad/ffill:用前一个非缺失值去填充该缺失值
2 . backfill/bfill:用下一个非缺失值填充该缺失值
image
image
image
4、统计

date4=pd.date_range('20181001',periods=5)
np.random.seed(7)
data4=np.random.randn(5,4)
df4=pd.DataFrame(data4,index=date3,columns=list('ABCD'))
df4

image

描述性统计 df.describe()

df4.describe()

image

df4.mean() #均值,默认按列axis=0
A    0.595828
B   -0.000170
C   -0.112358
D   -0.899704
dtype: float64
df4.mean(axis=1)  #按行
2018-10-01    0.416231
2018-10-02   -0.635618
2018-10-03    0.205295
2018-10-04   -0.363012
2018-10-05   -0.143401
Freq: D, dtype: float64

对数据使用函数df.apply()
image
image
5、数据合并

#Concat()
d1=pd.Series(range(5))
print(d1)
d2=pd.Series(range(5,10))
print(d2)
0    0
1    1
2    2
3    3
4    4
dtype: int64
0    5
1    6
2    7
3    8
4    9
dtype: int64
pd.concat([d1,d2],axis=1) #默认是纵向合并即axis=0

image
image
image
image
image
image
image
6、数据可视化(画图)

import matplotlib.pyplot as plt
from pylab import mpl  
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 
mpl.rcParams['axes.unicode_minus']=False  # 用来正常显示负号
%matplotlib inline
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000',
                periods=1000))
ts = ts.cumsum()
ts.plot(figsize=(12,8))
#利用tushare包抓取股票数据并画图
#得到的是DataFrame的数据结构
import tushare as ts
df=ts.get_k_data('sh',start='1990-01-01')
import pandas as pd
df.index=pd.to_datetime(df['date'])
df['close'].plot(figsize=(12,8))
plt.title("上证指数走势")

image
image

原文发布时间为:2019-1-3
本文作者:CuteHand
本文来自云栖社区合作伙伴“ Python爱好者社区”,了解相关信息可以关注“python_shequ”微信公众号

相关文章
|
3天前
|
数据挖掘 数据处理 索引
python常用pandas函数nlargest / nsmallest及其手动实现
python常用pandas函数nlargest / nsmallest及其手动实现
18 0
|
4天前
|
数据处理 Python
如何使用Python的Pandas库进行数据排序和排名
【4月更文挑战第22天】Pandas Python库提供数据排序和排名功能。使用`sort_values()`按列进行升序或降序排序,如`df.sort_values(by='A', ascending=False)`。`rank()`函数用于计算排名,如`df['A'].rank(ascending=False)`。多列操作可传入列名列表,如`df.sort_values(by=['A', 'B'], ascending=[True, False])`和分别对'A'、'B'列排名。
14 2
|
1月前
|
BI 数据处理 索引
Pandas基本操作:Series和DataFrame(Python)
Pandas基本操作:Series和DataFrame(Python)
105 1
|
5天前
|
索引 Python
如何在Python中使用Pandas库进行季节性调整?
在Python中使用Pandas和Statsmodels进行季节性调整的步骤包括:导入pandas和seasonal_decompose模块,准备时间序列DataFrame,调用`seasonal_decompose()`函数分解数据为趋势、季节性和残差,可选地绘制图表分析,以及根据需求去除季节性影响(如将原始数据减去季节性成分)。这是对时间序列数据进行季节性分析的基础流程。
19 2
|
3天前
|
数据挖掘 数据处理 索引
如何使用Python的Pandas库进行数据筛选和过滤?
Pandas是Python数据分析的核心库,提供DataFrame数据结构。基本步骤包括导入库、创建DataFrame及进行数据筛选。示例代码展示了如何通过布尔索引、`query()`和`loc[]`方法筛选`Age`大于19的记录。
10 0
|
5天前
|
Python
如何使用Python的Pandas库进行数据缺失值处理?
Pandas在Python中提供多种处理缺失值的方法:1) 使用`isnull()`检查;2) `dropna()`删除含缺失值的行或列;3) `fillna()`用常数、前后值填充;4) `interpolate()`进行插值填充。根据需求选择合适的方法处理数据缺失。
39 9
|
7天前
|
索引 Python
如何使用Python的Pandas库进行数据透视表(pivot table)操作?
使用Pandas在Python中创建数据透视表的步骤包括:安装Pandas库,导入它,创建或读取数据(如DataFrame),使用`pd.pivot_table()`指定数据框、行索引、列索引和值,计算聚合函数(如平均分),并可打印或保存结果到文件。这允许对数据进行高效汇总和分析。
10 2
|
8天前
|
数据采集 SQL 数据可视化
Python数据分析工具Pandas
【4月更文挑战第14天】Pandas是Python的数据分析库,提供Series和DataFrame数据结构,用于高效处理标记数据。它支持从多种数据源加载数据,包括CSV、Excel和SQL。功能包括数据清洗(处理缺失值、异常值)、数据操作(切片、过滤、分组)、时间序列分析及与Matplotlib等库集成进行数据可视化。其高性能底层基于NumPy,适合大型数据集处理。通过加载数据、清洗、分析和可视化,Pandas简化了数据分析流程。广泛的学习资源使其成为数据分析初学者的理想选择。
15 1
|
9天前
|
数据挖掘 vr&ar Python
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用
34 10
|
9天前
|
Python
Python金融应用编程:衍生品定价和套期保值的随机过程
Python金融应用编程:衍生品定价和套期保值的随机过程
24 0