【手把手教你】玩转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”微信公众号

相关文章
|
25天前
|
数据格式 Python
如何使用Python的Pandas库进行数据透视图(melt/cast)操作?
Pandas的`melt()`和`pivot()`函数用于数据透视。基本步骤:导入pandas,创建DataFrame,然后使用这两个函数转换数据格式。示例代码展示了如何通过`melt()`转为长格式,再用`pivot()`恢复为宽格式。输入数据是包含'Name'和'Age'列的DataFrame,最终结果经过转换后呈现出不同的布局。
38 6
|
25天前
|
数据挖掘 数据处理 索引
如何使用Python的Pandas库进行数据筛选和过滤?
Pandas是Python数据分析的核心库,其DataFrame数据结构便于数据操作。筛选与过滤数据主要包括:导入pandas,创建DataFrame,通过布尔索引、`query()`或`loc[]`、`iloc[]`方法筛选。
|
26天前
|
数据处理 Python
如何使用Python的Pandas库进行数据排序和排名?
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])`。
22 6
|
27天前
|
索引 Python
如何在Python中使用Pandas库进行季节性调整?
Pandas库在Python中支持季节性调整,通过`seasonal_decompose`函数实现。步骤包括:导入Pandas和statsmodels模块,准备时间序列DataFrame,调用函数分解数据为趋势、季节性和残差,可选地分析或绘制这些部分,以及根据需求去除季节性影响(原始数据减去季节性成分)。这是基础的季节性调整流程,可按实际需求调整。
41 0
|
27天前
|
Python
如何使用Python的Pandas库进行数据缺失值处理?
Pandas在Python中提供多种处理缺失值的方法:1) 使用`isnull()`检查;2) `dropna()`删除含缺失值的行/列;3) `fillna()`用常数、前/后一个值填充;4) `interpolate()`插值填充。根据需求选择合适的方法处理数据缺失值。
15 0
|
22天前
|
BI 数据处理 索引
Pandas基本操作:Series和DataFrame(Python)
Pandas基本操作:Series和DataFrame(Python)
92 1
|
27天前
|
索引 Python
如何在Python中,Pandas库实现对数据的时间序列分析?
Pandas在Python中提供强大的时间序列分析功能,包括:1) 使用`pd.date_range()`创建时间序列;2) 通过`pd.DataFrame()`将时间序列转为DataFrame;3) `set_index()`设定时间列作为索引;4) `resample()`实现数据重采样(如按月、季度);5) `rolling()`进行移动窗口计算,如计算移动平均;6) 使用`seasonal_decompose()`进行季节性调整。这些工具适用于各种时间序列分析场景。
26 0
|
27天前
|
数据采集 Python
如何在Python中使用Pandas库进行数据清洗?
Pandas在Python中提供高效的数据清洗功能,包括处理缺失值(`dropna()`删除、`fillna()`填充)、重复值(`duplicated()`检查、`drop_duplicates()`删除)、异常值(条件筛选、分位数、标准差)和文本数据(字符串操作、正则表达式)。这些方法帮助用户根据需求清洗数据,确保数据质量。
23 0
|
22天前
|
数据采集 存储 Web App开发
一键实现数据采集和存储:Python爬虫、Pandas和Excel的应用技巧
一键实现数据采集和存储:Python爬虫、Pandas和Excel的应用技巧
|
26天前
|
数据可视化 Python
如何使用Python的Pandas库进行数据分组和聚合操作?
【2月更文挑战第29天】【2月更文挑战第105篇】如何使用Python的Pandas库进行数据分组和聚合操作?