割り当てを連鎖せずにこれを行う方法がわかりません(コピーを設定するので、おそらくどうにか動作しないでしょう)。
Multiindex pandasデータフレームのサブセットを取得し、ゼロ未満の値をテストし、それらをゼロに設定することは望ましくありません。
例えば:
df = pd.DataFrame({('A','a'): [-1,-1,0,10,12],
('A','b'): [0,1,2,3,-1],
('B','a'): [-20,-10,0,10,20],
('B','b'): [-200,-100,0,100,200]})
df[df['A']<0] = 0.0
与える
In [37]:
df
Out[37]:
A B
a b a b
0 -1 0 -20 -200
1 -1 1 -10 -100
2 0 2 0 0
3 10 3 10 100
4 12 -1 20 200
これは、条件に基づいて設定できなかったことを示しています。または、連鎖割り当てを行った場合:
df.loc[:,'A'][df['A']<0] = 0.0
これにより、同じ結果が得られます(およびコピー警告の設定)
最初のレベルが必要なレベルであるという条件に基づいて、各列をループできます。
for one,two in df.columns.values:
if one == 'A':
df.loc[df[(one,two)]<0, (one,two)] = 0.0
これにより、望ましい結果が得られます。
In [64]:
df
Out[64]:
A B
a b a b
0 0 0 -20 -200
1 0 1 -10 -100
2 0 2 0 0
3 10 3 10 100
4 12 0 20 200
しかし、どういうわけか、これを行うには、列をループするよりも良い方法があると感じています。パンダでこれを行う最良の方法は何ですか?
これは(およびMultiIndexスライサーを使用する主な動機の1つ)のアプリケーションです。ドキュメントを参照してください here
In [20]: df = pd.DataFrame({('A','a'): [-1,-1,0,10,12],
('A','b'): [0,1,2,3,-1],
('B','a'): [-20,-10,0,10,20],
('B','b'): [-200,-100,0,100,200]})
In [21]: df
Out[21]:
A B
a b a b
0 -1 0 -20 -200
1 -1 1 -10 -100
2 0 2 0 0
3 10 3 10 100
4 12 -1 20 200
In [22]: idx = pd.IndexSlice
In [23]: mask = df.loc[:,idx['A',:]]<0
In [24]: mask
Out[24]:
A
a b
0 True False
1 True False
2 False False
3 False False
4 False True
In [25]: df[mask] = 0
In [26]: df
Out[26]:
A B
a b a b
0 0 0 -20 -200
1 0 1 -10 -100
2 0 2 0 0
3 10 3 10 100
4 12 0 20 200
列インデックスの第1レベルで作業しているため、以下も同様に機能します。上記の例はより一般的で、「a」に対してこれを実行したいとします。
In [30]: df[df[['A']]<0] = 0
In [31]: df
Out[31]:
A B
a b a b
0 0 0 -20 -200
1 0 1 -10 -100
2 0 2 0 0
3 10 3 10 100
4 12 0 20 200