在熊猫中将可变长度列表保存到 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的主要内容,如果未能解决你的问题,请参考以下文章