读写API
HDFStore支持使用read_hdf进行读取和使用to_hdf进行写入的top-level API,类似于read_csv和to_csv的工作方式。
默认情况下,HDFStore不会丢弃全部为na的行。可以通过设置dropna = True来更改此行为。
import pandas as pd
import h5py
df_tl = pd.DataFrame({'A': list(range(5)), 'B': list(range(5))})
df_tl.to_hdf('store_tl.h5', 'table', append=True)
pd.read_hdf('store_tl.h5', 'table', where=['index>2'])
HDF数据类型
- Fixed Format
- 一次写入,重复读取,不可追加
- 不可以使用where查询,比如每次获取指定key的全部内容
- 不支持dataframe有非唯一的column
- 相比于table格式更快的读写速度
- 使用put或者to_hdf时的默认类型,也可以通过format='fixed’或format='f’指定类型
- Table Format
- 支持append操作
- 支持删除和查询类型操作
- 执行put或者to_hdf操作时通过设置format='table’或format='t’指定table格式
- pd.set_option(‘io.hdf.default_format’,‘table’) 设置默认hdf format类型
在第一次append/put操作之后,您无法更改数据列(也不能转换索引)(当然,您只需读取数据并创建新表!)。
警告HDFStore对于写入不是线程安全的。底层PyTables仅支持并发读取(通过线程或进程)。如果您需要同时进行读写,则需要在单个进程中在单个线程中序列化这些操作。否则你将破坏你的数据。
TODO 验证append是否会按照index排序的例子
Hierarchical Keys
key可以包含路径,例如’/food/apple’, 存储时会自动创建sub-stores(在pytables中是groups),可以省略路径开头的’/’,’/food/apple’和’food/apple’表示相同的key。
注意:删除操作会删除子路径下的所有内容,请小心使用
df = pd.DataFrame({'A': list(range(2)), 'B': list(range(2))})
store = pd.HDFStore('hk_test.h5')
store.append('/food/apple', df)
store.append('food/orange', df)
store.append('df',df)
print(store.keys())
for (path, subgroups, subkeys) in store.walk():
for subgroup in subgroups:
print('GROUP: {}/{}'.format(path, subgroup))
for subkey in subkeys:
key = '/'.join([path, subkey])
print('KEY: {}'.format(key))
print(store.get(key))
print(store['food/orange'])
查询
select和delete操作可以通过查询语句对数据子集进行操作,好处是可以在非常大的数据集上只检索一小部分数据。
查询表达式:
- 支持使用index和columns查询dataframe
- 支持使用major_axis、minor_axis和items查询Panel
- 如果指定data_columns,则它将被作为附加索引器
有效的比较运算符是:
=, ==, !=, >, >=, <, <=
有效的布尔表达式包括:
- | : 或操作
- & : 与操作
- ( 和 ) : 分组
例子:
- ‘index >= date’
- “columns = [‘A’, ‘D’]”
- “columns in [‘A’, ‘D’]”
- ‘columns = A’
- ‘columns == A’
- “~(columns = [‘A’, ‘B’])”
- ‘index > df.index[3] & string = “bar”’
- ‘(index > df.index[3] & index <= df.index[6]) | string = “bar”’
- “ts >= Timestamp(‘2012-02-01’)”
- “major_axis>=20130101”
不建议通过将字符串插入查询表达式来将字符串传递给查询。只需将感兴趣的字符串分配给变量,并在表达式中使用该变量。
例如:
string = "HolyMoly'"
store.select('df', 'index == string')
store.select('dfq', "index>pd.Timestamp('20130104') & columns=['A', 'B']")
store.select('dfq', where="A>0 or C>0")
store.select('df', "columns=['A', 'B']")
删除
store.remove('wp', 'major_axis > 20000102')
警告: 请注意HDF5不会自动回收h5文件中的空格。因此,反复删除(或删除节点)并再次添加,将趋于增加文件大小。
压缩
- complevel指定压缩强度,complevel = 0和complevel = None禁用压缩,0 <complevel <10启用压缩。
- complib 指定压缩库,默认使用zlib
- zlib:默认的压缩库。压缩方面的经典之作可以实现良好的压缩率,但速度有些慢。
- lzo:快速压缩和减压。
- bzip2:良好的压缩率。
- blosc:快速压缩和解压缩。
- blosc:blosclz这是blosc的默认压缩器
- blosc:lz4:紧凑,非常流行和快速的压缩机。
- blosc:lz4hc:LZ4的调整版本,以牺牲速度为代价产生更好的压缩比。
- blosc:snappy:在许多地方使用的流行压缩器。
- blosc:zlib:经典;比以前慢一些,但实现了更好的压缩比。
- blosc:zstd:非常平衡的编解码器;它提供了上述其他压缩比,并且速度相当快。
store_compressed = pd.HDFStore('store_compressed.h5', complevel=9,complib='blosc:blosclz')
store.append('df', df, complib='zlib', complevel=5)
ptrepack
重新生成压缩文件,重写文件将回收已删除的空间,也可以改变complevel
ptrepack --chunkshape=auto --propindexes --complevel=9 --complib=blosc in.h5 out.h5
性能
- fixed stores 读写速度快于 tables 格式,但tables支持追加、删除和查询操作
- 可以设置chunksize=< int >来指定chunsize大小,这将会降低写入时的内存使用量
- 设置expectedrows 可以优化读写性能
- Duplicate rows将会被写入tables,在select时会被过滤掉
我的微信公众号:pyquant