Pandas、Numpy、Talib 的小知识点

        做笔试题的时候发现 pandas 没怎么学过,很久之前很潦草地看过而已,现在把金融分析里面常用的方法整理一下。

        pandas 中有若干个常用的数据类型,先来看 Series,是 pandas 中的一维数组,常用于时间序列分析。

创建 Series

        可以传入一个数组,也可以是字典(以键作为索引),

import pandas as pd
# 传入一个数列来创建一个 pandas.Series 对象
s = pd.Series([1, 2, 'mmm', 5, 7])
# 有属性 name,可以赋予字符串类型的值
s.name= 'number'

查看和修改索引

print(s.index)
# RangeIndex(start=0, stop=5, step=1)
# 表示默认情况下,一个 Series 的索引是从零开始的整数索引

new_index = pd.date_range('2016-01-01',periods = len(s), freq = 'D')
print(new_index)
# DatetimeIndex(['2016-01-01', '2016-01-02', '2016-01-03', '2016-01-04', '2016-01-05'], dtype='datetime64[ns]', freq='D')
# 用 date_range 函数输入三个变量,start,periods(end),freq 来产生一个日期索引

s.index = new_index
# 更改 s 的索引

print(s)
# 2016-01-01    1.0
# 2016-01-02    2.0
# 2016-01-03    NaN
# 2016-01-04    4.0
# 2016-01-05    5.0
# Freq: D, Name: Price series, dtype: float64

访问 Series 的元素

       习惯下我们可以像数组或元组一样直接用从 0 的整数来按顺序查看 Series 中的元素,也还可以用 s.iloc[i] 和 s.loc[i] 来访问。区别在于 loc 中需要严格按照该 Series 的索引来访问,而 iloc 是从序号也就是从 0 开始的整数索引。

        如果我们访问单个,结果是值,例如 s.iloc[0] 的结果为 1.0;而范围访问的结果仍是一个 Series。

print(type(s))
# <class 'pandas.core.series.Series'>
print(type(s.iloc[0]))
# <class 'numpy.float64'>
print(type(s.iloc[0:3]))
# <class 'pandas.core.series.Series'>

        对应的索引不是整数时,例如前面我们把索引改成了日期,然后想要按日期来切片数据,就需要引入索引对应的数据类型才可以。

from datetime import datetime
data_s= Series.loc[datetime(2017,1,1):datetime(2017,1,10)]

布尔索引

         比较 s 序列中的值是否符合标准,返回的是填充了 True 和 False 的 Series 对象,

print(s<3)
# 2016-01-01     True
# 2016-01-02     True
# 2016-01-03    False
# 2016-01-04    False
# 2016-01-05    False
# Freq: D, Name: Price series, dtype: bool

           把我们的标准放入到 loc 中(只能是 loc 不能是 iloc),返回符合标准的 Series 对象。 

print(s.loc[s<3])
# 2016-01-01    1.0
# 2016-01-02    2.0
# Freq: D, Name: Price series, dtype: float64

缺失值处理

          我们在导入文件的时候时常会发生数据缺漏的情况,而视若不见必定会对我们后续的处理带来影响。例如我们定义的 Series 中有缺失值 np.nan,有两种方法可以用:第一种是替代 fillna,用一个另外的值插入,需要传入参数 method 确定以何种方法获取值,method='ffill' 是将前一行的数据拿过来用,;第二种是删除 dropna,直接将该行删去。

创建 DataFrame 对象

         创建 DataFrame 对象的时候可以接受多种类型的输入。以字典输入为例,会将字典中的两个 Series 对象(同理是 ndarray 或 list 这种一维结构) 给组合成一个二维的结构,在这个二维结构如下,['a', 'b', 'c'] 仍然是索引,然后 'one' 和 'two' 可以通过 data.keys() 方法或者查看 data.columns 属性获取,得到的是一个 Index 类型仍是一种索引,不过如果想要获取该列不是加入中括号 [] 内的方法而是 data.one 来得到一个 Series 对象。

# 接受由 Series 组成的字典
col1 = pd.Series([1,2,3],index = ['a','b','c'])
col2 = pd.Series([5,6,7],index = ['a','b','c'])
dict = {'one':col1, 'two':col2} 
data = pd.DataFrame(dict)
print(data)
#    one  two
# a    1    5
# b    2    6
# c    3    7

        在创建 DataFrame 时可以传入参数 indexcolumns,应该说这两个参数负责"筛选"将会在 data 中展示的内容。如果给的不是 Series 对象而是 list 对象组成的字典,也就意味着没有自带 index,那么如果在创建的时候仍没有传入 index 参数那么会默认从 0 开始的整数来作为这个 dataframe 的 index。

col1 = pd.Series([1,2,3],index = ['a','b','c'])
col2 = pd.Series([5,6,7],index = ['a','b','c'])
dict = {'one':col1, 'two':col2} 
data = pd.DataFrame(dict, index = ['b', 'a'], columns = ['two','one','three'])
print(data)
#    two  one three
# b    6    2   NaN
# a    5    1   NaN

        DataFrame 对象支持一个方法 mean,接受一个参数 axis,取值为 0 表示将每一列的数据求平均,取值为 1 表示每一行的内容求平均。更多情况下还是取值为 0,因为若是 1 的话一行中的内容表示的是一只股票的开盘收盘等不同属性的值,平均值的意义不是很明显。

        目前有个小任务就是有一个 xlsx 文件,里面有多个 sheet,我们要用 pandas 导入保存成 DataFrame 格式。然后把索引设置为 datetime(否则会默认为 Index),将所有 sheets 的名字打印出来。先把文件导入一个管理器 ExcelFile 的实例中,然后再传给 read_excel,参数 sheetname 的本意是指定打开哪个 sheet,设为 None 的时候就是所有一并打开。

import pandas as pd
import numpy as np

file = pd.ExcelFile('D:/python3.6/sz50.xlsx')
data = pd.read_excel(file, sheetname = None,index_col = 'datetime')
# 此时的 data 是 OrderedDict 有序字典类型,所以下面打印的才会显示 odict_keys,与答案中的 dict_keys 不符
print(data.keys())

       得到的 OrderedDict 有着和普通 Dict 相似的操作,区别在于前者是有序的,我可以按照我存放数据的数据依次打印出来,通过如下的方法将一个 OrderedDict 的键和值给输出。

for key, value in odict.items():
    print(key, value)

        另一个任务就是,读取刚才我们创建的 DataFrame 对象 data 里编号为 600036 这只股票,将其收盘价转换成用 Numpy 的 Array 格式,并用talib计算10日均线值,返回ndarray的最后五个值。talib 是一个计算技术指标的库,里面封装了许多常用和不常用的技术指标的计算函数,接受的参数通常为 Series 或者 DataFrame。

import pandas as pd
import numpy as np
import talib as tb

file = pd.ExcelFile('D:/python3.6/sz50.xlsx')
data = pd.read_excel(file, sheetname = '600036.XSHG',index_col = 'datetime')
close = data.close.values
res = tb.MA(close, timeperiod = 10)
print(res[-5:])

         第三个任务是将MA的ndarray数据格式转换成Series格式,并加上datetime索引,最后将价格和MA值用Matplotlib展示出来。

import pandas as pd
import numpy as np
import talib as tb
import matplotlib.pyplot as plt

file = pd.ExcelFile('D:/python3.6/sz50.xlsx')
data = pd.read_excel(file, sheetname = '600036.XSHG', index_col = 'datetime')
res = tb.MA(data.close.values, 10)
close = pd.Series(res, index = data.close.index)
plt.plot(close, color = 'orange')
plt.plot(data.close, color = 'blue')
plt.show()		

        第四个任务是用talib计算50只股票的周期为5的ROCR100,生成Dataframe,并将前5只股票的ROCR100(参数timeperiod=5)用一张图显示出来。出现了一个问题就是其中一张 sheet 是空的,填充为 nan 在传给 talib.ROCR100 时会报错所以选择 pass 掉。用循环去获取有序字典的键和值,把值即一个 DataFrame 对象的 close 列转成 numpy.ndarray 的形式传给 talib.ROCR 计算得到一个 ndarray,再转成 Series 保存进字典中准备再生成所有有效的股票数据得到的 ROCR100 的字典。

       之后再提取该 DataFrame 的 columns 为一个列表方便我们用里面的名字,来依次提取 DataFrame 中的前五列数据。plot 中添加 label 为的是可以指示每条不同颜色的折线代表的对象,需要有plt.legend() 方法才能够在最后的图像中显示出来。

import pandas as pd
import numpy as np
import talib as tb
import matplotlib.pyplot as plt

file_path = 'D:/python3.6/sz50.xlsx' 
file = pd.ExcelFile(file_path)
data = pd.read_excel(file_path, sheetname = None, index_col = 'datetime')
date_index = pd.read_excel(file_path, index_col = 'datetime').index
columns_index = pd.read_excel(file_path).columns
new_dict = {}
for key,value in data.items():
	try:
		index = value.index
		new_dict[key] = pd.Series(tb.ROCR100(value.close.values, timeperiod = 5), index = index)
	except AttributeError:
		pass
df = pd.DataFrame(new_dict)
list = df.columns.values.tolist()
for i in range(5):
	plt.plot(df[list[i]],label = list[i])
plt.legend()
plt.show()

        最后一道题目。用 Pane l来计算 50 只股票的 MACD 并且输出 MACD 的 Panel 的 MultiIndex 格式。

        Panel 是继一维的 Series,二维的 DataFrame 之后的三维结构,有三个维度 items,major_xs,minor_xs 组成。在创建时需要给出一个字典,字典中的键名对应 items,字典中的值为 DataFrame 类型,DataFrame 的 major_xs 对应 index,minor_xs 对应 columns。访问 items 数据用中括号,也就是查看一个个表;访问 major_xs 数据用方法 major_xs(索引值) ,查看例如所有股票在某一天的行情;访问 minor_xs 数据用 minor_xs 方法,例如查看所有股票在所有时间上的收盘价。与创建一个 Panel 对象反向的操作是类似于我们提取字典中得 items(),对于 Panel 是 iteritems() 来获取 items 和对应的一个 DataFrame 对象。

        Panel 有个方法 transpose,顾名思义 trans+pose 改变形状,就是把我们原本 items、major_xs 和 minor_xs 中的内容交换位置。例如对一个 Panel 对象执行 transpose(2, 0, 1),结果如下。显然 2 指代 minor_xs,1 指代 major_xs 而 0 指代 items,而在 transpose 里面的位置表示改变之后原本索引(Index)新的归属。而且要注意 transpose 不是改变对象本身,而是产生一个新版本,需要把它赋给一个新变量保存起来。

 before tranposeafter transpose
items600000,600001open,close
major_xs2017-01-01600000,600001
minor_xsopen,close2017-01-01

        MultiIndex 称为 hierarchical index,分层索引,我们之前接触的 date_range 的结果 datetimeindex 和 index 都属于单层索引,分层索引就是是为了提高索引速度,将一部分索引归成一类然后所有归类的结果再组合成索引。简单的理解就是把 0-9 合成 0,把 10 到 19 合成1,以此类推,我们如果想要进入 78 这一行,首先要找到第一层 7 的索引内容然后从中再找到 78。但在 pandas 中 MultiIndex 的意义更多的是在二维情况下对数据进行更深的划分。 

       从 Panel 得到 MultiIndex 有方法 to_frame,根据官方文档中的注解,Panel.to_frame 方法是 Transform wide format into long (stacked) format as DataFrame whose columns are the Panel’s items and whose index is a MultiIndex formed of the Panel’s major and minor axes。我们希望最终得到的结果是 index 是 一个 MultiIndex,第一层索引是 datetime,然后第二层索引是股票编号,所以根据 toframe 方法计算的原则,我们在 Panel 中就要把 datetime 放到 major_xs,把股票编号放到 minor_xs,把 macd、macdsignal 等放到 items 上,所以 transpose(2,1,0)。

import pandas as pd
import numpy as np
import talib as tb
import matplotlib.pyplot as plt

file_path = 'D:/python3.6/sz50.xlsx' 
file = pd.ExcelFile(file_path)
data = pd.read_excel(file_path, sheetname = None, index_col = 'datetime')
date_index = pd.read_excel(file_path, index_col = 'datetime').index
columns_index = pd.read_excel(file_path).columns
new_dict = {}
for key,value in data.items():
	try:
		new_dict[key] = tb.abstract.MACD(value,10)
	except:
		pass
		
p = pd.Panel(new_dict)
q = p.transpose(2,1,0)
qq = q.to_frame()
print(qq.head())

         另外补充 Panel 的方法 resample 抽取数据,举个例子就是

PN.resample('W-MON',axis = 1)

        表示抽取每周周一的数据,也就是筛选。axis 应该是表示我表示日期的是在哪一个属性中也就是是 major_xs 还是 minor_xs 等,通常在 transpose 方法之后使用,就要注意经过 transpose 方法之后表示时间的项是在哪个位置。经过 resample 得到的对象不是 Panel 而是 DatetimeIndexResampler,要 to_frame 才能得到具有 MultiIndex 的 DataFrame。

        还有方法 stack,它的作用是将一个 DataFrame 对象转化成 Series 对象,这个 Series 的索引总会是 MultiIndex 的形式,其形式为 index 为外层索引而 columns 为内层索引;哪怕只有一个 columns 属性,也会固执地转化成  MultiIndex。我们转化成 Series 之后就可以添加到 MultiIndex 相同的 DataFrame 对象中去。

 

 

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值