如何压缩 hdf5 中的 lists/nested 列表
how to compress lists/nested lists in hdf5
我最近了解到 hdf5 压缩并使用它。在处理巨大的文件时,它比 .npz/npy 有一些优势。
我设法尝试了一个小列表,因为我有时会使用具有如下字符串的列表;
def write():
test_array = ['a1','a2','a1','a2','a1','a2', 'a1','a2', 'a1','a2','a1','a2','a1','a2', 'a1','a2', 'a1','a2','a1','a2','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', data=repr(test_array), dtype='S', compression='gzip', 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, in h5py.h5t.py_create
File "h5py/h5t.pyx", line 1689, in h5py.h5t.py_create
File "h5py/h5t.pyx", line 1508, in h5py.h5t._c_string
ValueError: Size must be positive (size must be positive)
在网上搜索了几个小时以找到更好的方法后,我还是找不到。
有没有更好的方法用H5压缩列表?
你很接近。 data=
参数旨在与现有的 NumPy 数组一起使用。当您使用列表时,它会在后台转换为数组。它适用于数字列表。 (请注意,列表和数组是不同的 Python 对象 类。)
您 运行 遇到转换字符串列表的问题。默认情况下,dtype 设置为 NumPy 的 Unicode 类型(在您的情况下为“HDF5 不支持宽字符。如果您尝试存储这种类型的数据,h5py 不会尝试绕过它并“假装”支持它,而是会引发错误。" link 处有关 NumPy 和字符串的完整详细信息:h5py doc: Strings in HDF5
我稍微修改了您的示例以展示如何让它工作。请注意,我明确创建了 NumPy 字符串数组,并声明了 dtype='S2'
以获得所需的字符串 dtype。我添加了一个使用整数列表的示例来展示列表如何处理数字。 但是,NumPy 数组是首选数据对象。
我删除了 f.close()
语句,因为在使用上下文管理器(with / as:
结构)时不需要这样做
此外,请注意压缩级别。与 compression_opts=1
相比,compression_opts=9
的压缩率会(稍微)高一些,但每次访问数据集时都会花费 I/O 的处理时间。我建议从 1.
开始
import h5py
import numpy as np
test_array = np.array(['a1','a2','a1','a2','a1','a2', 'a1','a2',
'a1','a2','a1','a2','a1','a2', 'a1','a2',
'a1','a2','a1','a2','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='gzip', compression_opts=1)
这是嵌套列表的更通用的答案,其中每个嵌套列表的长度不同。当嵌套列表长度相等时,它也适用于更简单的情况。有 2 种解决方案:一种使用 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:
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', 'w') as f:
f.create_dataset('test3', data=test_array, compression='gzip')
PyTables 示例
PyTables 支持参差不齐的二维数组作为 VLArrays(可变长度)。这避免了为“短”子字符串添加 'None' 值的复杂性。此外,您不必提前确定数组长度,因为在创建 VLArray 时未定义行数(行在创建后添加)。再次注意 dtype=
条目。这使用与上述相同的方法。
import tables as tb
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']]
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))
我最近了解到 hdf5 压缩并使用它。在处理巨大的文件时,它比 .npz/npy 有一些优势。 我设法尝试了一个小列表,因为我有时会使用具有如下字符串的列表;
def write():
test_array = ['a1','a2','a1','a2','a1','a2', 'a1','a2', 'a1','a2','a1','a2','a1','a2', 'a1','a2', 'a1','a2','a1','a2','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', data=repr(test_array), dtype='S', compression='gzip', 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, in h5py.h5t.py_create
File "h5py/h5t.pyx", line 1689, in h5py.h5t.py_create
File "h5py/h5t.pyx", line 1508, in h5py.h5t._c_string
ValueError: Size must be positive (size must be positive)
在网上搜索了几个小时以找到更好的方法后,我还是找不到。 有没有更好的方法用H5压缩列表?
你很接近。 data=
参数旨在与现有的 NumPy 数组一起使用。当您使用列表时,它会在后台转换为数组。它适用于数字列表。 (请注意,列表和数组是不同的 Python 对象 类。)
您 运行 遇到转换字符串列表的问题。默认情况下,dtype 设置为 NumPy 的 Unicode 类型(在您的情况下为“
我稍微修改了您的示例以展示如何让它工作。请注意,我明确创建了 NumPy 字符串数组,并声明了 dtype='S2'
以获得所需的字符串 dtype。我添加了一个使用整数列表的示例来展示列表如何处理数字。 但是,NumPy 数组是首选数据对象。
我删除了 f.close()
语句,因为在使用上下文管理器(with / as:
结构)时不需要这样做
此外,请注意压缩级别。与 compression_opts=1
相比,compression_opts=9
的压缩率会(稍微)高一些,但每次访问数据集时都会花费 I/O 的处理时间。我建议从 1.
import h5py
import numpy as np
test_array = np.array(['a1','a2','a1','a2','a1','a2', 'a1','a2',
'a1','a2','a1','a2','a1','a2', 'a1','a2',
'a1','a2','a1','a2','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='gzip', compression_opts=1)
这是嵌套列表的更通用的答案,其中每个嵌套列表的长度不同。当嵌套列表长度相等时,它也适用于更简单的情况。有 2 种解决方案:一种使用 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:
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', 'w') as f:
f.create_dataset('test3', data=test_array, compression='gzip')
PyTables 示例
PyTables 支持参差不齐的二维数组作为 VLArrays(可变长度)。这避免了为“短”子字符串添加 'None' 值的复杂性。此外,您不必提前确定数组长度,因为在创建 VLArray 时未定义行数(行在创建后添加)。再次注意 dtype=
条目。这使用与上述相同的方法。
import tables as tb
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']]
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))