Python h5py:字符串列表的存储列表

Python h5py:字符串列表的存储列表,python,python-3.x,hdf5,h5py,Python,Python 3.x,Hdf5,H5py,给定字符串列表,例如: test_array = [ ['a1','a2'], ['b1'], ['c1','c2','c3','c4'] ] 我希望使用h5py存储它,以便: f['test_dataset'][0] = ['a1','a2'] f['test_dataset'][0][0] = 'a1' etc. 遵循线程中的建议 ,我尝试了以下方法: import h5py test_array = [ ['a1','a2'], ['b1'], ['c1','c2','c3','c4'

给定字符串列表,例如:

test_array = [ ['a1','a2'], ['b1'], ['c1','c2','c3','c4'] ]
我希望使用h5py存储它,以便:

f['test_dataset'][0] = ['a1','a2']
f['test_dataset'][0][0] = 'a1'
etc.
遵循线程中的建议 ,我尝试了以下方法:

import h5py
test_array = [ ['a1','a2'], ['b1'], ['c1','c2','c3','c4'] ]
with h5py.File('test.h5','w') as f:
    string_dt = h5py.special_dtype(vlen=str)
    f.create_dataset('test_dataset',data=test_array,dtype=string_dt)
但是,这会导致每个嵌套列表存储为字符串,即:

f['test_dataset'][0] = "['a1', 'a2']"
f['test_dataset'][0][0] = '['
如果使用h5py或任何其他基于hdf5的库都不可能做到这一点,我很乐意听到关于我可以用来存储数据的其他可能格式/库的任何建议

我的数据由多维numpy整数数组和嵌套的字符串列表组成,如上例所示,行数约为100M,列数约为8

谢谢

In

我建议将可变长度数组列表保存为多个数据集

In [19]: f = h5py.File('test.h5','w')
In [20]: g = f.create_group('test_array')
In [21]: test_array = [ ['a1','a2'], ['b1'], ['c1','c2','c3','c4'] ]
In [22]: string_dt = h5py.special_dtype(vlen=str)
In [23]: for i,v in enumerate(test_array):
    ...:     g.create_dataset(str(i), data=np.array(v,'S4'), dtype=string_dt)
    ...:     
In [24]: for k in g.keys():
    ...:     print(k,g[k][:])
    ...:     
0 ['a1' 'a2']
1 ['b1']
2 ['c1' 'c2' 'c3' 'c4']
对于许多小的子列表,这可能是混乱的,尽管我不确定它是否有效

使用列表联接“展平”可能会起作用

In [27]: list1 =[', '.join(x) for x in test_array]
In [28]: list1
Out[28]: ['a1, a2', 'b1', 'c1, c2, c3, c4']
In [30]: '\n'.join(list1)
Out[30]: 'a1, a2\nb1\nc1, c2, c3, c4'
可以通过几个
拆分
重新创建嵌套列表

另一个想法——把一根线腌成泡菜,然后保存它


h5py
intro

An HDF5 file is a container for two kinds of objects: datasets, which
are array-like collections of data, and groups, which are folder-like
containers that hold datasets and other groups. The most fundamental
thing to remember when using h5py is:

Groups work like dictionaries, and datasets work like NumPy arrays

pickle
不起作用

In [32]: import pickle
In [33]: pickle.dumps(test_array)
Out[33]: b'\x80\x03]q\x00(]q\x01(X\x02\x00\x00\x00a1q\x02X\x02\x00\x00\x00a2q\x03e]q\x04X\x02\x00\x00\x00b1q\x05a]q\x06(X\x02\x00\x00\x00c1q\x07X\x02\x00\x00\x00c2q\x08X\x02\x00\x00\x00c3q\tX\x02\x00\x00\x00c4q\nee.'
In [34]: f.create_dataset('pickled', data=pickle.dumps(test_array), dtype=string
    ...: _dt)
....
ValueError: VLEN strings do not support embedded NULLs
json [35]中的
:导入json
[36]:json.dumps(test_数组)
[36]:“[[“a1”、“a2”]、[“b1”]、[“c1”、“c2”、“c3”、“c4”]”
在[37]中:f.create_dataset('pickled',data=json.dumps(test_数组),dtype=string_d
…:t)
出[37]:
[43]中:json.load(f['pickled'].value)
输出[43]:[['a1',a2'],['b1'],['c1',c2',c3',c4']]

丑陋的解决方法

hf.create_dataset('test', data=repr(test_array))

您是否考虑过存储列表列表的扁平化版本:
x=['a1'、'a2'、'b1'、'c1'、'c2'、'c3'、'c4']
。如果您随后还存储索引
idx=[2,3]
(其中
x
将被拆分),那么您可以使用
np.split(x,idx)
重新生成数组列表。或者,您可以同时存储
x
和“组号”
y=[0,0,1,2,2]
,这表明
x
中的值应该属于哪个列表。我也在考虑这一点,但是这会使向现有行添加新项变得更加灵活。我也在考虑这样保存它,将行存储为字符串,并在需要时使用eval()将其转换回字符串,但这本身也存在一些其他问题。谢谢你的评论!的链接,其中的似乎可以帮助您。(基本上,他们说使用
dtype=object
,并指出这会让事情变得更慢。)感谢@3D1T0R的评论,但是当他们在上下文中说“可变长度字符串”时,我相信他们的意思是,这只是一个字符串列表,每个字符串的长度不同,即['1'、'20'、'100']。我也想这样做,但在我的例子中,问题是存储这样一个数组的多维版本。啊,是的,我在上周搜索时也看到了这个线程。问题是,这可能会导致数千万或数亿个数据集,我不确定这是否会影响性能或文件大小(可能会有一些开销?)。如何
join
将字符串收集到更大的字符串单元中?基本问题是,
HDF5
主要是为多维数字数据而开发的,而不是各种项目的一般列表。我目前使用的方法进行类似的展平,每个嵌套列表都变成字符串,即“['a1','a2']”,然后,只需使用list1=eval(“['a1','a2']”),即可将其转换为实际列表。这样存储并不是世界末日,我只是担心未来的代码可读性,并认为如果可以存储为真实数组,而不是将所有内容扁平化或字符串化,会更直观。:)酸洗可能确实是最好的选择,谢谢你的评论,我现在会详细研究一下。
json
看起来比
pickle
更有希望。
hf.create_dataset('test', data=repr(test_array))