如何 return 存储在 HDF5 文件中的字符串列表

How to return a list of strings stored in an HDF5 file

希望有人能对此有所启发。我正在尝试学习使用 HDF5 文件的方法。这个字符串列表以某种方式作为整数数组编码到文件中,但我无法弄清楚如何解码它。我可以使用 read_hdf 函数将文件重新插入到 pandas 中,但这不是重点——我正在尝试理解编码逻辑。这里总结了我正在使用的示例。

smiles.txt = 

structure
[11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24
[11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24
[11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)C(F)(F)F
[11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3
[11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3

>>> import pandas as pd
>>> df = pd.read_csv('smiles.txt', header=0)

>>> df.to_hdf('smiles.h5', 'table')

然后我探索新创建的 HDF5 文件的结构:

>>> import h5py
>>> with h5py.File('smiles.h5',"r") as f:
>>>    f.visit(print)

table
table/axis0
table/axis1
table/block0_items
table/block0_values

>>> with h5py.File('smiles_temp', 'r') as f:
>>>    print(list(f.keys()))
>>>    print(f['/thekey/axis0'][:])
>>>    print(f['/thekey/axis1'][:])
>>>    print(f['/thekey/block0_items'][:])
>>>    print(f['/thekey/block0_values'][:])

['thekey']
[b'structure']
[0 1 2 3 4]
[b'structure']
[array([128,   4, 149, 123,   1,   0,   0,   0,   0,   0,   0, 140,  21,
       110, 117, 109, 112, 121,  46,  99, 111, 114, 101,  46, 109, 117,
       108, 116, 105,  97, 114, 114,  97, 121, 148, 140,  12,  95, 114,
       101,  99, 111, 110, 115, 116, 114, 117,  99, 116, 148, 147, 148,
       140,   5, 110, 117, 109, 112, 121, 148, 140,   7, 110, 100,  97,
       114, 114,  97, 121, 148, 147, 148,  75,   0, 133, 148,  67,   1,
        98, 148, 135, 148,  82, 148,  40,  75,   1,  75,   5,  75,   1,
       134, 148, 104,   3, 140,   5, 100, 116, 121, 112, 101, 148, 147,
       148, 140,   2,  79,  56, 148,  75,   0,  75,   1, 135, 148,  82,
       148,  40,  75,   3, 140,   1, 124, 148,  78,  78,  78,  74, 255,
       255, 255, 255,  74, 255, 255, 255, 255,  75,  63, 116, 148,  98,
       137,  93, 148,  40, 140,  41,  91,  49,  49,  67,  72,  50,  93,
        49,  78,  67,  67,  78,  50,  67,  91,  67,  64,  64,  72,  93,
        51,  67,  67,  67,  91,  67,  64,  64,  72,  93,  51,  99,  52,
        99,  99,  99,  99,  49,  99,  50,  52, 148, 140,  40,  91,  49,
        49,  67,  72,  50,  93,  49,  78,  67,  67,  78,  50,  91,  67,
        64,  64,  72,  93,  51,  67,  67,  67,  91,  67,  64,  64,  72,
        93,  51,  99,  52,  99,  99,  99,  99,  49,  99,  50,  52, 148,
       140,  54,  91,  49,  49,  67,  72,  51,  93,  99,  49,  99,  99,
        99,  40,  99,  99,  49,  41,  99,  50,  99,  99,  40, 110, 110,
        50,  99,  51,  99,  99,  99,  40,  99,  99,  51,  41,  83,  40,
        61,  79,  41,  40,  61,  79,  41,  78,  41,  67,  40,  70,  41,
        40,  70,  41,  70, 148, 140,  44,  91,  49,  49,  67,  72,  51,
        93,  99,  49,  99,  99,  99,  99,  99,  49,  79,  91,  67,  64,
        72,  93,  40,  91,  67,  64,  64,  72,  93,  50,  67,  78,  67,
        67,  79,  50,  41,  99,  51,  99,  99,  99,  99,  99,  51, 148,
       140,  44,  91,  49,  49,  67,  72,  51,  93,  99,  49,  99,  99,
        99,  99,  99,  49,  83,  91,  67,  64,  72,  93,  40,  91,  67,
        64,  64,  72,  93,  50,  67,  78,  67,  67,  79,  50,  41,  99,
        51,  99,  99,  99,  99,  99,  51, 148, 101, 116, 148,  98,  46],
      dtype=uint8)]

如何使用 h5py 返回字符串列表?

澄清一下,数据框显示为:

In [2]: df = pd.read_csv('stack63452223.csv', header=0)                                              
In [3]: df                                                                                           
Out[3]: 
                                           structure
0          [11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24
1           [11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24
2  [11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)...
3       [11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3
4       [11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3

In [11]: df._values                                                                                  
Out[11]: 
array([['[11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24'],
       ['[11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24'],
       ['[11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)C(F)(F)F'],
       ['[11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3'],
       ['[11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3']], dtype=object)

或作为字符串列表:

In [24]: df['structure'].to_list()                                                                   
Out[24]: 
['[11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24',
 '[11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24',
 '[11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)C(F)(F)F',
 '[11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3',
 '[11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3']

h5pytables写的,与h5py不同;一般h5py可以读pytables,但细节会比较复杂

顶级键:

['axis0', 'axis1', 'block0_items', 'block0_values']

数据框有轴(行和列)。在另一个场合,我查看了数据框如何存储其值,并发现它使用 blocks,每个列都具有共同的数据类型。这里有 1 列,它是 object dtype,因为它包含字符串。

字符串在 HDF5 中有点笨拙,尤其是 unicode。 numpy 数组使用 unicode 字符串数据类型; pandas 使用对象 dtype,引用 Python 字符串(存储在数据框之外)。我怀疑 pytables 在保存这样的帧时使用了更复杂的引用方案(通过 h5py 不是很明显)。

我猜这是一个很长的答案,只是说我不知道​​。

Pandas 自己的 h5 负载:

In [19]: pd.read_hdf('stack63452223.h5', 'table')                                                    
Out[19]: 
                                           structure
0          [11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24
1           [11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24
2  [11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)...
3       [11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3
4       [11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3

h5对象还有attrs,

In [38]: f['table'].attrs.keys()                                                                     
Out[38]: <KeysViewHDF5 ['CLASS', 'TITLE', 'VERSION', 'axis0_variety', 'axis1_variety', 'block0_items_variety', 'encoding', 'errors', 'nblocks', 'ndim', 'pandas_type', 'pandas_version']>
 

摆弄我发现:

In [66]: x=f['table']['block0_values'][0]                                                            
In [67]: b''.join(x.view('S1').tolist())                                                             
Out[67]: b'\x80\x04\x95y\x01\x8c\x15numpy.core.multiarray\x94\x8c\x0c_reconstruct\x94\x93\x94\x8c\x05numpy\x94\x8c\x07ndarray\x94\x93\x94K\x85\x94C\x01b\x94\x87\x94R\x94(K\x01K\x05K\x01\x86\x94h\x03\x8c\x05dtype\x94\x93\x94\x8c\x02O8\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK?t\x94b\x89]\x94(\x8c)[11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24\x94\x8c([11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24\x94\x8c6[11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)C(F)(F)F\x94\x8c,[11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3\x94\x8c,[11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3\x94et\x94b.'

看起来你的字符串在那里。 uint8是一个单字节的dtype,可以看成byte。加入他们我看到你的字符串,以某种方式连接。

正在重新格式化:

Out[67]: b'\x80\x04\x95y\x01\x8c\x15numpy.core.multiarray\x94\x8c\x0c_reconstruct\x94\x93\x94\x8c\x05numpy\x94\x8c\x07ndarray\x94\x93\x94K\x85\x94C\x01b\x94\x87\x94R\x94(K\x01K\x05K\x01\x86\x94h\x03\x8c\x05dtype\x94\x93\x94\x8c\x02O8\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK?t\x94b\x89]\x94(\x8c)
[11CH2]1NCCN2C[C@@H]3CCC[C@@H]3c4cccc1c24\x94\x8c(
[11CH2]1NCCN2[C@@H]3CCC[C@@H]3c4cccc1c24\x94\x8c6
[11CH3]c1ccc(cc1)c2cc(nn2c3ccc(cc3)S(=O)(=O)N)C(F)(F)F\x94\x8c,
[11CH3]c1ccccc1O[C@H]([C@@H]2CNCCO2)c3ccccc3\x94\x8c,
[11CH3]c1ccccc1S[C@H]([C@@H]2CNCCO2)c3ccccc3\x94et\x94b.'