下面是学习《Python金融大数据分析》一书第9章“输入/输出操作”的笔记。若想查看细节,可阅读原书~
将python对象写入磁盘,办法之一是使用pickle模块,这个模块可以序列化大部分Python对象。
import pickle
import numpy as np
from random import gauss
#导入高斯生成正态分布随机数
a=[gauss(1.5,2) for i in range(1000000)]
'''
存储单个对象
'''
#设置要保存的路径
path=‘’
#为二进制模式(wb)打开文件
pkl_file=open(path+'data.pkl','wb')
#序列化对象a,并将其保存到文件
pickle.dump(a, pkl_file)
#关闭文件
pkl_file.close()
'''
读取单个对象
'''
#为二进制读模式(rb)打开文件
pkl_file=open(path+'data.pkl','rb')
#从磁盘读取对象并反序列化
b=pickle.load(pkl_file)
'''
比较a和b是否相同
'''
np.allclose(np.array(a),np.array(b)) #True、
'''
存储多个对象
'''
x=np.array(a)
y=np.array(a)**2
#为二进制模式(wb)打开文件
pkl_file=open(path+'data.pkl','wb')
#保存为字典格式
pickle.dump({'x':x,'y':y}, pkl_file)
#关闭文件
pkl_file.close()
'''
读取多个对象
'''
#为二进制读模式(rb)打开文件
pkl_file=open(path+'data.pkl','rb')
#从磁盘读取对象并反序列化
data=pickle.load(pkl_file)
pkl.close()
'''
查看输出结果
'''
for key in data.keys():
print(key, data[key][:4])
尽管CSV文件有特殊的结构,但是这种文件本质上还是普通文本文件。CSV文件很重要也很常见,因此Python标准库中有一个CSV模块,可以返回列表对象或者字典对象的一个列表。(当然,Pandas读取会更加方便)
import csv
'''
将每一行当作列表对象返回
'''
with open(path+'data.csv','r') as f:
csv_reader=csv.reader(f)
lines=[line for line in csv_reader]
'''
将每一行当作OrderedDic(有序字典)对象返回,该对象是字典的特例
即返回的每一行为OrderedDic([(列名1,列值1),(列名2,列值2),(列名3,列值3),(列名3,列值3),……])
'''
with open(path+'data.csv','r') as f:
csv_reader=csv.DicReader(f)
lines=[line for line in csv_reader]
ndarry对象的保存经过了高度优化,因此相当快速。
import numpy as np
# datetime64[m]为以分为单位的时间格式
dtimes=np.arange('2019-01-01 10:00:00','2025-12-31 22:00:00',dtype='datetime64[m]')
#为结构数组定义特殊的dtype对象
dty=np.dtype([('Date','datetime64[m]'),('No1','f'),('No2','f')])
#用特殊dtype来实例化ndarray对象
data=np.zeros(len(dtimes),dtype=dty)
'''
填充
'''
data['Date']=dtimes
a=np.random.standard_normal((len(dtimes),2)).round(4)
data['No1']=a[:,0]
data['No2']=a[:,1]
'''
保存及读取数据
'''
np.save(path+'array',data)
np.load(path+'array.npy')
numpy也可以创建类似于dataframe的对象。
pandas 库的主要优势之一是可以原生读取和写入不同的数据格式,包括:
用pandas读取整个表或者查询结果通常更为高效
import cx_Oracle
import pandas as pd
# 下面以查询wind底层数据库filesync为例
cx_Oracle.init_oracle_client(lib_dir='instantclient_21_3路径')
conn = cx_Oracle.connect('用户名', '密码', 'ip')
testSql='''
SELECT TRADE_DT ,S_DQ_CLOSE enjie
FROM FILESYNC.AShareEODPrices
WHERE S_INFO_WINDCODE LIKE '002812.SZ'
ORDER BY TRADE_DT
'''
data=pd.read_sql(testSql,conn)
data.head()
PyTable是Python与HDF5数据库/文件标准的结合。专门为优化I/O操作的性能、最大限度地利用可用硬件而设计。
PyTable提供了基于文件的数据库格式。其他数据需要服务器/客户端架构。事实证明,对于交互式数据和金融分析,基于文件的数据库更方便一些,也足以应付大部分场合。
import tables as tb
import numpy as np
import datetime as dt
filename=path+'pytab.h5'
h5=tb.open_file(filename,'w')
row_des={'Date':tb.StringCol(26,pos=1),
'No1':tb.IntCol(pos=2),
'No2':tb.IntCol(pos=3),
'No3':tb.Float64Col(pos=4),
"No4":tb.Float64Col(pos=5)}
rows=20000000
#指定压缩级别
filters=tb.Filters(complevel=0)
tab=h5.create_table('/','ints_floats', #表的节点和技术名称
row_des,
title='Integers and Floats',
expectedrows=rows, #预期行数,可优化
filters=filters)
#创建指针对象
pointer=tab.row
ran_int=np.random.randint(0,10000,size=(rows,2))
ran_flo=np.random.standard_normal((rows,2)).round(4)
for i in range(rows):
pointer['Date']=dt.datetime.now()
pointer['No1']=ran_int[i,0]
pointer['No2']=ran_int[i,1]
pointer['No3']=ran_flo[i,0]
pointer['No4']=ran_flo[i,1]
pointer.append() #附加新行
tab.flush() #所有写入的行都必须flush,也就是提交为永久性更改
上述例子中Python循环相当慢,可以通过Numpy结构数据提升性能
dty=np.dtype([('Date','S26'),('No1','),('No2','),
('No3','),('No4',')])
sarray=np.zeros(len(ran_int),dtype=dty)
sarray['Date']=dt.Datetime.now()
sarray['No1']=ran_int[:,0]
sarray['No2']=ran_int[:,1]
sarray['No3']=ran_flo[:,0]
sarray['No4']=ran_flo[:,1]
h5.create_table('/','ints_floats_from_array',sarray,
title='Integers and Floats',
expectedrows=rows, #预期行数,可优化
filters=filters)
h5.remove_node('/','ints_floats_from_array') #删除包含冗余数据的第二个Table对象
Table对象在大多数情况下与Numpy结构化数组的表现很相似
PyTables还提供了通过典型类SQL语句查询数据的灵活工具
query='((No3<-0.5) | (No3>0.5)) & ((No4<-1) | (No4>1))'
iterator = tab.where(query) #基于查询的迭代器对象
res=[(row['No3'], row['No4']) for row in iterator]
res=np.array(res)
使用PyTable的主要优势之一是压缩方法。使用压缩不仅能节约磁盘空间,还能改善I/O操作的性能。
filters=tb.Filters(complevel=5, #压缩级别,参数取值范围为0-9
complib='blosc') #使用Blosc压缩引擎,该引擎优化了性能