7

在 Pandas 中,有没有办法以表格格式有效地提取 HDFStore 中存在的所有 MultiIndex 索引?

我可以select()有效地使用where=,但我想要所有索引,而不想要任何列。我也可以select()用来iterator=True节省内存,但这仍然意味着从磁盘读取几乎所有的表,所以它仍然很慢。

我一直在寻找 store.root..table.* 的东西,希望我能得到一个索引值列表。我在正确的轨道上吗?

计划 B 是保留一个较短的 MultiIndex 数据帧,每次我附加主要数据帧时,它只包含附加的空数据帧。我可以检索它并获得比主要索引便宜得多的索引。虽然不优雅。

4

2 回答 2

9

创建多索引df

In [35]: df = DataFrame(randn(100000,3),columns=list('ABC'))

In [36]: df['one'] = 'foo'

In [37]: df['two'] = 'bar'

In [38]: df.ix[50000:,'two'] = 'bah'

In [40]: mi = df.set_index(['one','two'])

In [41]: mi
Out[41]: 
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 100000 entries, (foo, bar) to (foo, bah)
Data columns (total 3 columns):
A    100000  non-null values
B    100000  non-null values
C    100000  non-null values
dtypes: float64(3)

将其存储为表格

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

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

get_storer将返回存储的对象(但不检索数据)

In [44]: store.get_storer('df').levels
Out[44]: ['one', 'two']

In [2]: store
Out[2]: 
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df            frame_table  (typ->appendable_multi,nrows->100000,ncols->5,indexers->[index],dc->[two,one])

索引级别创建为 data_columns,这意味着您可以在选择中使用它们 这是仅选择索引的方法

In [48]: store.select('df',columns=['one'])
Out[48]: 
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 100000 entries, (foo, bar) to (foo, bah)
Empty DataFrame

选择单个列并将其作为 mi-frame 返回

In [49]: store.select('df',columns=['A'])
Out[49]: 
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 100000 entries, (foo, bar) to (foo, bah)
Data columns (total 1 columns):
A    100000  non-null values
dtypes: float64(1)

选择单个列作为系列(也可以是索引,因为它们存储为列)。这将是相当快的。

In [2]: store.select_column('df','one')
Out[2]: 
0     foo
1     foo
2     foo
3     foo
4     foo
5     foo
6     foo
7     foo
8     foo
9     foo
10    foo
11    foo
12    foo
13    foo
14    foo
...
99985    foo
99986    foo
99987    foo
99988    foo
99989    foo
99990    foo
99991    foo
99992    foo
99993    foo
99994    foo
99995    foo
99996    foo
99997    foo
99998    foo
99999    foo
Length: 100000, dtype: object

如果你真的想要最快的选择只有索引

In [4]: %timeit store.select_column('df','one')
100 loops, best of 3: 8.71 ms per loop

In [5]: %timeit store.select('df',columns=['one'])
10 loops, best of 3: 43 ms per loop

或者得到一个完整的索引

In [6]: def f():
   ...:     level_1 =  store.select_column('df','one')
   ...:     level_2 =  store.select_column('df','two')
   ...:     return MultiIndex.from_arrays([ level_1, level_2 ])
   ...: 

In [17]: %timeit f()
10 loops, best of 3: 28.1 ms per loop

如果您想要每个级别的值,这是一种非常快速的方法

In [2]: store.select_column('df','one').unique()
Out[2]: array(['foo'], dtype=object)

In [3]: store.select_column('df','two').unique()
Out[3]: array(['bar', 'bah'], dtype=object)
于 2013-07-15T12:50:09.557 回答
1

那些使用更大表的人可能会找到 Jeff 建议的解决方案,最终导致内存错误。这是一个更优雅的解决方案,但我无法在我的情况下使用(对于 2e9 行表,日期时间索引,在 16GB RAM 桌面上)。我最终得到了以下(不幸的是不优雅)的解决方案,对象在哪里h5storeHDFStore一个多索引的 DataFrame,保存为一个表,timestamp索引(Float64)是CSI一个:

%%time
#ts = h5store.select_column(h5store.keys()[0], column='timestamp').unique()

chunkshape = int(1e7) # can vary due to machine and hdf5

## get a list of chunks unique timestamps
ts = [indx.index.get_level_values('timestamp').unique() 
          for indx in h5full.select(h5full.keys()[0], columns=['timestamp'],
                                    stop=None, # change for a smaller selection
                                    chunksize=chunkshape)
      ]
## drop duplicates at the the end-points
for i in range(len(ts)-1):
    if ts[i][-1]==ts[i+1][0]:
         ts[i] = ts[i][:-1]
## merge to single ndarray
ts = np.concatenate(ts)

这次运行的时间(超过 2e9 行):

CPU times: user 14min 16s, sys: 2min 34s, total: 16min 50s
Wall time: 14min 45s
于 2014-01-05T22:40:07.710 回答