前回の記事で、np.whereという関数の紹介をしたのですが、pandasにも同名のwhereっていうメソッドがあるので紹介します。また、非常に似た挙動のmaskというメソッドもありますので合わせて書きます。
pandasのwhereとmaskはDataFrameやSeriesが持っているメソッドです。
参考:
pandas.DataFrame.where — pandas 2.2.3 documentation
pandas.DataFrame.mask — pandas 2.2.3 documentation
挙動はnumpyのwhereと似ている部分があり、条件に応じて要素を置き換えます。ただし、使い方が少しだけ異なっており、np.where()のようにnumpy自体が持っていた関数ではなくDataFrameやSeriesなどのメソッドなので元の値が利用される分、np.whereより引数が一つ少なくなります。
1個目の引数に条件、2個目の引数に置き換える値(省略すればNoneになります。また関数を指定することもできます。)を入れて使用します。
そしてこの条件の扱いがwhereとmaskで異なります。
whereは条件がFalseの場合に値を置き換え、maskは条件がTrueの場合に値を置き換えます。
例えば、0~9の値を並べたデータフレームで、3の倍数かどうかという条件で置き換え対象を負の数にするような書き方をすると、whereは3の倍数以外の数がマイナスになり、maskの方は3の倍数がマイナスになります。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array(range(10)).reshape(5, 2))
print(df)
"""
0 1
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9
"""
# 3の倍数が条件を満たすのでそのまま残り、それ以外がマイナスになる。
print(df.where(df%3==0, -df))
"""
0 1
0 0 -1
1 -2 3
2 -4 -5
3 6 -7
4 -8 9
"""
# 3の倍数が条件を満たすのでマイナスになる。
print(df.mask(df%3==0, -df))
"""
0 1
0 0 1
1 2 -3
2 4 5
3 -6 7
4 8 -9
"""
上記の例は、2個目の引数に元のデータと同じ形のデータフレームが渡されていますが、2個目の引数は定数を渡すこともできるし、関数を渡すこともできます。
例えば奇数を定数-1に置き換えたり、奇数を3倍して1足すようなメソッドは次のようになるでしょう。
print(df.mask(df%2==0, -1))
"""
0 1
0 -1 1
1 -1 3
2 -1 5
3 -1 7
4 -1 9
"""
print(df.mask(df%2==1, lambda x: 3*x+1))
"""
0 1
0 0 4
1 2 10
2 4 16
3 6 22
4 8 28
"""
「こういう値に対してこうしたい」っていう日本語の説明に対して直感的に書けるのはmaskの方ですね。fillna()の汎用版みたいなイメージで使いやすいです。
whereの方は、「こういう条件を満たす値はそのままでいいんだ、そうでは無いのを置き換えたい」っていうイメージでしょうか。