在我老死之前尝试用 dataframe.to_hdf 加载 hdf5 table

Trying to load an hdf5 table with dataframe.to_hdf before I die of old age

这听起来应该很容易用 Google 回答,但我发现用这种方式回答我的大部分重要 pandas/pytables 问题是不可能的。我要做的就是将大约 6000 个不同 CSV 文件中的大约 30 亿条记录加载到单个 HDF5 文件中的单个 table 中。这是一个简单的 table,26 个字段,混合了字符串、浮点数和整数。我正在使用 df = pandas.read_csv() 加载 CSV,并使用 df.to_hdf() 将它们附加到我的 hdf5 文件中。我真的不想使用 df.to_hdf(data_columns = True),因为它看起来需要大约 20 天,而 df.to_hdf(data_columns = False) 大约需要 4 天。但是显然,当您使用 df.to_hdf(data_columns = False) 时,您最终会得到一堆垃圾,您甚至无法从中恢复 table 结构(或者在我未受过教育的眼中看来是这样)。只有在 min_itemsize 列表(4 个字符串列)中标识的列在 hdf5 table 中是可识别的,其余的按数据类型转储到 values_block_0values_block_4:

table = h5file.get_node('/tbl_main/table')
print(table.colnames)
['index', 'values_block_0', 'values_block_1', 'values_block_2', 'values_block_3', 'values_block_4', 'str_col1', 'str_col2', 'str_col3', 'str_col4']

并且像 df = pd.DataFrame.from_records(table.read_where(condition)) 这样的任何查询都失败并出现错误 "Exception: Data must be 1-dimensional"

所以我的问题是:(1) 我真的必须使用需要 5 倍长的 data_columns = True 吗?我期望进行快速加载,然后在加载 table 后仅索引几列。 (2) 我用data_columns = False得到的这堆垃圾到底是什么?如果我需要我的 table 返回可查询的列,它有什么用吗?它有什么用吗?

这是使用 pytables 从 CSV 数据创建 HDF5 文件的方法。您也可以使用类似的过程通过 h5py 创建 HDF5 文件。

  1. 使用循环将 np.genfromtxt 的 CSV 文件读入 np 数组。
  2. 读取第一个CSV文件后,使用.create_table()方法写入数据,引用步骤1中创建的np数组。
  3. 对于其他 CSV 文件,使用 .append() 方法写入数据,引用在步骤 1
  4. 中创建的 np 数组

循环结束
更新于 6/2/2019 以读取日期字段 (mm/dd/YYY) 并转换为 datetime 对象。注意 genfromtxt() 参数的变化!使用的数据添加在更新后的代码下方。

import numpy as np   
import tables as tb
from datetime import datetime
csv_list = ['SO_56387241_1.csv', 'SO_56387241_2.csv' ]

my_dtype= np.dtype([ ('a',int),('b','S20'),('c',float),('d',float),('e','S20') ])

with tb.open_file('SO_56387241.h5', mode='w') as h5f:

for  PATH_csv in csv_list:
    csv_data = np.genfromtxt(PATH_csv, names=True, dtype=my_dtype, delimiter=',', encoding=None)
    # modify date in fifth field 'e'   
    for row in csv_data :
        datetime_object = datetime.strptime(row['my_date'].decode('UTF-8'), '%m/%d/%Y' )
        row['my_date'] = datetime_object

    if h5f.__contains__('/CSV_Data') :
        dset = h5f.root.CSV_Data
        dset.append(csv_data)

    else:
        dset = h5f.create_table('/','CSV_Data', obj=csv_data)

    dset.flush()

h5f.close()

测试数据:

SO_56387241_1.csv:
my_int,my_str,my_float,my_exp,my_date
0,zero,0.0,0.00E+00,01/01/1980
1,one,1.0,1.00E+00,02/01/1981
2,two,2.0,2.00E+00,03/01/1982
3,three,3.0,3.00E+00,04/01/1983
4,four,4.0,4.00E+00,05/01/1984
5,five,5.0,5.00E+00,06/01/1985
6,six,6.0,6.00E+00,07/01/1986
7,seven,7.0,7.00E+00,08/01/1987
8,eight,8.0,8.00E+00,09/01/1988
9,nine,9.0,9.00E+00,10/01/1989


SO_56387241_2.csv:
my_int,my_str,my_float,my_exp,my_date
10,ten,10.0,1.00E+01,01/01/1990
11,eleven,11.0,1.10E+01,02/01/1991
12,twelve,12.0,1.20E+01,03/01/1992
13,thirteen,13.0,1.30E+01,04/01/1993
14,fourteen,14.0,1.40E+01,04/01/1994
15,fifteen,15.0,1.50E+01,06/01/1995
16,sixteen,16.0,1.60E+01,07/01/1996
17,seventeen,17.0,1.70E+01,08/01/1997
18,eighteen,18.0,1.80E+01,09/01/1998
19,nineteen,19.0,1.90E+01,10/01/1999