2017-10-07 10 views
4

私はこのようなマルチインデックスのデータフレームを持っている:マルチインデックスデータフレームのサブセットを新しいデータフレームに格納する方法は?

import pandas as pd 
import numpy as np 


df = pd.DataFrame({'ind1': list('aaaaaaaaabbbbbbbbb'), 
        'ind2': list('cccdddeeecccdddeee'), 
        'ind3': list(range(3))*6, 
        'val1': list(range(100, 118)), 
        'val2': list(range(70, 88))}) 

df_mult = df.set_index(['ind1', 'ind2', 'ind3']) 

       val1 val2 
ind1 ind2 ind3    
a c 0  100 70 
      1  101 71 
      2  102 72 
    d 0  103 73 
      1  104 74 
      2  105 75 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  109 79 
      1  110 80 
      2  111 81 
    d 0  112 82 
      1  113 83 
      2  114 84 
    e 0  115 85 
      1  116 86 
      2  117 87 

私は今、今、私ならば期待

   val1 val2 
ind1 ind2 ind3    
a c 0  100 70 
      1  101 71 
      2  102 72 
    d 0  103 73 
      1  104 74 
      2  105 75 

を与える.loc

このような
df_subs = df_mult.loc['a', ['c', 'd'], :] 

を使用して、それのサブセットを選択することができますdf_subsのサブセットを再度選択したいとします。

df_subs.loc['a', 'c', :] 

作品となります

 val1 val2 
ind3    
0  100 70 
1  101 71 
2  102 72 

しかし

df_subs.loc[:, 'c', :] 

が失敗し、エラー

KeyError: 'the label [c] is not in the [columns]'

なぜこれができないのを与えますか?

EDIT

もともと、私はこの記事に2つの質問を持っていました。私はそれを2つに分割しました。第2の質問はhereです。 IndexSliceを使用することにより

+0

https://pandas.pydata.org/pandas-docs/stable/advanced.html「スライス」や「IndexSlice」を使用しない理由 – Wen

+0

@Wen:確かに、より良いオプションがあるかもしれませんが、私はまだ好きです上記の試みが失敗する理由を理解する。試行が間違っている場合は、それを実行する正しい方法、つまり代替案を確認することは素晴らしいことです。 – Cleb

+0

@JohnE:それでは、すでに知っておいてよかったです。私は 'IndexSlice'をいつ使うべきか正確に把握する必要があります。 df_mult.loc [pd.IndexSlice ['a'、['c'、 'd']、:]、:]。index'はまだ 'a'と'レベル0のb。どんな考え? – Cleb

答えて

2

idx = pd.IndexSlice 
df_subs.loc[idx[:, 'c',:],:] 
Out[159]: 
       val1 val2 
ind1 ind2 ind3    
a c 0  100 70 
      1  101 71 
      2  102 72 

それとも、行または列

df_subs.loc(axis=0)[:, 'c', :] 
Out[196]: 
       val1 val2 
ind1 ind2 ind3    
a c 0  100 70 
      1  101 71 
      2  102 72 

上の特定のスライス.loc[:, 'c', :]が働くことができない理由をする必要があります:あなたはすべて指定する必要があり

.loc指定子の軸は、インデックスとカラムのインデクサを意味します。渡されたインデクサーは、行のMuliIndexではなく、両方の軸のインデックスとして誤解される可能性があるあいまいなケースがあります。明らか

Link1

Link2

+0

良い、作業の代替(upvoted)を知っている。しかし、なぜ '.loc'のバージョンが動作していないのか知っていますか? 'df_subs.loc [idx [:, 'c'、:]、:]。index'はレベル0にまだ' a'と 'b'を持っています。どんな考え? – Cleb

+0

@Cleb gitの議論です。あなたは〜を提供する2つのリンクを確認することができます〜:-)より安全にするには、スライスまたはIndexSliceを使用することができます:) – Wen

+0

面白い読んで、ありがとう。質問1について私の質問も編集しました。これに関するコメント? (今はこれが実際に関連しているかどうかはもう分かりませんので、私はそれを2つの質問に分けてください)。 – Cleb

1

、それらがリセットされるまで.locは元の形式のインデックスを保持することができる使用。 .copy()を使用して元のデータフレームのビューを回避すると、マルチインデックス値は引き続き維持されます。

df_subs = df_mult.loc['a', ['c', 'd'], :].copy() 

print(df_subs.index) 
# MultiIndex(levels=[['a', 'b'], ['c', 'd', 'e'], [0, 1, 2]], 
#   labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]], 
#   names=['ind1', 'ind2', 'ind3']) 

また、値によるフィルタリングはまだmultindex値を保持:

df_subs = df_mult[df_mult['val1'] <= 105] 

print(df_subs) 
#     val1 val2 
# ind1 ind2 ind3    
# a c 0  100 70 
#   1  101 71 
#   2  102 72 
#  d 0  103 73 
#   1  104 74 
#   2  105 75 

print(df_subs.index) 
# MultiIndex(levels=[['a', 'b'], ['c', 'd', 'e'], [0, 1, 2]], 
#   labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]], 
#   names=['ind1', 'ind2', 'ind3']) 

そのため、手動でインデックスをリセット検討し、元の割り当て最後に

df_subs = df_mult.loc['a', ['c', 'd'], :].reset_index() 

df_subs = df_subs.set_index(['ind1', 'ind2', 'ind3']) 

print(df_subs.index) 
# MultiIndex(levels=[['a'], ['c', 'd'], [0, 1, 2]], 
#   labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]], 
#   names=['ind1', 'ind2', 'ind3']) 

以下、最後.loc割り当てのために(# 2)、少なくとも必要な第1の指標を提供する:

df_subs2 = df_subs.loc['a', 'c', :] 
#  val1 val2 
# ind3    
# 0  100 70 
# 1  101 71 
# 2  102 72 
関連する問題