2013-07-15 17 views
5

パンダでは、HDFStoreに存在するすべてのMultiIndexインデックスをテーブル形式で効率的に取り出す方法はありますか?MultiIndex DataFramesのPandas HDFStore:効率的にすべてのインデックスを取得する方法

私はwhere=を効率的に使用してselect()を使用できますが、すべてのインデックスとカラムは不要です。私もselect()iterator=Trueを使用してRAMを節約することができますが、それでもディスクからすべてのテーブルを読み込むことを意味するので、まだ遅いです。

私はstore.root..table。*で狩りをしていましたが、私はインデックス値のリストを得ることを望んでいました。正しい軌道にいるのですか?

プランBは、メインのものを追加するたびに空のDataFramesが追加された、より短いMultiIndex DataFrameを保持することになります。私はそれを取得し、主なものよりもずっと安く索引を得ることができます。しかし、哀れみを感じる。

答えて

5

ストア、それをテーブルとして

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]) 

ます

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) 

dfをマルチインデックスを作成します。インデックスレベルはdata_columnsとして作成されます。つまり、選択範囲で使用できます。 これは単一の列を選択することもできるシリーズ(として単一の列を選択するにはMI-フレーム

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

を選択する方法でありますインデックスは列として格納されます)。これはかなり速いでしょう。

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) 
+0

素晴らしい回答、ありがとうございます。私は直接答えがstore.rootを見ていることだと思う*。テーブルは無駄です。さらに検討すると、あなたの反応に刺激を受けて、選択肢にすべてのデータを考慮させる必要があります。どのインデックス値が同じスペースを取るかを示すメタデータを取得しようとしています。説明のために、私のマルチインデックスのすべての可能な組み合わせが満たされているわけではないので、マルチインデックスのレベルを取得するだけでは不十分です。ありがとうございました。 – Tony

+0

'' select_column(...)。unique() ''も便利です。実際には特定のレベルの値が得られますが、それが役に立つかどうかは分かりません。 – Jeff

+0

メソッドIただ提案しました – Jeff

1

さらに大きなテーブルで作業する人は、Jeffが提案した解決策を見つけ出し、メモリエラーに終わることがあります。はるかに洗練されたソリューションですが、私の場合は使用できませんでした(16GB RAMデスクトップの2e9行テーブル、datetimeインデックスの場合)。 IはCSI一つtimestamp指数(Float64)と、h5storeをテーブルとして保存HDFStoreオブジェクト、マルチ・インデックス付きデータフレームであり、(残念ながらエレガントではない)以下の溶液、で終わった:

%%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 
関連する問題