【问题标题】:Saving lists of variable length to HDF5 in pandas在熊猫中将可变长度列表保存到 HDF5
【发布时间】: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' 保存数据框,一切都会正常工作,但是我想以表格格式保存。

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

非常感谢您的帮助。

马库斯

【问题讨论】:

    标签: python pandas large-files large-data


    【解决方案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)]。由于这对于我的目的来说太大了,我真的想避免填充。知道如何做到这一点吗?
    猜你喜欢
    • 2020-10-09
    • 2020-04-13
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 2019-12-07
    • 2016-08-25
    • 2022-11-04
    相关资源
    最近更新 更多