Как отмечается в комментариях, HDF5 / h5py использует NumPy структуры массивов и не поддерживает словари. Честно говоря, я думаю, что массивы намного превосходят словари для управления такого рода данными. (Лично я бы НЕ сохранял данные gene_pair в словарях ... грязно, чтобы загружать и выгружать ... но это только я.)
Нет необходимости создавать группу gene_pair
с отдельным наборы данных для cor
и data
. Фактически, ваш метод усложняет схему, требуя доступа к 2 различным наборам данных для получения cor
и data
. Вы можете сделать все это в одном наборе данных / таблице для каждого gene_pair
(эквивалентно массиву записей NumPy). Есть много способов сделать это. Если вы можете изменить структуру данных gene_pair перед этим процессом, я настоятельно рекомендую массив записей NumPy. Он имеет естественную привязку к наборам данных HDF5 / h5py, и их создание - одношаговый процесс. Если вы не можете (или не хотите) сделать это, у меня есть 3 предложения.
Примечание. Код для создания словаря sample_N одинаков для всех методов и приведен в конце.
Кроме того, я последовал вашему примеру и создал каждый набор данных / таблицу как расширяемый набор данных с нулем строки изначально, добавляя по одной строке за раз. Это нормально для небольших выборок данных, но перераспределение больших наборов данных станет медленным, если у вас есть миллионы строк. Если вы планируете добавить много данных, я предлагаю другой подход. Выделите начальный блок больших строк (10e4?), Затем проследите за текущей строкой и расширите при необходимости дополнительными большими блоками. Этот метод только «немного» сложнее. : -)
Метод 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 для значений, которые не были введены, поэтому это может быть проблемой.
Как работает процесс: Сначала я получаю gene_pair
имен из словарей sample_N и строю список уникальных имен. Я использую этот список для создания NumPy dtype для хранения всех данных. Затем я l oop в словарях 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 use as NumPy dtype to create the dataset
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
Метод 3: Я создал этот пример, потому что этот формат набора данных / таблицы наиболее точно имитирует исходный формат словаря. Он похож на метод 2 с немного отличающимся типом и таблицей. Как и в методе 2, он имеет одну строку данных для каждой выборки с 12 дополнительными полями для значений gene_pair
и cor_val
. (Я предполагал, что у вас всегда есть 6 пар.)
# Create dictionary of names and formats to use for dtype
# Then use as NumPy dtype to create dataset
sample_table_dt = {'names':['Sample','ID'], 'formats':['S20', int] }
for cnt in range(1,7,1):
sample_table_dt['names'].append('gene_name_'+str(cnt))
sample_table_dt['formats'].append('S20')
sample_table_dt['names'].append('cor_val_'+str(cnt))
sample_table_dt['formats'].append(float)
with h5py.File("SO_61351577_3.h5", 'w') as h5f:
sample_table_ds = h5f.create_dataset('SampleTable', (0,), maxshape=(None,),
dtype=sample_table_dt, compression="gzip", compression_opts=9)
for sample_N in sample_dict:
sample_table_ds.resize(sample_table_ds.shape[0] + 1, axis=0)
sample_table_ds[-1,'Sample'] = sample_N
sample_table_ds[-1,'ID'] = int(sample_N[7:] )
gcnt = 1
for gene_pair, cor_val in sample_dict.get(sample_N).items():
sample_table_ds[-1,'gene_name_'+str(gcnt)] = gene_pair
sample_table_ds[-1,'cor_val_'+str(gcnt)] = cor_val
gcnt += 1
Код для создания словаря 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 )