尝试在 h5py 中打开由 pandas 创建的 hdf 时缺少列
Column missing when trying to open hdf created by pandas in h5py
这就是我的数据框的样子。第一列是一个整数。第二列是一个包含 512 个整数的列表。
IndexID Ids
1899317 [0, 47715, 1757, 9, 38994, 230, 12, 241, 12228...
22861131 [0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...
2163410 [0, 26039, 41156, 227, 860, 3320, 6673, 260, 1...
15760716 [0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
12244098 [0, 45651, 4128, 227, 5, 10397, 995, 731, 9, 3...
我将它保存到 hdf 并尝试使用
打开它
df.to_hdf('test.h5', key='df', data_columns=True)
h3 = h5py.File('test.h5')
当我列出键时,我看到了 4 个键
h3['df'].keys()
KeysViewHDF5 ['axis0', 'axis1', 'block0_items', 'block0_values']
Axis1 包含第一列的值
h3['df']['axis1'][0:5]
array([ 1899317, 22861131, 2163410, 15760716, 12244098,
但是,第二列似乎没有数据。确实有另一列包含其他数据
h3['df']['block0_values'][0][0:5]
但这似乎与第二列中的任何数据都不对应
array([128, 4, 149, 1, 0], dtype=uint8)
目的
我最终尝试创建一个内存映射的数据存储,它使用特定索引检索数据。
所以像
h3['df']['workingIndex'][22861131, 15760716]
会检索
[0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...],
[0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
问题是您正在尝试序列化 Pandas 系列的 Python 列表,但它不是矩形(呈锯齿状)。
Pandas 和 HDF5 主要用于矩形(立方体、超立方体等)数据,而不是锯齿状列表列表。
您在调用 to_hdf()
时是否看到此警告?
PerformanceWarning:
your performance may suffer as PyTables will pickle object types that it cannot
map directly to c-types [inferred_type->mixed,key->block0_values] [items->['Ids']]
它试图告诉您的是,不以直观、高性能的方式支持列表的列表。如果您在输出文件上 运行 一个像 h5dump
这样的 HDF5 可视化工具,您会发现问题所在。索引(表现良好)如下所示:
DATASET "axis1" {
DATATYPE H5T_STD_I64LE
DATASPACE SIMPLE { ( 5 ) / ( 5 ) }
DATA {
(0): 1899317, 22861131, 2163410, 15760716, 12244098
}
ATTRIBUTE "CLASS" {
DATA {
(0): "ARRAY"
}
}
但是值(列表的列表)看起来像这样:
DATASET "block0_values" {
DATATYPE H5T_VLEN { H5T_STD_U8LE}
DATASPACE SIMPLE { ( 1 ) / ( H5S_UNLIMITED ) }
DATA {
(0): (128, 5, 149, 164, ...)
}
ATTRIBUTE "CLASS" {
DATA {
(0): "VLARRAY"
}
}
ATTRIBUTE "PSEUDOATOM" {
DATA {
(0): "object"
}
}
发生的事情正是 PerformanceWarning 警告您的:
> PyTables will pickle object types that it cannot map directly to c-types
您的列表列表正在被 pickle 并存储为 H5T_VLEN,这只是一个字节块。
这里有一些方法可以解决这个问题:
- 将每一行存储在 HDF5 中的单独键下。也就是说,每个列表都将存储为一个数组,并且它们都可以有不同的长度。这对 HDF5 没有问题,因为它支持一个文件中的任意数量的密钥。
- 将您的数据更改为矩形,例如通过用零填充较短的列表。参见:
- 使用 h5py 以您喜欢的任何格式写入数据。它比 Pandas/PyTables 更灵活,创建更简单(但更强大)的 HDF5 文件。这是一个示例(它表明 h5py 实际上可以存储锯齿状数组,尽管它并不漂亮):
这就是我的数据框的样子。第一列是一个整数。第二列是一个包含 512 个整数的列表。
IndexID Ids
1899317 [0, 47715, 1757, 9, 38994, 230, 12, 241, 12228...
22861131 [0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...
2163410 [0, 26039, 41156, 227, 860, 3320, 6673, 260, 1...
15760716 [0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
12244098 [0, 45651, 4128, 227, 5, 10397, 995, 731, 9, 3...
我将它保存到 hdf 并尝试使用
打开它df.to_hdf('test.h5', key='df', data_columns=True)
h3 = h5py.File('test.h5')
当我列出键时,我看到了 4 个键
h3['df'].keys()
KeysViewHDF5 ['axis0', 'axis1', 'block0_items', 'block0_values']
Axis1 包含第一列的值
h3['df']['axis1'][0:5]
array([ 1899317, 22861131, 2163410, 15760716, 12244098,
但是,第二列似乎没有数据。确实有另一列包含其他数据
h3['df']['block0_values'][0][0:5]
但这似乎与第二列中的任何数据都不对应
array([128, 4, 149, 1, 0], dtype=uint8)
目的
我最终尝试创建一个内存映射的数据存储,它使用特定索引检索数据。
所以像
h3['df']['workingIndex'][22861131, 15760716]
会检索
[0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...],
[0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
问题是您正在尝试序列化 Pandas 系列的 Python 列表,但它不是矩形(呈锯齿状)。
Pandas 和 HDF5 主要用于矩形(立方体、超立方体等)数据,而不是锯齿状列表列表。
您在调用 to_hdf()
时是否看到此警告?
PerformanceWarning:
your performance may suffer as PyTables will pickle object types that it cannot
map directly to c-types [inferred_type->mixed,key->block0_values] [items->['Ids']]
它试图告诉您的是,不以直观、高性能的方式支持列表的列表。如果您在输出文件上 运行 一个像 h5dump
这样的 HDF5 可视化工具,您会发现问题所在。索引(表现良好)如下所示:
DATASET "axis1" {
DATATYPE H5T_STD_I64LE
DATASPACE SIMPLE { ( 5 ) / ( 5 ) }
DATA {
(0): 1899317, 22861131, 2163410, 15760716, 12244098
}
ATTRIBUTE "CLASS" {
DATA {
(0): "ARRAY"
}
}
但是值(列表的列表)看起来像这样:
DATASET "block0_values" {
DATATYPE H5T_VLEN { H5T_STD_U8LE}
DATASPACE SIMPLE { ( 1 ) / ( H5S_UNLIMITED ) }
DATA {
(0): (128, 5, 149, 164, ...)
}
ATTRIBUTE "CLASS" {
DATA {
(0): "VLARRAY"
}
}
ATTRIBUTE "PSEUDOATOM" {
DATA {
(0): "object"
}
}
发生的事情正是 PerformanceWarning 警告您的:
> PyTables will pickle object types that it cannot map directly to c-types
您的列表列表正在被 pickle 并存储为 H5T_VLEN,这只是一个字节块。
这里有一些方法可以解决这个问题:
- 将每一行存储在 HDF5 中的单独键下。也就是说,每个列表都将存储为一个数组,并且它们都可以有不同的长度。这对 HDF5 没有问题,因为它支持一个文件中的任意数量的密钥。
- 将您的数据更改为矩形,例如通过用零填充较短的列表。参见:
- 使用 h5py 以您喜欢的任何格式写入数据。它比 Pandas/PyTables 更灵活,创建更简单(但更强大)的 HDF5 文件。这是一个示例(它表明 h5py 实际上可以存储锯齿状数组,尽管它并不漂亮):