微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 hdf5

如何解决如何在 hdf5

我最近了解了 hdf5 压缩并使用它。在处理巨大文件时,它比 .npz/npy 有一些优势。 我设法尝试了一个小列表,因为我有时会使用具有如下字符串的列表;

def write():
    test_array = ['a1','a2','a1','a2']
    

    with  h5py.File('example_file.h5','w') as f:
        f.create_dataset('test3',data=repr(test_array),dtype='S',compression='gzip',compression_opts=9) 
        f.close()
    

但是我遇到了这个错误

f.create_dataset('test3',compression_opts=9)
  File "/usr/local/lib/python3.6/dist-packages/h5py/_hl/group.py",line 136,in create_dataset
    dsid = dataset.make_new_dset(self,shape,dtype,data,**kwds)
  File "/usr/local/lib/python3.6/dist-packages/h5py/_hl/dataset.py",line 118,in make_new_dset
    tid = h5t.py_create(dtype,logical=1)
  File "h5py/h5t.pyx",line 1634,in h5py.h5t.py_create
  File "h5py/h5t.pyx",line 1656,line 1689,line 1508,in h5py.h5t._c_string
ValueError: Size must be positive (size must be positive)

在网上搜索了几个小时以寻找更好的方法后,我无法得到。 有没有更好的方法来用 H5 压缩列表?

解决方法

你很近。 data= 参数旨在处理现有的 NumPy 数组。当您使用 List 时,它会在幕后转换为 Array。它适用于数字列表。 (请注意,列表和数组是不同的 Python 对象类。)

您在转换字符串列表时遇到了问题。默认情况下,dtype 设置为 NumPy 的 Unicode 类型(在您的情况下为 'HDF5 不支持宽字符。与其尝试破解并“假装”支持它,如果您尝试存储这种类型的数据,h5py 会引发错误。" 有关 NumPy 和字符串的完整详细信息,请访问此链接:h5py doc: Strings in HDF5

我稍微修改了您的示例以展示如何使其工作。请注意,我显式创建了 NumPy 字符串数组,并声明了 dtype='S2' 以获得所需的字符串 dtype。我添加了一个使用整数列表的示例来展示列表如何处理数字。 然而,NumPy 数组是首选的数据对象。

我删除了 f.close() 语句,因为这在使用上下文管理器(with / as: 结构)时不是必需的

此外,请注意压缩级别。与 compression_opts=9 相比,compression_opts=1 将获得(稍微)更多的压缩,但每次访问数据集时,您都将支付 I/O 处理时间。我建议从 1 开始。

import h5py
import numpy as np

test_array = np.array(['a1','a2','a1','a2'],dtype='S2')

data_list = [ 1,2,3,4,5,6,7,8,9 ]

with h5py.File('example_file.h5','w') as f:
     f.create_dataset('test3',data=test_array,compression='gzip',compression_opts=9) 

     f.create_dataset('test4',data=data_list,compression_opts=1) 
,

这是嵌套列表的更一般的答案,其中每个嵌套列表的长度不同。当嵌套列表长度相等时,它也适用于更简单的情况。有两种解决方案:一种使用 h5py,一种使用 PyTables。

h5py 示例
h5py 不支持参差不齐的数组,因此您必须根据最长的子字符串创建一个数据集,并将元素添加到“短”子字符串中。 您将在嵌套列表中没有对应值的每个数组位置获得 'None'(或子字符串)。请注意 dtype= 条目。这显示了如何找到列表中最长的字符串(如 slen=##)并使用它来创建 dtype='S##'

import h5py
import numpy as np

test_list = [['a01','a02','a03','a04','a05','a06'],['a11','a12','a13','a14','a15','a16','a17'],['a21','a22','a23','a24','a25','a26','a27','a28']]

# arrlen and test_array from answer to SO #10346336 - Option 3:
# Ref: https://stackoverflow.com/a/26224619/10462884    
slen = max(len(item) for sublist in test_list for item in sublist)
arrlen = max(map(len,test_list))
test_array = np.array([tl+[None]*(arrlen-len(tl)) for tl in test_list],dtype='S'+str(slen))
  
with h5py.File('example_nested.h5',compression='gzip')

PyTable 示例
PyTables 支持不规则的二维数组作为 VLArrays(可变长度)。这避免了为“短”子字符串添加“无”值的复杂性。此外,您不必提前确定数组长度,因为在创建 VLArray 时未定义行数(创建后添加行)。再次注意 dtype= 条目。这使用与上面相同的方法。

import tables as tb
import numpy as np

test_list = [['a01','a28']]
   
slen = max(len(item) for sublist in test_list for item in sublist)

with tb.File('example_nested_tb.h5','w') as h5f:        
    vlarray = h5f.create_vlarray('/','vla_test',tb.StringAtom(slen) ) 
    for slist in test_list:
        arr = np.array(slist,dtype='S'+str(slen))
        vlarray.append(arr)

    print('-->',vlarray.name)
    for row in vlarray:
        print('%s[%d]--> %s' % (vlarray.name,vlarray.nrow,row))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。