次のようなMultiIndex列を持つDataFrameがあります。
# sample data
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'],
['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)
data
特定の列のみを選択する適切で簡単な方法は何ですか(例:['a', 'c']
、範囲ではない)第2レベルから?
現在、私はそれを次のようにしています:
import itertools
tuples = [i for i in itertools.product(['one', 'two'], ['a', 'c'])]
new_index = pd.MultiIndex.from_tuples(tuples)
print(new_index)
data.reindex_axis(new_index, axis=1)
ただし、itertools
をバストアウトし、別のMultiIndexを手動で作成してからインデックスを再作成する必要があるため、これは良い解決策のようには思えません(列のリストがそうでないため、実際のコードはさらに面倒です)フェッチが簡単です)。これを行うにはいくつかのix
またはxs
の方法が必要だと確信していますが、私が試みたすべての結果はエラーになりました。
それは素晴らしいことではありませんが、おそらく:
>>> data
one two
a b c a b c
0 -0.927134 -1.204302 0.711426 0.854065 -0.608661 1.140052
1 -0.690745 0.517359 -0.631856 0.178464 -0.312543 -0.418541
2 1.086432 0.194193 0.808235 -0.418109 1.055057 1.886883
3 -0.373822 -0.012812 1.329105 1.774723 -2.229428 -0.617690
>>> data.loc[:,data.columns.get_level_values(1).isin({"a", "c"})]
one two
a c a c
0 -0.927134 0.711426 0.854065 1.140052
1 -0.690745 -0.631856 0.178464 -0.418541
2 1.086432 0.808235 -0.418109 1.886883
3 -0.373822 1.329105 1.774723 -0.617690
うまくいくでしょうか?
loc
またはix
を使用できます。loc
の例を示します。
data.loc[:, [('one', 'a'), ('one', 'c'), ('two', 'a'), ('two', 'c')]]
MultiIndexed DataFrameがあり、一部の列のみをフィルターで除外する場合は、それらの列に一致するタプルのリストを渡す必要があります。したがって、itertoolsのアプローチはほとんど問題ありませんでしたが、新しいMultiIndexを作成する必要はありません。
data.loc[:, list(itertools.product(['one', 'two'], ['a', 'c']))]
私ははるかに良い方法があると思います(今)、これが私がこの質問(グーグルのトップの結果でした)を陰から引き出すのを邪魔する理由です:
data.select(lambda x: x[1] in ['a', 'b'], axis=1)
期待どおりの出力をすばやくクリーンなワンライナーで提供します。
one two
a b a b
0 -0.341326 0.374504 0.534559 0.429019
1 0.272518 0.116542 -0.085850 -0.330562
2 1.982431 -0.420668 -0.444052 1.049747
3 0.162984 -0.898307 1.762208 -0.101360
それはほとんど自己説明的な、[1]
はレベルを指します。
列インデクサーの第2レベルで'a'
および'c'
という名前のすべての列を選択するには、スライサーを使用できます。
>>> data.loc[:, (slice(None), ('a', 'c'))]
one two
a c a c
0 -0.983172 -2.495022 -0.967064 0.124740
1 0.282661 -0.729463 -0.864767 1.716009
2 0.942445 1.276769 -0.595756 -0.973924
3 2.182908 -0.267660 0.281916 -0.587835
ここ スライサーの詳細を読むことができます。
ix
とselect
は非推奨です!pd.IndexSlice
を使用すると、loc
をix
およびselect
よりも望ましいオプションにすることができます。
DataFrame.loc
with pd.IndexSlice
# Setup
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'],
['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame('x', index=range(4), columns=col)
data
one two
a b c a b c
0 x x x x x x
1 x x x x x x
2 x x x x x x
3 x x x x x x
data.loc[:, pd.IndexSlice[:, ['a', 'c']]]
one two
a c a c
0 x x x x
1 x x x x
2 x x x x
3 x x x x
または、axis
パラメータをloc
に指定して、インデックスを付ける軸を明示的に指定できます。
data.loc(axis=1)[pd.IndexSlice[:, ['a', 'c']]]
one two
a c a c
0 x x x x
1 x x x x
2 x x x x
3 x x x x
MultiIndex.get_level_values
loc
でフィルタリングするためにdata.columns.get_level_values
を呼び出すことも別のオプションです。
data.loc[:, data.columns.get_level_values(1).isin(['a', 'c'])]
one two
a c a c
0 x x x x
1 x x x x
2 x x x x
3 x x x x
これにより、当然のことながら、単一レベルの条件式のフィルタリングが可能になります。次に、辞書式フィルタリングを使用したランダムな例を示します。
data.loc[:, data.columns.get_level_values(1) > 'b']
one two
c c
0 x x
1 x x
2 x x
3 x x
MultiIndexesのスライスとフィルタリングの詳細については、 (Select rows in pandas MultiIndex DataFrame )を参照してください。
最も簡単な方法は、.loc
を使用することです。
>>> data.loc[:, (['one', 'two'], ['a', 'b'])]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
[]
と()
は、MultiIndex
オブジェクトを処理するときに特別な意味を持つことに注意してください。
(...)タプルは1つのmulti-levelキーとして解釈されます
(...)リストは複数のキーを指定するために使用されます[同じレベル]
(...)リストのタプルは、レベル内のいくつかの値を参照します
(['one', 'two'], ['a', 'b'])
を記述するとき、タプル内の最初のリストは、MultiIndex
の第1レベルから必要なすべての値を指定します。タプル内の2番目のリストは、MultiIndex
の第2レベルから取得するすべての値を指定します。
編集1:別の可能性は、slice(None)
を使用して、最初のレベルから何でも欲しいことを指定することです(:
によるスライスと同様に機能します)リスト)。次に、必要な第2レベルの列を指定します。
>>> data.loc[:, (slice(None), ["a", "b"])]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
構文slice(None)
が魅力的である場合、もう1つの可能性は、pd.IndexSlice
を使用することです。これにより、より複雑なインデックスでフレームをスライスできます。
>>> data.loc[:, pd.IndexSlice[:, ["a", "b"]]]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
pd.IndexSlice
を使用する場合、通常どおり:
を使用してフレームをスライスできます。
Marc P。 のリフ スライスを使用した回答 :
import pandas as pd
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'], ['a', 'b', 'c', 'a', 'b', 'c']])
data = pd.DataFrame(np.random.randn(4, 6), columns=col)
data.loc[:, pd.IndexSlice[:, ['a', 'c']]]
one two
a c a c
0 -1.731008 0.718260 -1.088025 -1.489936
1 -0.681189 1.055909 1.825839 0.149438
2 -1.674623 0.769062 1.857317 0.756074
3 0.408313 1.291998 0.833145 -0.471879
pandas 0.21程度)以降、 。selectは非推奨になり、.locに置き換えられます 。