写在前面HDF是什么可视化工具Pandas内置HDF文件操作踩坑记录参考文献后记
写在前面
最近在做股价预测有关项目,需要大量股票数据,然而手头的CSV格式的数据对硬盘的占用越来越大,且读取起来速度较慢,正好了解到HDF文件具有数据库的特性,可以快速、高效读取数据,且支持压缩,内存占用较小等特点,便于数据存储及查询等操作,且Python 的Pandas库正好有相关接口,于是它就成了不二之选。
P.S.:本文主要通过Pandas
数据处理库自带的HDF
接口进行操作,想了解更多操作方法(h5py库等)详见文末动物书。
HDF是什么
HDF(Hierarchical Data File)是美国国家高级计算应用中心(National Center for Supercomputing Application,NCSA)为了满足各种领域研究需求而研制的一种能高效存储和分发科学数据的新型数据格式[1]。
HDF5文件里面的’5’是这个文件的版本,相应的还有HDF4,这里做后缀时候可以选择’hdf5’或’h5’,都是指生成HDF5文件。
可视化工具
SQL、MongoDB数据库都有自己的可视化工具,便于数据查看与操作,HDF文件也亦然。HDF-Viewer,Windows平台下HDF数据可视化工具,由于官网下载比较慢,可以从我的资源下载,附上链接。不过这个工具打开时有点慢,而且数据表不进行格式化操作的话在这里面数据会显示不完整,有兴趣可以看动物书了解更多。
Pandas内置HDF文件操作
键值操作:在指定数据进行读写时,需要指定key和value,下面的例子会详细说明。
三种模式:‘r’, ‘w’, 'a’对应文件操作的三种模式,即只读,只写,追加。
设定压缩:在生成HDF文件时,可以指定压缩所用的算法(默认BLOSC,Pandas接口的最优算法)及压缩等级(0-9,9压缩程度最高)
table数据:如果不指定存储为table格式数据,则不能进行追加和查询操作,但是这样也有一个缺点,就是耗时较长且占用内存较多,不过一般还是建议使用table。
示例代码:
Python 3.6.8
Pandas 1.0.3
import os, timeimport pandas as pd# 列过多时显示不换行pd.set_option('expand_frame_repr', False)# 设置默认为table类型,或者在数据导入时指定也可以pd.set_option('io.hdf.default_format', 'table')start = time.perf_counter()# 遍历数据CSV文件绝对路径,存入列表f_list = []for root, dirs, files in os.walk(r"E:\data\stock_data"):for f_name in files:if f_name.endswith('.csv'):f_list.append(os.path.abspath(os.path.join(root, f_name)))# 生成HDF文件,模式:写入,设定压缩等级及算法hdf_db = pd.HDFStore('stock_data.h5', mode='w', complevel=6, complib='blosc')def import_to_hdf(f_path):stock_code = f_path.split('\\')[-1].split('.')[0]# 存入文件,采用.put方法,需指定键与值hdf_db.put(key=stock_code, value=pd.read_csv(f_path))print(stock_code, '已导入')if __name__ == '__main__':for f_path in f_list:import_to_hdf(f_path)# 关闭HDF文件,否则可能会丢失数据hdf_db.close()print('总用时{:.5f}s'.format(time.perf_counter() - start))
代码运行下来总共花费了近10分钟时间,生成的HDF文件约828MB.
读取常用操作: 以下代码建议使用IPython命令行
import pandas as pd# 读取hdf文件hdf1 = pd.HDFStore("stock_data.h5", mode='a')# 读取所有键hdf1.keys()# 读取数据表,三种方法,均需要键名hdf1.sh600000# hdf1.get('sh600000')# hdf1['sh600000']# 查看hdf文件是否打开,返回布尔类型hdf1.is_open# 移除指定数据表,默认为全部数据表hdf1.remove('sh600000')# 新增数据表hdf.put(key='sh600519',value=pd.DataFrame([]))# 关闭hdf文件hdf1.close()
更多内容详见官方文档。
踩坑记录
作为小白的我总是好高骛远、年少轻狂,才学了皮毛就想玩更复杂的操作。。。下面是我使用Python操作HDF的一些坑。。
对于股票数据来说,如果能每天更新数据并同时写入这个优良的HDF中去,那真是一件事半功倍的事。但是,在一个下午的奋战后,我发现这个梦想泡汤了。原因: HDF数据如果要追加,在初次存入时一定要格式化!格式化!格式化!,否则就会报错TypeError: Cannot serialize the column [date] because its data contents are [datetime] object dtype
,各种的类型错误目不暇接。。因为对于股票数据这样需要很多列来存储的数据,其格式内容也不尽相同,例如股票代码为str
类型,而时间必须为datetime64[ns]
类型,对于时间类型的转换让人十分头疼,特别是对于HDF这样要保证绝对正确格式的文件(在我终于调试好了每日更新HDF的代码后,欣喜若狂地看着代码运行时,却在最后一只股票未完成时报了错,还是TypeError,当场崩溃…以后有机会再好好研究)。HDF数据如果追加,其占用的磁盘空间要远大于直接生成压缩好的HDF文件,例如上面生成的828MB的HDF文件,更新并追加后文件大小就增加了将近50MB了,还不如CSV省地方…
参考文献
[1] 百度百科:HDF
后记
O’Reilly Media动物书出版了Python and HDF5一书,书不算厚,100多页,但内容很丰富.有兴趣深入学习的朋友点击这里(密码:4ehj)获得此书中文版及英文版。