web-dev-qa-db-ja.com

Pandas:マルチインデックスデータフレームのサブセットの条件に基づいて値を設定する適切な方法

割り当てを連鎖せずにこれを行う方法がわかりません(コピーを設定するので、おそらくどうにか動作しないでしょう)。

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

しかし、どういうわけか、これを行うには、列をループするよりも良い方法があると感じています。パンダでこれを行う最良の方法は何ですか?

17
pbreach

これは(および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
17
Jeff