【问题标题】:Save Pandas data frame from list of dicts as hdf5 table将字典列表中的 Pandas 数据框保存为 hdf5 表
【发布时间】:2016-09-29 21:12:56
【问题描述】:

我有一个大型 pandas 数据框,它是从字典列表创建的,其中列名是字典键。这些列包含不同类型的数据,但任何给定列中的数据类型都是一致的。

示例:我的一列包含 28x28 numpy 数组,另一列包含字符串……等等。我想将其保存为 HDF5 文件,具有表格格式,以便以后读取数据时可以查询数据(这些文件约为 1-2 GB)。

这就是我尝试保存 hdf5 文件的方式:

df = pd.DataFrame(list_of_dicts)

df.convert_objects(convert_numeric=True) (**have also tried pd.to_numeric)**

df.to_hdf(path_to_save, 'df', format='table')

我收到以下错误:

TypeError:无法序列化列 [image_dims],因为 它的数据内容是 [mixed] object dtype

在这种情况下,image_dims 列的每个条目都有一个 numpy 数组,这发生在 pandas 中具有对象数据类型的任何列上,我不知道如何更改/设置它。我可以将其保存为固定格式,但我真的很想使用表格来节省加载时间等,查询。我看到了一些与此类似的其他问题,但与从字典列表创建数据框无关,这可能会导致问题?

感谢您的任何建议

【问题讨论】:

    标签: database pandas dataframe pytables zodb


    【解决方案1】:

    您更改了内存中的 DF - df.convert_objects(convert_numeric=True) - 将返回转换后的 DF 的副本,但不会更改原始 DF。改为这样做:

    df.apply(pd.to_numeric, errors='coerce').to_hdf(path_to_save, 'df', format='table')
    

    df = df.apply(pd.to_numeric)
    df['image_dims'] = df['image_dims'].astype(str) # in case it can't be converted to numeric
    df.to_hdf(path_to_save, 'df', format='table')
    

    PS 你可能想在调用pd.to_numeric(...) 函数时使用errors='coerce'errors='ignore' 参数,这取决于你想要什么

    【讨论】:

    • 感谢您的回复,我认为第一个解决方案会起作用,除了我收到此错误:类型错误 arg 必须是列表、元组、一维数组或系列。它适用于单个系列,但我需要它适用于整个数据框。你的意思是在单独的行上调用转换对象会导致内存变化吗?因为它没有就地转换列而是复制了数据框?
    • @notarya, DataFrame.convert_objects() - 返回转换后的 DF,但不会更改原始 DF,因此您需要:df = df.convert_objects(convert_numeric=True)
    • 谢谢。我认为现在的问题是我的一些列有字符串条目,而一些是数字,所以现在我遇到了这个问题: ValueError: ('Unable to parse string', u'occurred at index axis_view') 我可能有手动转换列或遍历它们并以这种方式转换为数字类型。
    • @notarya,您可以尝试这样做:df.apply(pd.to_numeric, errors='coerce'),但是将字符串(不代表数字)转换为数字 dtype 没有多大意义。您还可以准备必须转换的列列表并将其用作过滤器
    • 是的,我试过了,但我得到了相同的混合对象 dtype 错误。如果我找不到比手动更改列更好的方法,我可能会尝试使用 sqlite 方法。
    【解决方案2】:

    在尝试了很多事情之后,我终于找到了一种保存混合数据类型对象的好方法,可以快速加载和查询。我想我会发布它以防其他人遇到问题:

    尝试并失败:Pandas 数据框保存为 hdf5 或 json 文件。当数据类型混合时,Hdf5 可以工作,但只能以固定格式(无查询能力)工作。 Json 适用于混合,但对于这种大小的文件加载速度并不快。尝试将所有 numpy 数组、列表等转换为字节字符串以进行保存:这比我正在处理的列数和不同数据类型更麻烦。

    解决方案:使用 ZODB (https://pypi.python.org/pypi/ZODB)。对象数据库非常容易实现,如果数据框是你的东西,很容易与 pandas 集成。

    from ZODB.FileStorage import FileStorage
    from ZODB.DB import DB
    import transaction
    storage = FileStorage('path_to_store.fs')
    db = DB(storage)
    connection = db.open()
    root = connection.root()
    # insert each column of the dataframe into the db
    for col in df.columns:
        root[col] = df[col]
    # commit changes to the db
    transaction.commit()
    # works like a dictionary with key:value pairs that correspond to column names
    print root.keys()
    
    # close db and connection
    db.close()
    connection.close()
    

    然后您可以使用相同的语法读取数据库,并通过根变量访问数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-19
      • 2018-05-18
      • 1970-01-01
      相关资源
      最近更新 更多