それが価値があるために、私は次のことをしました:
foo = pd.DataFrame(np.random.rand(12,3),
index=pd.MultiIndex.from_product([['A','B','C','D'],['Green','Red','Blue']],
names=['Letter','Color']),
columns=['X','Y','Z']).sort_index()
foo.reset_index()\
.loc[foo.reset_index().Color.isin({'Green','Red'})]\
.set_index(foo.index.names)
このアプローチは select に似ていますが、ラムダを使用してすべての行を反復することを回避します。
ただし、これをパネル アプローチと比較したところ、パネル ソリューションの方が高速であるように見えます (index/loc で 2.91 ミリ秒、to_panel/to_frame で 1.48 ミリ秒)。
foo.to_panel()[:,:,['Green','Red']].to_frame()
時間:
In [56]:
%%timeit
foo.reset_index().loc[foo.reset_index().Color.isin({'Green','Red'})].set_index(foo.index.names)
100 loops, best of 3: 2.91 ms per loop
In [57]:
%%timeit
foo2 = foo.reset_index()
foo2.loc[foo2.Color.eq('Green') | foo2.Color.eq('Red')].set_index(foo.index.names)
100 loops, best of 3: 2.85 ms per loop
In [58]:
%%timeit
foo2 = foo.reset_index()
foo2.loc[foo2.Color.ne('Blue')].set_index(foo.index.names)
100 loops, best of 3: 2.37 ms per loop
In [54]:
%%timeit
foo.to_panel()[:,:,['Green','Red']].to_frame()
1000 loops, best of 3: 1.18 ms per loop
アップデート
このトピックを (再び) 再検討した後、次のことに気付きました。
In [100]:
%%timeit
foo2 = pd.DataFrame({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}).transpose()
foo2.index.names = foo.index.names
foo2.columns.names = foo2.columns.names
100 loops, best of 3: 1.97 ms per loop
In [101]:
%%timeit
foo2 = pd.DataFrame.from_dict({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}, orient='index')
foo2.index.names = foo.index.names
foo2.columns.names = foo2.columns.names
100 loops, best of 3: 1.82 ms per loop
レベルの元の順序と名前を維持することを気にしない場合は、次を使用できます。
%%timeit
pd.concat({key: foo.xs(key, axis=0, level=1) for key in ['Green','Red']}, axis=0)
1000 loops, best of 3: 1.31 ms per loop
そして、最初のレベルで選択するだけの場合:
%%timeit
pd.concat({key: foo.loc[key] for key in ['A','B']}, axis=0, names=foo.index.names)
1000 loops, best of 3: 1.12 ms per loop
対:
%%timeit
foo.to_panel()[:,['A','B'],:].to_frame()
1000 loops, best of 3: 1.16 ms per loop
別のアップデート
例のインデックスを並べ替えると、foo
上記の時間の多くが改善されます (時間は事前に並べ替えられたインデックスを反映するように更新されています)。ただし、インデックスがソートされている場合は、user674155 によって説明されているソリューションを使用できます。
%%timeit
foo.loc[(slice(None), ['Blue','Red']),:]
1000 loops, best of 3: 582 µs per loop
私の意見では、これが最も効率的で直感的です (ユーザーは、パネルと、パネルがフレームからどのように作成されるかを理解する必要はありません)。
注: インデックスがまだソートされていない場合でもfoo
、オンザフライでのインデックスのソートは、to_panel
オプションのパフォーマンスに匹敵します。