【问题标题】:Issues with adding a MultiIndex Pandas DataFrame to a PyTables HDFStore将 MultiIndex Pandas DataFrame 添加到 PyTables HDFStore 的问题
【发布时间】:2013-06-21 23:21:07
【问题描述】:

我在一个充满栅格的列表上使用 for 循环。在每个栅格中,我提取一个数据数组,并且我想使用栅格的基本名称(日期)作为该数组的索引。为此,我使用 Pandas DataFrame 多索引。然后将包含新集合索引的数组附加到 HDFStore。接下来选择另一个日期的栅格

代码sn-ps:

root, ext = os.path.splitext(raster)
name = int(decimal.Decimal(os.path.basename(root)))

array = ma.MaskedArray.compressed(raster)
arr2df = pd.DataFrame(pd.Series(data = array), columns=['rastervalue'])
arr2df['timestamp'] = pd.Series(name,index=arr2df.index)
arr2df.set_index('timestamp')
store.append('rastervalue',arr2df)

DataFrame 似乎没问题(顺便说一句,我怎样才能检索 MultiIndex?)。

>>> arr2df
<class 'pandas.core.frame.DataFrame'>
  MultiIndex: 123901 entries, (0, 20060101) to (123900, 20060101)
  Data columns (total 1 columns):
  rastervalue    123901  non-null values
  dtypes:        int32(1)

但是在我检查 HDFStore 的那一刻,我的 Multi-Index 似乎消失了并变成了“values_block_1”

>>> store.root.rastervalue.table.read
<bound method Table.read of /rastervalue/table (Table(12626172,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Int32Col(shape=(1,), dflt=0, pos=1),
  "values_block_1": Int64Col(shape=(1,), dflt=0, pos=2)}
  byteorder := 'little'
  chunkshape := (3276,)
  autoIndex := True
  colindexes := {
    "index": Index(6, medium, shuffle, zlib(1)).is_CSI=False}>

>>> store.root.rastervalue.table.read(field="values_block_1")
array([[20060101],
       [20060101],
       [20060101],
       ...,
       [ 20060914],
       [ 20060914],
       [ 20060914]], dtype=int64)

通过阅读documentation,我无法弄清楚如何正确存储或更改 HDFStore 中的 MultiIndex。有什么建议?最终我想查询表为:

 store.select('rastervalue', [ pd.Term('index', '=', '20060101')])

【问题讨论】:

  • 您对 MaskArray 的使用可能会对索引产生有趣的影响,您能否提供一个可重现的示例和/或显示您尝试存储的某些帧(df.head(10) ) 还是什么...?
  • 我刚刚注意到您的set_index 没有分配给任何东西;这不是就地操作(除非你通过inplace=True

标签: python dataframe pandas pytables hdfstore


【解决方案1】:

这是一个工作示例。

In [43]: df = DataFrame(dict(ivalue = range(123901), date = 20060101, 
              value = Series([1]*123901,dtype='int32'))).set_index(['ivalue','date'])

In [44]: df
Out[44]: 
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 123901 entries, (0, 20060101) to (123900, 20060101)
Data columns (total 1 columns):
value    123901  non-null values
dtypes: int32(1)

In [45]: df.head()
Out[45]: 
                 value
ivalue date           
0      20060101      1
1      20060101      1
2      20060101      1
3      20060101      1
4      20060101      1

In [46]: store = pd.HDFStore('test.h5',mode='w')

In [48]: store.append('df',df)

In [49]: store
Out[49]: 
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df            frame_table  (typ->appendable_multi,nrows->123901,ncols->3,indexers->[index],dc->[date,ivalue])

In [50]: store.get_storer('df')
Out[50]: frame_table  (typ->appendable_multi,nrows->123901,ncols->3,indexers->[index],dc->[date,ivalue])
In [51]: store.get_storer('df').attrs
Out[51]: 
/df._v_attrs (AttributeSet), 14 attributes:
   [CLASS := 'GROUP',
    TITLE := '',
    VERSION := '1.0',
    data_columns := ['date', 'ivalue'],
    encoding := None,
    index_cols := [(0, 'index')],
    info := {'index': {}},
    levels := ['ivalue', 'date'],
    nan_rep := 'nan',
    non_index_axes := [(1, ['ivalue', 'date', 'value'])],
    pandas_type := u'frame_table',
    pandas_version := '0.10.1',
    table_type := u'appendable_multiframe',
    values_cols := ['values_block_0', 'date', 'ivalue']]

In [52]: store.get_storer('df').table
Out[52]: 
/df/table (Table(123901,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Int32Col(shape=(1,), dflt=0, pos=1),
  "date": Int64Col(shape=(), dflt=0, pos=2),
  "ivalue": Int64Col(shape=(), dflt=0, pos=3)}
  byteorder := 'little'
  chunkshape := (2340,)
  autoIndex := True
  colindexes := {
    "date": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "index": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "ivalue": Index(6, medium, shuffle, zlib(1)).is_CSI=False}

【讨论】:

  • 我明白了,在 DataFrame 上设置多索引时已经犯了我的错误。那么 HDFStore 不喜欢输入是有道理的。感谢您解释与就地操作相关的 set_index。我没有意识到需要它。顺便说一句,现在我也不需要它,因为你的工作示例就像一个魅力。我希望有一天能够像你一样回答关于 SO 的问题:)。坚持下去。
  • np 很高兴它成功了。您可能会发现这本食谱很有用:pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore
  • is_CSI=False是什么意思?
  • 好的,完全排序的索引。那么,这是否意味着索引速度比它可能的慢,因为它被设置为 False?
  • 阅读本节:pytables.github.io/usersguide/optimization.html;很少需要创建 CSI,而且这样做非常耗时(更糟糕的是,它只能针对 1 个索引完成)。但如果你想尝试(并且有很多时间),它可能会有所回报。
猜你喜欢
  • 2013-10-06
  • 1970-01-01
  • 2021-06-16
  • 2016-12-30
  • 2012-10-07
  • 2019-02-16
  • 2022-07-20
  • 2016-09-18
相关资源
最近更新 更多