【问题标题】:HDF + pandas: how can I use a where mask with multindex?HDF + pandas:如何使用带有多索引的 where 掩码?
【发布时间】:2015-09-30 05:07:57
【问题描述】:

我想每天从 HUGE hdf5 中选择一个数据子集。使用where mask 将是完美的,但我不能使它与多索引一起使用(因为我必须有两个条件的位置)。不能使用带有多索引的 where 掩码:

import itertools
import pandas as pd
import numpy as np
a = ('A', 'B')
i = (0, 1, 2)
idx = pd.MultiIndex.from_tuples(list(itertools.product(a, i)),
                            names=('Alpha', 'Int'))
df = pd.DataFrame(np.random.randn(len(idx), 7), index=idx,
              columns=('I', 'II', 'III', 'IV', 'V', 'VI', 'VII'))

好的,现在我把它放在 hdf 商店里

from pandas.io.pytables import HDFStore
store =HDFStore('cancella.h5', 'w')
store.append('df_mask',df)

但如果我再读一遍,我有

c = store.select_column('df_mask','index')
print c

这个索引是错误的。

0    0
1    1
2    2
3    3
4    4
5    5
dtype: int64

所以我不能使用where mask。你能帮帮我吗?

【问题讨论】:

    标签: python pandas hdf5 pyhdf


    【解决方案1】:

    我猜这是因为 pandas 在将表放入 HDF5 之前可能会 reset_index(原因可能是它试图避免任何潜在的重复索引,这在数据帧中是允许的,但对数据库非常不利),并使用整数自动递增的主键作为HDF5 表中的索引。所以你在帖子中写的代码选择了这些自动递增的主键。

    可能还有其他一些更优雅的方法,但我发现了以下工作。 (如果 pandas 确实是 reset_index 的结果,那么现在多级索引变成列...)

    import itertools
    import pandas as pd
    import numpy as np
    a = ('A', 'B')
    i = (0, 1, 2)
    idx = pd.MultiIndex.from_tuples(list(itertools.product(a, i)),
                                names=('Alpha', 'Int'))
    df = pd.DataFrame(np.random.randn(len(idx), 7), index=idx,
                  columns=('I', 'II', 'III', 'IV', 'V', 'VI', 'VII'))
    print(df)
    
    store = pd.HDFStore('/home/Jian/Downloads/temp.h5')
    store.append('df_mask',df)
    
    store.select('df_mask', columns=['Alpha','Int'])
    

    【讨论】:

    • 我必须使用 where 掩码,所以我不能像最后一行那样只选择两列。此外,pandas 不会 reset_index,因为当我使用 read_hdf 读取 DataFrame 时,它​​是正确的。
    【解决方案2】:

    您是否尝试过使用 Pandas to_hdf(在安装 pytables 之后)?

    df.to_hdf('/Users/Alexander/Downloads/hdf.h5', key='data', format='t')
    
    >>> pd.read_hdf('/Users/Alexander/Downloads/hdf.h5', 'data', columns='index')
    Empty DataFrame
    Columns: []
    Index: [(A, 0), (A, 1), (A, 2), (B, 0), (B, 1), (B, 2)]
    

    选择 format='t' 选项:

    “写为 PyTables 表结构,可能性能更差,但允许 更灵活的操作,例如搜索/选择 数据”

    本文档提供了使用 where 掩码选择数据的详细信息。

    【讨论】:

    • 没用。 to_hdf 只是一个包装器 :)
    【解决方案3】:

    这可能与您的问题正交,但我没有在您的 DataFrame 中看到名为“索引”的列或索引,所以我不知道您实际选择的是什么

    c = store.select_column('df_mask','index')
    

    我一直使用read_hdf 包装器来处理 PyTables,并且发现它非常灵活。它的语法非常灵活,例如

    c = pd.read_hdf('/home/Jian/Downloads/temp.h5', 'df_mask', where="Alpha='A' | Alpha='B' & Int=0")
    

    您的 where 子句中的条件数量有严格限制,但如果我正确阅读了您的问题,那对您来说将是次要问题。

    【讨论】:

      【解决方案4】:

      在当前的 pandas 0.24.2 版本中,您可以使用直接查询而无需中间的 MultiIndex 检索:

      idx = pd.MultiIndex.from_product([('A', 'B'), range(3)], names=('Alpha', 'Int'))
      df = pd.DataFrame(np.random.randn(len(idx), 3), index=idx,
                        columns=('I', 'II', 'III'))
      df
      
      >>>                    I           II         III
      >>> Alpha   Int             
      >>>     A   0    0.547846   -1.630704    0.456686
      >>>         1   -0.057442   -0.232721    0.349548
      >>>         2    1.495230    0.661166    1.309862
      >>>     B   0    2.116818    0.477923   -0.252352
      >>>         1    1.001081    2.578723   -0.040782
      >>>         2   -1.286964    0.357969    0.002976
      

      只需使用内置的where 掩码:

      with pd.HDFStore('test.h5') as store:
          store.put('df_mask', df, format='t')
          store.select('df_mask', where = 'Alpha = A & Int in [0,2]')
      
      >>>                         I          II        III
      >>> Alpha   Int             
      >>>     A     0      0.621453   -1.757883   0.494433
      >>>           2     -0.689012   -1.254884   0.655424
      

      对于 where 掩码中允许的不同功能,请访问docs

      但是,如果您想要的过滤器非常复杂,并且您想检索 MultiIndex 并“手动”构建掩码,您可以选择它,例如 so:

      with pd.HDFStore('test.h5') as store:
          store.select('df_mask', columns=['index'])
      
      >>> Alpha   Int
      >>>     A     0
      >>>           1
      >>>           2
      >>>     B     0
      >>>           1
      >>>           2
      

      【讨论】:

        猜你喜欢
        • 2021-06-30
        • 2018-05-11
        • 2020-02-16
        • 2013-07-07
        • 1970-01-01
        • 2019-01-29
        • 1970-01-01
        • 1970-01-01
        • 2020-05-12
        相关资源
        最近更新 更多