有没有办法将每个 HDF5 数据集保存为 .csv 列?

Is there a way to save each HDF5 data set as a .csv column?

我正在努力处理 H5 文件以提取数据并将其保存为多列 csv。如图所示,h5 文件的结构由主要组(基因型、位置和分类单元)组成。主组 Genotypes 包含 1500 多个子组(基因型部分名称),每个子组包含子组(基因型的完整名称)。大约有 100 万个数据集(命名调用)-每个子组都放在一个子组中-子组 - 我需要将它们写在每个单独的专栏中。问题是,当我使用 h5py(group.get 函数)时,我必须使用任何调用的路径。我提取了路径末尾包含 "calls" 的所有路径,但我无法到达所有路径 100 万次调用将它们放入 csv 文件中。 谁能帮我提取 "calls" 这是 8 位整数 i\as 一个单独的列在 csv 文件中。 通过 运行 第一个答案中的代码,我得到了这个错误:

  1. 回溯(最近调用最后):文件 "path/file.py",第 32 行, 在 h5r.visititems(dump_calls2csv) #注意:函数名不是字符串!文件 "path/file.py",第 565 行,在 visititems 中 return h5o.visit(self.id,代理)文件 "h5py_objects.pyx",第 54 行,在 h5py._objects.with_phil.wrapper 文件中 "h5py_objects.pyx",第 55 行,在 h5py._objects.with_phil.wrapper
    中 文件 "h5py\h5o.pyx",第 355 行,在 h5py.h5o.visit 文件中 "h5py\defs.pyx",第 1641 行,在 h5py.defs.H5Ovisit_by_name 文件中 "h5py\h5o.pyx",第 302 行,在 h5py.h5o.cb_obj_simple 文件中 "path/file.py",第 564 行,在代理中 return func(name, self[name]) 文件 "path/file.py", 第 10 行,在 dump_calls2csv np.savetxt(csvfname, arr, fmt='%5d', delimiter=',') 文件“<array_function internals>”,第 6 行,在 savetxt 中文件 "path/file.py",第 1377 行,在 savetxt 中 open(fname, 'wt').close() OSError: [Errno 22] 无效参数: 'Genotypes_ArgentineFlintyComposite-C(1)-37-B-B-B2-1-B25-B2-B?-1- B:100000977_calls.csv

2020 年 5 月 16 日更新:

  • 添加了第二个使用 Pytables 读取和导出的示例(又名 表)使用 .walk_nodes()。我更喜欢这种方法而不是 h5py .visititems()
  • 为清楚起见,我将创建示例文件的代码与 2 个读取和导出 CSV 数据的示例。

下面附有 2 个简单示例,说明如何在所有顶级 object 上递归循环。为了完整起见,创建测试文件的代码位于此 post 的末尾。

示例 1:使用 h5py
此示例使用带有可调用函数 (dump_calls2csv) 的 .visititems() 方法。
此过程的摘要:
1) 检查名称中带有 calls 的数据集 objects。
2) 当找到匹配的 object 时,它会执行以下操作:
a) 将数据读入一个 Numpy 数组,
b) 创建一个唯一的文件名(在 H5 group/dataset 路径名上使用字符串替换以确保唯一性),
c) 用 numpy.savetxt() 将数据写入文件。

import h5py
import numpy as np

def dump_calls2csv(name, node):    

    if isinstance(node, h5py.Dataset) and 'calls' in node.name :
       print ('visiting object:', node.name, ', exporting data to CSV')
       csvfname = node.name[1:].replace('/','_') +'.csv'
       arr = node[:]
       np.savetxt(csvfname, arr, fmt='%5d', delimiter=',')

##########################    

with h5py.File('SO_61725716.h5', 'r') as h5r :        
    h5r.visititems(dump_calls2csv) #NOTE: function name is NOT a string!

如果你想花哨,可以把np.savetxt()中的arr换成node[:]
此外,您希望在 CSV 中使用 headers,从数据集中提取并引用 dtype 字段名称(在此示例中我没有创建任何字段名称)。

示例 2:使用 PyTables(表)
此示例使用带有过滤器的 .walk_nodes() 方法:classname='Leaf'。在 PyTables 中,叶子可以是任何存储 类(数组和 Table)。
该过程类似于上述方法。 walk_nodes() 简化了查找数据集的过程,并且不需要调用单独的函数。

import tables as tb
import numpy as np

with tb.File('SO_61725716.h5', 'r') as h5r :     
    for node in h5r.walk_nodes('/',classname='Leaf') :         
       print ('visiting object:', node._v_pathname, 'export data to CSV')
       csvfname = node._v_pathname[1:].replace('/','_') +'.csv'
       np.savetxt(csvfname, node.read(), fmt='%d', delimiter=',')

为了完整起见,请使用下面的代码创建示例中使用的测试文件。

import h5py
import numpy as np

ngrps = 2
nsgrps = 3
nds = 4
nrows = 10
ncols = 2

with h5py.File('SO_61725716.h5', 'w') as h5w :    
    for gcnt in range(ngrps):
        grp1 = h5w.create_group('Group_'+str(gcnt))
        for scnt in range(nsgrps):
            grp2 = grp1.create_group('SubGroup_'+str(scnt))
            for dcnt in range(nds):
                i_arr = np.random.randint(1,100, (nrows,ncols) )
                ds = grp2.create_dataset('calls_'+str(dcnt), data=i_arr)