龙空技术网

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

Python金融量化 437

前言:

而今姐妹们对“pandas创建空表”大概比较讲究,朋友们都需要分析一些“pandas创建空表”的相关知识。那么小编也在网上搜集了一些关于“pandas创建空表””的相关资讯,希望我们能喜欢,兄弟们一起来学习一下吧!

贵有恒,何必三更起五更眠。最无益,只怕一日曝十日寒。 ——毛泽东

前言

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

对于Python零基础的请关注公众号CuteHand,并回复Python入门,奉上Python的程序安装和入门应用指南。对于Python的高阶学习,如数据分析挖掘、机器学习和量化投资,请继续关注公众号的动态。

Pandas的数据结构类型:

Series (序列:一维列表)DataFrame (数据框:二维表)

1. Series

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

import pandas as pdimport 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.6243451 -0.6117562 -0.5281723 -1.0729694 0.865408dtype: float64index: 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.indexa -0.416758b -0.056267c -2.136196d 1.640271e -1.793436dtype: float64Index(['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贵州茅台 600519dtype: object
使用字典创建Series时指定index的情形(index长度不必和字典相同)。
Series(stocks, index=['中国平安', '格力电器', '招商银行', '中信证券', '工业富联'])#注意,在原来的stocks(dict)里没有‘工业富联’,因此值为‘NaN’中国平安 601318格力电器 000651招商银行 600036中信证券 600030工业富联 NaNdtype: object
给数据序列和index命名:
Series_stocks.name='股票代码' #注意python是使用.号来连接和调用Series_stocks.index.name='股票名称'print(Series_stocks)股票名称中国平安 601318格力电器 000651招商银行 600036中信证券 600030贵州茅台 600519Name: 股票代码, dtype: object

1.2 Series数据的访问

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

np.random.seed(3)data=np.random.randn(5)s = Series(data,index=['a', 'b', 'c', 'd', 'e'])sa 1.624345b -0.611756c -0.528172d -1.072969e 0.865408dtype: float64s[:2] #取出第0、1行数据a -0.670228b 0.488043dtype: float64s[[2,0,4]] #取出第2、0、4行数据c -0.528172a 1.624345e 0.865408dtype: float64s[['e', 'a']] #取出‘e’、‘a’对应数据e 0.865408a 1.624345dtype: 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'])sj 1.788628a 0.436510c 0.096497b -1.863493d -0.277388e -0.354759h -0.082741f -0.627001g -0.043818i -0.477218dtype: float64#排序s.sort_index(ascending=True) #按index从小到大,False从大到小a 0.436510b -1.863493c 0.096497d -0.277388e -0.354759f -0.627001g -0.043818h -0.082741i -0.477218j 1.788628dtype: float64s.sort_values(ascending=True)b -1.863493f -0.627001i -0.477218e -0.354759d -0.277388h -0.082741g -0.043818c 0.096497a 0.436510j 1.788628dtype: float64s.rank(method='average',ascending=True,axis=0) #每个数的平均排名j 10.0a 9.0c 8.0b 1.0d 5.0e 4.0h 6.0f 2.0g 7.0i 3.0dtype: float64#返回含有最大值的索引位置: print(s.idxmax())#返回含有最小值的索引位置: print(s.idxmin())jb
根据索引返回已排序的新对象: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。

#通过字典创建DataFramed={'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 fivea 1.0 1.0 0 1.0 fb 2.0 2.0 1 1.0 fc 3.0 3.0 2 1.0 fd 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 twoa 1.0 4.0b 2.0 3.0c 3.0 2.0d 4.0 1.0#值非数组时,没有这一限制,并且缺失值补成NaNd= [{'a': 1.6, 'b': 2}, {'a': 3, 'b': 6, 'c': 9}]df = DataFrame(d)print df a b c0 1.6 2 NaN1 3.0 6 9.0#在实际处理数据时,有时需要创建一个空的DataFrame,可以这么做df = DataFrame()print (df)Empty DataFrameColumns: []Index: []#另一种创建DataFrame的方法十分有用,那就是使用concat函数基于Series#或者DataFrame创建一个DataFramea = 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 10 0 4.01 1 8.02 2 12.03 3 16.04 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 4alpha 0.0 0.0 0.0 0.0 0.0beta 1.0 2.0 3.0 4.0 5.0gamma 2.0 4.0 6.0 8.0 10.0delta 3.0 6.0 9.0 12.0 15.0eta 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 4alpha 0.0 0.0 0.0 0.0 0.0beta 1.0 2.0 3.0 4.0 5.0gamma 2.0 4.0 6.0 8.0 10.0delta 3.0 6.0 9.0 12.0 15.0eta 4.0 8.0 12.0 16.0 20.0df[1]: alpha 0.0beta 2.0gamma 4.0delta 6.0eta 8.0Name: 1, dtype: float64df:  a b c d ealpha 0.0 0.0 0.0 0.0 0.0beta 1.0 2.0 3.0 4.0 5.0gamma 2.0 4.0 6.0 8.0 10.0delta 3.0 6.0 9.0 12.0 15.0eta 4.0 8.0 12.0 16.0 20.0df[b]: alpha 0.0beta 2.0gamma 4.0delta 6.0eta 8.0Name: b, dtype: float64df.b: alpha 0.0beta 2.0gamma 4.0delta 6.0eta 8.0Name: b, dtype: float64df[['a','b']]: a dalpha 0.0 0.0beta 1.0 4.0gamma 2.0 8.0delta 3.0 12.0eta 4.0 16.0#访问特定的元素可以如Series一样使用下标或者是索引:print (df['b'][2]) #第b列,第3行(从0开始算)print (df['b']['gamma']) #第b列,gamma对应行4.04.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.0b 2.0c 3.0d 4.0e 5.0Name: beta, dtype: float64a 1.0b 2.0c 3.0d 4.0e 5.0Name: 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 ebeta 1.0 2.0 3.0 4.0 5.0gamma 2.0 4.0 6.0 8.0 10.0根据布尔类型取值: a b c d ealpha 0.0 0.0 0.0 0.0 0.0gamma 2.0 4.0 6.0 8.0 10.0delta 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 dbeta 2.0 4.0delta 6.0 12.0 b dbeta 2.0 4.0delta 6.0 12.0 b dbeta 2.0 4.0delta 6.0 12.0 b dbeta 2.0 4.0delta 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 ealpha 0.0 0.0 0.0 0.0 0.0beta 1.0 2.0 3.0 4.0 5.0gamma 2.0 4.0 6.0 8.0 10.0delta 3.0 6.0 9.0 12.0 15.0eta 4.0 8.0 12.0 16.0 20.08.08.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
#查看数据头n行 ,默认n=5df.head()#查看数据最后3行df.tail(3)
#查看数据的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)
#按某列的值排序df.sort_values('A') #按A列的值从小到大排序
#数据选取loc和ilocdf.loc[dates[0]]A 0.441227B -0.330870C 2.430771D -0.252092Name: 2018-01-31 00:00:00, dtype: float64df.loc['20180131':'20180430',['A','C']] #根据标签取数
df.iloc[1:3,1:4] #根据所在位置取数,注意从0开始数
df.iloc[[1,3,5],[0,3]] #根据特定行和列取数
df[df.A>0] #相当于取出A列大于0时的数据列表
df[df>0] #显示值大于0的数,其余使用NaN代替

数据筛选isin()

df2=df.copy() #复制df数据df2['E']=np.arange(12)df2
df2[df2['E'].isin([0,2,4])]

3. 缺失值处理

缺失值用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
df3.iat[3,3]=np.NaN #令第3行第3列的数为缺失值(0.129151)df3.iat[1,2]=np.NaN #令第1行第2列的数为缺失值(1.127064)df3
#丢弃存在缺失值的行#设定how=all只会删除那些全是NaN的行:df3.dropna(how='any')
#删除列也一样,设置axis=1df3.dropna(how='any',axis=1)
#thresh参数,如thresh=4,一行中至少有4个非NaN值,否则删除df3.iloc[2,2]=np.NaNdf3.dropna(thresh=4)

填充缺失值

fillna 还可以使用 method 参数

method 可以使用下面的方法

1 . pad/ffill:用前一个非缺失值去填充该缺失值

2 . backfill/bfill:用下一个非缺失值填充该缺失值

df3.fillna(method='ffill')
df3.fillna(method='bfill')
df3
#使在改变DataFrame 和 Series 的操作时,会返回一个新的对象,#原对象不变,如果要改变原对象,可以添加参数 inplace = True用列均值填充#使用该列的均值填充df3['C'].fillna(df3['C'].mean(),inplace=True)df3

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

描述性统计 df.describe()

df4.describe()
df4.mean() #均值,默认按列axis=0A 0.595828B -0.000170C -0.112358D -0.899704dtype: float64df4.mean(axis=1) #按行2018-10-01 0.4162312018-10-02 -0.6356182018-10-03 0.2052952018-10-04 -0.3630122018-10-05 -0.143401Freq: D, dtype: float64

对数据使用函数df.apply()

df4.apply(np.cumsum) #np.cumsum()累加函数
df4.apply(lambda x:x.max()-x.min()) #lambda自定义函数#相当于计算每列里最大值-最小值A 2.479449B 1.066436C 0.899889D 2.162241dtype: float64df4['E']=['a','a','a','b','b']df4
#计算某个值出现评率df4['E'].value_counts()a 3b 2Name: E, dtype: int64

5、数据合并

#Concat()d1=pd.Series(range(5))print(d1)d2=pd.Series(range(5,10))print(d2)0 01 12 23 34 4dtype: int640 51 62 73 84 9dtype: int64pd.concat([d1,d2],axis=1) #默认是纵向合并即axis=0
#pd.merge(left_on=None, right_on=None, left_index=False, #right_index=False)d1=pd.DataFrame(np.random.randn(3,3),columns=list('ABC'))print(d1)d2=pd.DataFrame(np.random.randn(3,3),columns=list('DEF'))print(d2)pd.merge(d1,d2,left_index=True, right_index=True) A B C0 1.766161 -0.329414 0.8407331 -0.179986 0.568062 -0.7528372 -1.708339 -1.803099 0.383122 D E F0 2.247595 0.269412 -0.5246051 1.912019 0.237302 0.1014342 0.252578 -0.132377 -0.309476
#增加1行数据:Append()df = pd.DataFrame(np.random.randn(3, 3), columns=['A','B','C'])df
s=pd.Series([1.,1,1],index=list('ABC'))df.append(s,ignore_index=True)

聚类分析 groupby

df = pd.DataFrame({'A' : ['true', 'false', 'true', 'false', 'true', 'false', 'true', 'false'], 'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'], 'C' : np.random.randn(8), 'D' : np.random.randn(8)})df
df.groupby(['A']).sum() #以A列特征分类并加总
df.groupby(['A','B']).sum()

数据透视表

df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3, 'B' : ['A', 'B', 'C'] * 4, 'C' : ['foo', 'foo', 'foo', 'bar', 'bar',  'bar'] * 2, 'D' : np.random.randn(12), 'E' : np.random.randn(12)})df
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])

6、数据可视化(画图)

import matplotlib.pyplot as pltfrom pylab import mpl mpl.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 mpl.rcParams['axes.unicode_minus']=False # 用来正常显示负号%matplotlib inlinets = 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 tsdf=ts.get_k_data('sh',start='1990-01-01')import pandas as pddf.index=pd.to_datetime(df['date'])df['close'].plot(figsize=(12,8))plt.title("上证指数走势")

标签: #pandas创建空表