【问题标题】:Convert large csv to hdf5将大 csv 转换为 hdf5
【发布时间】:2015-01-27 23:15:29
【问题描述】:

我有一个 100M 行的 csv 文件(实际上是许多单独的 csv 文件),总计 84GB。我需要将其转换为具有单个浮点数据集的 HDF5 文件。我在测试中使用 h5py 没有任何问题,但现在我无法在内存不足的情况下做最终数据集。

如何写入 HDF5 而无需将整个数据集存储在内存中?我希望这里有实际的代码,因为它应该很简单。

我只是在研究 pytables,但它看起来不像可以迭代写入数组类(对应于 HDF5 数据集)。同样,pandas 在其io_tools 中有read_csvto_hdf 方法,但我无法一次加载整个数据集,因此无法正常工作。或许你可以用 pytables 或 pandas 中的其他工具帮助我正确解决问题。

【问题讨论】:

    标签: python csv pandas hdf5 pytables


    【解决方案1】:

    Use append=True 在对to_hdf 的调用中:

    import numpy as np
    import pandas as pd
    
    filename = '/tmp/test.h5'
    
    df = pd.DataFrame(np.arange(10).reshape((5,2)), columns=['A', 'B'])
    print(df)
    #    A  B
    # 0  0  1
    # 1  2  3
    # 2  4  5
    # 3  6  7
    # 4  8  9
    
    # Save to HDF5
    df.to_hdf(filename, 'data', mode='w', format='table')
    del df    # allow df to be garbage collected
    
    # Append more data
    df2 = pd.DataFrame(np.arange(10).reshape((5,2))*10, columns=['A', 'B'])
    df2.to_hdf(filename, 'data', append=True)
    
    print(pd.read_hdf(filename, 'data'))
    

    产量

        A   B
    0   0   1
    1   2   3
    2   4   5
    3   6   7
    4   8   9
    0   0  10
    1  20  30
    2  40  50
    3  60  70
    4  80  90
    

    请注意,您需要在第一次调用df.to_hdf 时使用format='table' 以使表格可附加。否则,格式默认为'fixed',读写速度更快,但创建的表格无法追加。

    因此,您可以一次处理每个 CSV,使用 append=True 构建 hdf5 文件。然后覆盖 DataFrame 或使用 del df 让旧的 DataFrame 被垃圾回收。


    或者,您可以append to a HDFStore,而不是调用df.to_hdf

    import numpy as np
    import pandas as pd
    
    filename = '/tmp/test.h5'
    store = pd.HDFStore(filename)
    
    for i in range(2):
        df = pd.DataFrame(np.arange(10).reshape((5,2)) * 10**i, columns=['A', 'B'])
        store.append('data', df)
    
    store.close()
    
    store = pd.HDFStore(filename)
    data = store['data']
    print(data)
    store.close()
    

    产量

        A   B
    0   0   1
    1   2   3
    2   4   5
    3   6   7
    4   8   9
    0   0  10
    1  20  30
    2  40  50
    3  60  70
    4  80  90
    

    【讨论】:

      【解决方案2】:

      这应该可以通过 PyTables 实现。不过,您需要使用 EArray 类。

      例如,以下是我编写的脚本,用于将存储为 .npy 文件的分块训练数据导入单个 .h5 文件。

      import numpy
      import tables
      import os
      
      training_data = tables.open_file('nn_training.h5', mode='w')
      a = tables.Float64Atom()
      bl_filter = tables.Filters(5, 'blosc')   # fast compressor at a moderate setting
      
      training_input =  training_data.create_earray(training_data.root, 'X', a,
                                                   (0, 1323), 'Training Input',
                                                   bl_filter, 4000000)
      training_output = training_data.create_earray(training_data.root, 'Y', a,
                                                   (0, 27), 'Training Output',
                                                   bl_filter, 4000000)
      
      for filename in os.listdir('input'):
          print "loading {}...".format(filename)
          a = numpy.load(os.path.join('input', filename))
          print "writing to h5"
          training_input.append(a)
      
      for filename in os.listdir('output'):
          print "loading {}...".format(filename)
          training_output.append(numpy.load(os.path.join('output', filename)))
      

      查看文档以获取详细说明,但非常简单,create_earray 函数需要 1) 数据根或父节点; 2) 数组名; 3) 数据类型原子; 4)要扩展的维度中带有0的形状; 5) 一个详细的描述符; 6) 一个compression filter; 7) 沿可扩展维度的预期行数。只有前两个是必需的,但您可能会在实践中使用所有七个。该函数还接受一些其他可选参数;再次,请参阅文档了解详细信息。

      创建数组后,您可以按预期方式使用其append 方法。

      【讨论】:

        猜你喜欢
        • 2022-12-04
        • 2016-12-13
        • 2014-07-08
        • 2020-03-16
        • 2020-01-30
        • 2014-06-13
        • 2018-11-19
        • 2019-11-28
        • 2014-03-07
        相关资源
        最近更新 更多