【问题标题】:Pandas to_hdf succeeds but then read_hdf failsPandas to_hdf 成功但 read_hdf 失败
【发布时间】:2023-03-14 15:14:01
【问题描述】:

Pandas to_hdf 成功,但是当我使用自定义对象作为列标题时 read_hdf 失败(我使用自定义对象是因为我需要在其中存储其他信息)。

有什么方法可以让这个工作吗?或者这只是 Pandas 错误或 PyTables 错误?

作为一个例子,下面,我将首先展示一个使用字符串列标题的 DataFrame foo,并且使用 to_hdf/read_hdf 一切正常,但随后将 foo 更改为使用自定义 Col 类对于列标题,to_hdf 仍然可以正常工作,但随后 read_hdf 引发断言错误:

In [48]: foo = pd.DataFrame(np.random.randn(2, 3), columns = ['aaa', 'bbb', 'ccc'])

In [49]: foo
Out[49]: 
    aaa       bbb       ccc
0 -0.434303  0.174689  1.373971
1 -0.562228  0.862092 -1.361979

In [50]: foo.to_hdf('foo.h5', 'foo')

In [51]: bar = pd.read_hdf('foo.h5', 'foo')

In [52]: bar
Out[52]: 
    aaa       bbb       ccc
0 -0.434303  0.174689  1.373971
1 -0.562228  0.862092 -1.361979

In [52]: 

In [53]: class Col(object):
...:     def __init__(self, name, other_info):
...:         self.name = name
...:         self.other_info = other_info
...:     def __str__(self):
...:         return self.name
...:     

In [54]: foo = pd.DataFrame(np.random.randn(2, 3), columns = [Col('aaa', {'z': 5}), Col('bbb', {'y': True}), Col('ccc', {})])

In [55]: foo
Out[55]: 
    aaa       bbb       ccc
0 -0.830503  1.066178  1.057349
1  0.406967 -0.131430  1.970204

In [56]: foo.to_hdf('foo.h5', 'foo')

In [57]: bar = pd.read_hdf('foo.h5', 'foo')
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-57-888b061a1d2c> in <module>()
----> 1 bar = pd.read_hdf('foo.h5', 'foo')

/.../python3.4/site-packages/pandas/io/pytables.py in read_hdf(path_or_buf, key, **kwargs)
330 
331     try:
--> 332         return store.select(key, auto_close=auto_close, **kwargs)
333     except:
334         # if there is an error, close the store

/.../python3.4/site-packages/pandas/io/pytables.py in select(self, key, where, start, stop, columns, iterator, chunksize, auto_close, **kwargs)
672                            auto_close=auto_close)
673 
--> 674         return it.get_result()
675 
676     def select_as_coordinates(

/.../python3.4/site-packages/pandas/io/pytables.py in get_result(self, coordinates)
   1366 
   1367         # directly return the result
-> 1368         results = self.func(self.start, self.stop, where)
   1369         self.close()
   1370         return results

/.../python3.4/site-packages/pandas/io/pytables.py in func(_start, _stop, _where)
665             return s.read(start=_start, stop=_stop,
666                           where=_where,
--> 667                           columns=columns, **kwargs)
668 
669         # create the iterator

/.../python3.4/site-packages/pandas/io/pytables.py in read(self, **kwargs)
   2792             blocks.append(blk)
   2793 
-> 2794         return self.obj_type(BlockManager(blocks, axes))
   2795 
   2796     def write(self, obj, **kwargs):

/.../python3.4/site-packages/pandas/core/internals.py in __init__(self, blocks, axes, do_integrity_check, fastpath)
   2180         self._consolidate_check()
   2181 
-> 2182         self._rebuild_blknos_and_blklocs()
   2183 
   2184     def make_empty(self, axes=None):

/.../python3.4/site-packages/pandas/core/internals.py in _rebuild_blknos_and_blklocs(self)
   2271 
   2272         if (new_blknos == -1).any():
-> 2273             raise AssertionError("Gaps in blk ref_locs")
   2274 
   2275         self._blknos = new_blknos

AssertionError: Gaps in blk ref_locs

更新

所以 Jeff 回答 (a)“不支持”和 (b)“如果您有元数据,则将其写入属性”。

关于 (a) 的问题 1: 我的列标题对象具有返回其属性等的方法。例如,我可以简单地执行 col_header.x (gives 5) col_header.y (给出 3) 等等。这是非常面向对象和 pythonic 的,而不是使用字符串来存储信息并且每次都必须解析它来检索信息。您如何建议我以一种很好的方式替换我当前的列标题对象(这也受支持)?

(顺便说一句,您可能会查看“x5y3z8”并认为分层索引有效,但事实并非如此,因为并非每个列标题都是“x#y#z#”。我可能有一列“foo”字符串, 另一个 'bar5baz7' 的整数和另一个 'x5y3z8' 的浮点数。列标题不统一。)

关于 (a) 的问题 2: 当您说它不支持时,您是在专门谈论 to_hdf/read_hdf 不支持它,还是您实际上是在说 Pandas 一般不支持它?如果只是缺少 HDF5 支持,那么我可以切换到其他方式将 DataFrames 保存到磁盘并让它工作,对吗?你预见到未来会有什么问题吗?例如,这会与 to_pickle/read_pickle 中断吗? (我失去了表现,但必须放弃一些东西,对吧?)

关于 (b) 的问题 3: “如果您有元数据,则将其写入属性”是什么意思。什么属性?一个简单的例子对我有很大帮助。我对熊猫很陌生。谢谢!

【问题讨论】:

    标签: python pandas hdf5 pytables hdf


    【解决方案1】:

    这不是受支持的功能。

    这将在下一版本的 pandas 中提出(关于写作),用于format='table'。也应该适用于fixed,但这没有实现。根本不支持,也不可能支持。你应该只使用字符串。如果您有元数据,则将其写入属性。

    【讨论】:

    • 添加了一些后续问题,如果您不介意回答的话。谢谢。
    • 阅读文档:pandas.pydata.org/pandas-docs/stable/io.html#hdf5-pytables 然后阅读 PyTables 本身。这与 Python 无关,而是磁盘上定义的格式。有很多选择,你必须找出最适合你的情况。
    • 当你说不支持的时候,你是在说 to_hdf/read_hdf 不支持,还是说 Pandas 一般不支持?如果只是缺少对 HDF5 的支持,那么我可以切换到类似 to_pickle/read_pickle 的东西。你预见到未来会有什么问题吗?将来会不会中断?
    • 理论上您可以像使用列标签一样使用对象。它甚至可以工作,但不受支持。序列化可能会也可能不会起作用。这是一件非常不标准的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    相关资源
    最近更新 更多