当前位置: 首页 > 科技观察

使用hdf5在pandas中高效存储数据

时间:2023-03-15 08:54:31 科技观察

一、介绍HDF5(HierarchicalDataFormal)是一种理想的存储大规模数值型数据的存储格式。文件后缀为h5,存储和读取速度非常快,数据可以在文件内层次分明地存储。同样的HDF5可以看作是一个高度集成的文件夹,可以存放不同类型的数据。在Python中操作HDF5文件的主要方法有两种。一种是利用pandas内置的一系列HDF5文件操作相关方法,将pandas中的数据结构保存在HDF5文件中。另一种是使用h5py模块完成从保存Python原生数据结构到HDF5格式。本文将介绍pandas读写HDF5文件的方法。图12.使用pandas操作HDF5文件1.写出文件。pandas中的HDFStore()用于生成管理HDF5文件IO操作的对象。其主要参数如下:“path”:字符输入,用于指定h5文件名(不在当前工作目录时需要完整路径信息)“mode”:用于指定IO操作的模式,与Python内置的open()中的参数,默认为'a',即当指定文件已经存在时,不会影响原始数据的写入。如果指定的文件不存在,将创建一个新文件;'r',只读模式;'w',创建一个新文件(旧的同名文件会被覆盖);'r+',与'a'功能类似,但文件必须已经存在;"complevel":int类型,用于控制h5文件的压缩级别,取值范围在0-9之间,文件越大,压缩程度越大,占用的空间越小,但相应的,需要读取文件时有更多时间解压缩。默认为0,表示不压缩。接下来,我们创建一个HDF5IO对象存储:importpandasaspdstore=pd.HDFStore('demo.h5')'''Viewstoretype'''print(store)图2显示存储对象属于pandas的io类。通过上面的语句,我们已经成功初始化了名为demo.h5的文件,本地会出现相应的文件。接下来,我们在pandas中创建两个不同的对象,并将它们一起保存在store中。首先创建一个Series对象:importnumpyasnp#创建一个series对象s=pd.Series(np.random.randn(5),index=['a','b','c','d','e'])s图3然后我们创建一个DataFrame对象:#Createadataframeobjectdf=pd.DataFrame(np.random.randn(8,3),columns=['A','B','C'])df图4第一种方法使用键值对在store对象中存储不同的数据:store['s'],store['df']=s,df第二种方法使用store对象的put()方法,其主要参数如下:“key”:指定h5文件中要写入的数据的key“value”:指定key对应的要写入的key输入数据“format”:字符输入,用于指定写入模式,'fixed'对应的模式速度快,但不支持追加或检索;'table'对应的mode是以表格形式写的,速度稍慢,但是支持直接通过store对象进行追加和查表操作使用put()方法将数据存入store对象:store.put(key='s',value=s);store.put(key='df',value=df)由于是键值对的格式,可以查看store的items属性(注意这里的store对象只有items和keys属性,andhasnovaluesattribute):store.items图5调用store对象中的数据直接用对应的键名索引即可:store['df']图6删除指定数据的方法有两种存储对象。一种是使用remove()方法传入待删除数据对应的key:store。remove('s')第二种是在Python中使用关键字del来删除指定的数据:delstore['s']这时候如果想在本地持久化当前的store对象,只需要使用close()方法关闭store对象就可以了,而且除了定义一个确切的store对象外,还可以直接将pandas中的数据结构导出到本地的h5文件中:#createanewdataframedf_=pd.DataFrame(np.random.randn(5,5))#导出到已有的h5文件,这里需要指定keydf_.to_hdf(path_or_buf='demo.h5',key='df_')#在本地demo.h5中创建一个store对象用于IO连接store=pd.HDFStore('demo.h5')#查看指定的h5对象Allkeysprint(store.keys())图72.读入文件pandas中读入HDF5文件主要有两种方式,一种是创建一个连接到本地h5文件的IO对象,方式与上一节类似,然后使用key索引或者store对象的get()方法传入key提取数据读入指定数据:store=pd.HDFStore('demo.h5')'''方法1'''df1=store['df']'''方法二'''df2=store.get('df')df1==df2如图8所示两种方法都可以成功读取key对应的数据第二种读取h5格式文件中数据的方法是pandas中的read_hdf()。其主要参数如下:“path_or_buf”:传入指定h5文件的名称“key”:提取数据的key。read_hdf()读取h5文件时,对应的文件不能同时有其他未关闭的IO对象,否则会报错,如下例:print(store.is_open)df=pd.read_hdf('demo.h5',key='df')图9关闭IO对象后,再次解压:store.close()print(store.is_open)df=pd.read_hdf('demo.h5',key='df')df图103.性能测试下面我们来测试一下存储相同数据的csv格式文件和h5格式文件的读取速度差异:这里我们首先创建一个非常大的数据框,它由1亿行x5列的标准正态分布的随机数,然后用pandas写出HDF5和csv格式的文件进行持久化存储:importpandasapdimportnumpyasnpimporttimestore=pd.HDFStore('store.h5')#生成一个1亿行5列的标准正态分布随机数表df=pd.DataFrame(np.random.rand(100000000,5))start1=time.clock()store['df']=dfstore.close()print(f'HDF5存储时间{time.clock()-start1}秒')start2=time.clock()df.to_csv('df.csv',index=False)print(f'csv存储时间{time.clock()-start2}seconds')图11中写入相同大小的数据帧时,HDF5比常规csv快近50倍,两者存储后文件大小差异较大:图12csv占用近两倍于HDF5的空间,还在我们的空间里如果没有启用HDF5压缩,那么我们关闭所有的IO连接,然后运行下面的代码,比较恢复到dataframe中的上述两个文件中的数据的时间差:importpandasaspdimporttimestart1=time.clock()store=pd.HDFStore('store.h5',mode='r')df1=store.get('df')print(f'HDF5读取时间{time.clock()-start1}秒')start2=time.clock()df2=pd.read_csv('df.csv')print(f'csvreadingtakes{time.clock()-start2}seconds')图13HDF5只需要csv的1/13,所以当涉及到数据存储,尤其是大规模数据时,HDF5是你最好的选择