複数の列に対して _get_level_values
_ の結果を取得する方法はありますか?
次のDataFrame
が与えられます:
_ d
a b c
1 4 10 16
11 17
5 12 18
2 5 13 19
6 14 20
3 7 15 21
_
レベルa
およびc
の値(、つまりタプルのリスト)を取得したい:
_[(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
注:
_get_level_values
_に複数のレベルを与えることはできません(例:_df.index.get_level_values(['a','c']
_)
必要な各列に対して_get_level_values
_を使用し、それらを一緒にZip
することができる回避策があります。
例えば:
_a_list = df.index.get_level_values('a').values
c_list = df.index.get_level_values('c').values
print([i for i in Zip(a_list,c_list)])
[(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
しかし、列の数が増えると面倒になります。
DataFrame
:df = pd.DataFrame({'a':[1,1,1,2,2,3],'b':[4,4,5,5,6,7,],'c':[10,11,12,13,14,15], 'd':[16,17,18,19,20,21]}).set_index(['a','b','c'])
MultiIndex
の.tolist()
メソッドは、MultiIndex
のすべてのレベルのタプルのリストを提供します。たとえば、あなたの例ではDataFrame
、
_df.index.tolist()
# => [(1, 4, 10), (1, 4, 11), (1, 5, 12), (2, 5, 13), (2, 6, 14), (3, 7, 15)]
_
したがって、ここに2つのアイデアがあります。
元のMultiIndex
からタプルのリストを取得し、結果をフィルタリングします。
_[(a, c) for a, b, c in df.index.tolist()]
# => [(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
この単純な方法の欠点は、必要なレベルの順序を手動で指定する必要があることです。代わりに、_itertools.compress
_を利用して名前で選択できます。
_from itertools import compress
mask = [1 if name in ['a', 'c'] else 0 for name in df.index.names]
[Tuple(compress(t, mask)) for t in df.index.tolist()]
# => [(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
必要なレベルを正確に持つMultiIndexを作成し、.tolist()
を呼び出します。
_df.index.droplevel('b').tolist()
# => [(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
ドロップしたいレベルではなく、保持したいレベルに名前を付けたい場合は、次のようにすることができます。
_df.index.droplevel([level for level in df.index.names
if not level in ['a', 'c']]).tolist()
# => [(1, 10), (1, 11), (1, 12), (2, 13), (2, 14), (3, 15)]
_
選択したいインデックス名のリストを渡すことができる限り、これはそれほど面倒ではありません。
df.reset_index()[['a', 'c']].to_dict(orient='split')['data']
インデックスオブジェクトからレベル'a'
と'b'
を直接選択する方法が見つからなかったため、reset_index
を使用しました。
to_dict
は、タプルではなくリストのリストを返すことに注意してください。
[[1, 10], [1, 11], [1, 12], [2, 13], [2, 14], [3, 15]]