尝试通过使用 h5py 更改索引字段类型来缩小 HDF5 文件的大小

Posted

技术标签:

【中文标题】尝试通过使用 h5py 更改索引字段类型来缩小 HDF5 文件的大小【英文标题】:Trying to size down HDF5 File by changing index field types using h5py 【发布时间】:2019-08-29 18:57:53 【问题描述】:

我有一个非常大的 CSV 文件 (~12Gb),看起来像这样:

posX,posY,posZ,eventID,parentID,clockTime -117.9853515625,60.2998046875,0.29499998688697815,0,0,0 -117.9853515625,60.32909393310547,0.29499998688697815,0,0,0 -117.9560546875,60.2998046875,0.29499998688697815,0,0,0 -117.9560546875,60.32909393310547,0.29499998688697815,0,0,0 -117.92676544189453,60.2998046875,0.29499998688697815,0,0,0 -117.92676544189453,60.32909393310547,0.29499998688697815,0,0,0 -118.04051208496094,60.34012985229492,4.474999904632568,0,0,0 -118.04051208496094,60.36941909790039,4.474999904632568,0,0,0 -118.04051208496094,60.39870834350586,4.474999904632568,0,0,0

我想使用库 h5py 将此 CSV 文件转换为 HDF5 格式,同时通过设置字段/索引类型 i.G. 来降低总文件大小。说:

将 posX、posY 和 posZ 保存为 float32。将 eventID、parentID 和 clockTime 保存为 int32 或类似的内容。

注意:当我读入数据时,我需要以某种形式对数据进行分块以避免内存错误。

但是我无法得到想要的结果。到目前为止我已经尝试过: 按照本指南使用 Pandas 自己的方法:How to write a large csv file to hdf5 in python? 这会创建文件,但我无法更改类型并且文件仍然太大(~10.7Gb)。字段类型为 float64 和 int64。

在处理增量之前,我还尝试将 CSV 拆分为多个部分(使用 split -n x myfile.csv)。我在每个文件的开头和结尾都遇到了一些数据错误,我可以通过使用 sed 删除所述行来修复这些错误。然后我尝试了以下代码:

import pandas as pd
import h5py

PATH_csv = "/home/MYNAME/Documents/Workfolder/xaa" #xaa is my csv increment
DATA_csv = pd.read_csv(PATH_csv)

with h5py.File("pct_data-hdf5.h5", "a") as DATA_hdf:
    dset = DATA_hdf.create_dataset("posX", data=DATA_csv["posX"], dtype="float32")

遗憾的是,这创建了文件和表,但没有向其中写入任何数据。

期待 创建一个包含大型 CSV 文件数据的 HDF5 文件,同时更改每个索引的变量类型。

如果有不清楚的地方,请向我寻求说明。我还是个初学者!

【问题讨论】:

【参考方案1】:

您考虑过numpy 模块吗? 它有一个方便的功能 (genfromtxt) 可以将带有标题的 CSV 数据读取到 Numpy 数组中。您定义数据类型。该数组适合通过h5py.create_dataset()函数加载到HDF5中。

见下面的代码。我包括了 2 个打印语句。第一个显示从 CSV 标头创建的 dtype 名称。第二个展示了如何通过字段(列)名称访问 numpy 数组中的数据。

import h5py
import numpy as np

PATH_csv = 'SO_55576601.csv'
csv_dtype= ('f8', 'f8', 'f8', 'i4', 'i4', 'i4' )

csv_data = np.genfromtxt(PATH_csv, dtype=csv_dtype, delimiter=',', names=True)

print (csv_data.dtype.names)
print (csv_data['posX'])

with h5py.File('SO_55576601.h5', 'w') as h5f:
    dset = h5f.create_dataset('CSV_data', data=csv_data)

h5f.close()   

【讨论】:

抱歉回复晚了!我确实尝试使用 3.7gb 大 CSV 文件运行此代码,但遗憾的是由于某种原因内存不足(我的系统中有 16gb)。在使用了一个 ~800mb 的大 CSV 文件后,它确实按预期工作了,即使在我运行脚本时占用了 ~8gb 的 RAM 之后。 我的示例在 OP 中使用了您的小数据 sn-p。我没有对大型数据集进行任何内存测试。根据您的结果,您必须将 CSV 数据分成单独的文件(带有标题)。然后你可以在第一次读/写时create_dataset(),然后读取更多数据,调整数据集大小,写入更多数据。有关示例,请参阅这些 SO 帖子:incremental-writes-to-hdf5-with-h5py 和 how-to-append-data-to-one-specific-dataset-in-a-hdf5-file-with-h5py

以上是关于尝试通过使用 h5py 更改索引字段类型来缩小 HDF5 文件的大小的主要内容,如果未能解决你的问题,请参考以下文章

具有版本控制的 HDF5 文件 (h5py) - 每次保存时都会更改哈希

Elasticsearch 更改已有字段的数据类型,清洗数据

如果它是主键并且被索引,如何更改列的数据类型?

MySQL数据库索引

Sencha cmd 5缩小问题

MySQL索引和字段类型,字段长度