如何将多个词典保存到hdf5并合并来自不同词典的公用密钥的信息?

问题描述 投票:0回答:1

简而言之,我感兴趣的是有什么有效的方法可以将带有公共密钥的多个词典保存到hdf5文件中。

也许我有N个具有以下结构的字典(在下面的示例中,我将使用2个字典):

sample_1 = {'gene1_gene1': 1,
            'gene1_gene2': -0.385,
            'gene1_gene3': 0.25,
            'gene2_gene2': 1,
            'gene2_gene3': 0.004,
            'gene3_gene3': 1
           }
sample_2 = {'gene1_gene1': 1,
            'gene1_gene2': -0.0035,
            'gene1_gene4': 0.0421,
            'gene2_gene2': 1,
            'gene2_gene4': -0.0783,
            'gene4_gene4': 1
           }

每个词典包含M个键。一些键对于多个词典是通用的(例如gene1_gene2),某些键是唯一的(例如gene2_gene3gene2_gene4)。我想将每本字典保存到一个具有这样结构的hdf5文件中:

{
    'gene1_gene2': {
         'sample_1': -0.385,
         'sample_2': -0.0035,
         ....
    }
    ....
}

因此该文件必须同时包含每个键的值和相应的样本名称。

此后,我想使用目标geneX_geneY对从hdf5文件中提取样本名称和值。

为此,我编写此代码:

with h5py.File("out_file.hdf5", 'a') as f:
    for gene_pair, cor_val in sample_N.items():
        try:
            grp = f.create_group(gene_pair)
            grp.create_dataset('data', (0,), maxshape=(None,), dtype=h5py.string_dtype(encoding='ascii'),
                               compression="gzip", compression_opts=9)
            grp.create_dataset('cor', (0,), maxshape=(None,), dtype='f4', compression="gzip", compression_opts=9)
            data = f[gene_pair]['data']
            cor = f[gene_pair]['cor']
            cor.resize(cor.shape[0] + 1, axis=0)
            cor[-1] = cor_val
            data.resize(data.shape[0] + 1, axis=0)
            data[-1] = 'sample_N'
        except:
            data = f[gene_pair]['data']
            cor = f[gene_pair]['cor']
            cor.resize(cor.shape[0] + 1, axis=0)
            cor[-1] = cor_val
            data.resize(data.shape[0] + 1, axis=0)
            data[-1] = 'sample_N'

简而言之,代码创建了与geneX_geneY键相对应的组,并将值(f[gene_pair]['cor'])和数据集名称(f[gene_pair]['data'])保存到具有numpy数组的相应数据集。

我很感兴趣,有什么有效的方法吗?

python hdf5 h5py
1个回答
0
投票

如评论中所述,HDF5 / h5py使用NumPy数组结构,不支持字典。坦率地说,我认为数组在管理此类数据方面远胜于字典。 (就我个人而言,我不会将gene_pair数据存储在字典中……加载和卸载时会很混乱……但这就是我。)

不需要创建带有单独的gene_paircor数据集的data组。实际上,您的方法使模式复杂化,需要访问2个不同的数据集才能获得cordata。您可以在每个gene_pair的单个数据集/表中完成所有工作(等同于NumPy记录数组)。有很多方法可以做到这一点。如果可以在此过程的上游更改gene_pair数据结构,则强烈建议使用NumPy记录数组。它具有到HDF5 / h5py数据集的自然映射,创建它们是一个一步的过程。如果您不能(或不想这样做),我有2条建议。注意:创建sample_N字典的代码对于这两种方法都是相同的,并在末尾提供。

方法1:

这是符合您要求的表格格式。它为每个gene_pair创建一个数据集(表)。数据集名称为gene_pair,它具有3个字段:Sample_ID(文本),ID(提取的整数)和与此样本相关联的测试值。
with h5py.File("SO_61351577_1.h5", 'w') as h5f:
  for sample_N in sample_dict:
    for gene_pair, cor_val in sample_dict.get(sample_N).items():
        gene_dt = np.dtype ([ ('Sample', 'S20'), ('ID', int), ('Value', float) ]) 
        if gene_pair not in h5f.keys() :
            gene_pair_ds = h5f.create_dataset(gene_pair, (1,), maxshape=(None,), dtype=gene_dt,
                           compression="gzip", compression_opts=9)
        else:
            gene_pair_ds = h5f[gene_pair]
            gene_pair_ds.resize(gene_pair_ds.shape[0] + 1, axis=0)
        gene_pair_ds[-1,'Sample'] = sample_N
        gene_pair_ds[-1,'ID'] = int(sample_N[7:] )
        gene_pair_ds[-1,'Value']  = cor_val

方法2:

这使用不同的表格格式。每个样本都有一行数据,并且在匹配的列/字段下有测试值。这只是您的建议。如果对的数量很大(例如> 100),则没有任何意义。另外,该表的未输入值为0.0,因此可能会出现问题。该过程如何工作:首先,我从sample_N字典中获得gene_pair名称,并建立一个唯一名称列表。我使用此列表创建一个NumPy dtype来保存所有数据。然后,我循环访问sample_N字典,并将该样本的所有gene_pair值写在同一行上。映射到字段/列是通过gene_pair名称完成的。
#Create a list of unique dictionary keys:
gene_list = []
for sample_N in sample_dict:
    for gene_pair in sample_dict.get(sample_N):
        if gene_pair not in gene_list:
            gene_list.append(gene_pair)
gene_list.sort()
# Create dictionary of names and formats to use for dtype
# Then create NumPy dtype from the dictionary
dt_genetable = {'names':['Sample','ID'], 'formats':['S20', int] }
for gene_name in gene_list:
     dt_genetable['names'].append(gene_name)
     dt_genetable['formats'].append(float)

with h5py.File("SO_61351577_2.h5", 'w') as h5f:
    genetable_ds = h5f.create_dataset('GeneTable', (0,), maxshape=(None,), 
                        dtype=dt_genetable, compression="gzip", compression_opts=9)

    for sample_N in sample_dict:
        genetable_ds.resize(genetable_ds.shape[0] + 1, axis=0)
        genetable_ds[-1,'Sample'] = sample_N
        genetable_ds[-1,'ID'] = int(sample_N[7:] )
        for gene_pair, cor_val in sample_dict.get(sample_N).items():
            print (sample_N, ':', gene_pair, ':', cor_val)
            genetable_ds[-1,gene_pair]  = cor_val

创建sample_N字典的代码:

sample_1 = {'gene1_gene1': 1,
            'gene1_gene2': -0.385,
            'gene1_gene3': 0.25,
            'gene2_gene2': 1,
            'gene2_gene3': 0.004,
            'gene3_gene3': 1
           }
sample_2 = {'gene1_gene1': 1,
            'gene1_gene2': -0.0035,
            'gene1_gene4': 0.0421,
            'gene2_gene2': 1,
            'gene2_gene4': -0.0783,
            'gene4_gene4': 1
           }
sample_3 = {'gene1_gene1': 1,
            'gene1_gene2': -0.065,
            'gene1_gene4': 0.0567,
            'gene2_gene2': 1,
            'gene2_gene3': -0.0378,
            'gene4_gene4': 1
           }

sample_dict = dict( sample_1=sample_1,
                    sample_2=sample_2,
                    sample_3=sample_3 )
© www.soinside.com 2019 - 2024. All rights reserved.