在熊猫中将可变长度列表保存到 HDF5

Posted

技术标签:

【中文标题】在熊猫中将可变长度列表保存到 HDF5【英文标题】:Saving lists of variable length to HDF5 in pandas 【发布时间】:2016-08-04 14:45:50 【问题描述】:

我对 pandas 很陌生,所以如果我的问题很琐碎,请道歉。

我想将 pandas 数据框保存到 hdf5,其中包含可变长度列表的列表作为列。我的目标是稍后在这个数据框中以块的形式写入和读取。这似乎只有在我以表格格式存储数据框时才有可能。 但是,如果我以表格格式保存我的数据框,我会收到以下错误:

TypeError: Cannot serialize the column [pdf] because its data contents are [mixed] object dtype

在下面我展示了一个重现问题的最小示例:

import pandas as pd
import numpy as np
df = pd.DataFrame()
df['ID'] = [el for el in np.arange(100)]
df['pdf'] = [np.arange(i) for i in df['ID']]
df.to_hdf('test_format_table.h5','df', format='table')

如果我使用 format = 'fixed' 保存数据框,一切都会正常工作,但是我想以表格格式保存。

是否可以轻松解决此问题?

非常感谢您的帮助。

马库斯

【问题讨论】:

【参考方案1】:

你正在以一种奇怪的方式解决这个问题。当您拥有整洁的数据时,Pandas 和 HDF5 可以很好地工作。

In [32]: df
Out[32]: 
   ID                          pdf
0   0                           []
1   1                          [0]
2   2                       [0, 1]
3   3                    [0, 1, 2]
4   4                 [0, 1, 2, 3]
5   5              [0, 1, 2, 3, 4]
6   6           [0, 1, 2, 3, 4, 5]
7   7        [0, 1, 2, 3, 4, 5, 6]
8   8     [0, 1, 2, 3, 4, 5, 6, 7]
9   9  [0, 1, 2, 3, 4, 5, 6, 7, 8]

将列表分解为列

In [33]: df2 = pd.concat([df.ID, df.pdf.apply(Series)], axis=1)

In [34]: df2
Out[34]: 
   ID    0    1    2    3    4    5    6    7    8
0   0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
1   1  0.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
2   2  0.0  1.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN
3   3  0.0  1.0  2.0  NaN  NaN  NaN  NaN  NaN  NaN
4   4  0.0  1.0  2.0  3.0  NaN  NaN  NaN  NaN  NaN
5   5  0.0  1.0  2.0  3.0  4.0  NaN  NaN  NaN  NaN
6   6  0.0  1.0  2.0  3.0  4.0  5.0  NaN  NaN  NaN
7   7  0.0  1.0  2.0  3.0  4.0  5.0  6.0  NaN  NaN
8   8  0.0  1.0  2.0  3.0  4.0  5.0  6.0  7.0  NaN
9   9  0.0  1.0  2.0  3.0  4.0  5.0  6.0  7.0  8.0

重命名以使名称清晰

In [35]: df2.columns = ['ID'] + [ 'C%s' % c for c in df2.columns[1:] ]

In [36]: df2
Out[36]: 
   ID   C0   C1   C2   C3   C4   C5   C6   C7   C8
0   0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
1   1  0.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
2   2  0.0  1.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN
3   3  0.0  1.0  2.0  NaN  NaN  NaN  NaN  NaN  NaN
4   4  0.0  1.0  2.0  3.0  NaN  NaN  NaN  NaN  NaN
5   5  0.0  1.0  2.0  3.0  4.0  NaN  NaN  NaN  NaN
6   6  0.0  1.0  2.0  3.0  4.0  5.0  NaN  NaN  NaN
7   7  0.0  1.0  2.0  3.0  4.0  5.0  6.0  NaN  NaN
8   8  0.0  1.0  2.0  3.0  4.0  5.0  6.0  7.0  NaN
9   9  0.0  1.0  2.0  3.0  4.0  5.0  6.0  7.0  8.0

将列变成行

In [47]: df2.stack().reset_index()
Out[47]: 
    level_0 level_1    0
0         0      ID  0.0
1         1      ID  1.0
2         1      C0  0.0
3         2      ID  2.0
4         2      C0  0.0
..      ...     ...  ...
50        9      C4  4.0
51        9      C5  5.0
52        9      C6  6.0
53        9      C7  7.0
54        9      C8  8.0

[55 rows x 3 columns]

In [48]: df2 = df2.stack().reset_index()

重命名

In [49]: df2.columns = ['A', 'B', 'C']

In [50]: df2
Out[50]: 
    A   B    C
0   0  ID  0.0
1   1  ID  1.0
2   1  C0  0.0
3   2  ID  2.0
4   2  C0  0.0
.. ..  ..  ...
50  9  C4  4.0
51  9  C5  5.0
52  9  C6  6.0
53  9  C7  7.0
54  9  C8  8.0

[55 rows x 3 columns]

这是整齐的数据,IOW 已标准化且易于使用。

In [51]: df2.to_hdf('test.h5','df',format='table')

【讨论】:

非常感谢您的回答。你是完全正确的:我以一种奇怪的方式解决了这个问题。我这样做的原因是存储空间,这就是我不做任何填充的原因。我尝试了您的解决方案,它生成了一个大小为 1.46 Gb 的文件,而我的“解决方案”只需要 401.5 MB。我在这个例子中使用 df['ID'] = [el for el in np.arange(10000)]。由于这对于我的目的来说太大了,我真的想避免填充。知道如何做到这一点吗?

以上是关于在熊猫中将可变长度列表保存到 HDF5的主要内容,如果未能解决你的问题,请参考以下文章

从 Python 将字符串列表存储到 HDF5 数据集

如何在python中将文本字符串列表转换为熊猫数据框?

如何在循环中将不同大小的列表附加到空熊猫数据框的每一列?

如何使用列表重命名熊猫中的列

你如何在熊猫中将多行连接成一行?

如何使用可变长度类型将包含多个 std::vector<float> 的结构写出到 HDF5?