こんにちは。現役エンジニアの”はやぶさ”@Cpp_Learningです。
今回はデータ分析などに役立つ Pandas の mask() を紹介します。
Contents
やりたいこと -条件を満たす値を任意の値に置き換える-
データ分析などでPandasのDataFrameを使う際、以下のように条件を満たす値を任意の値に置き換えたいときがあります。
データフレーム内の偶数にマスクする
A | B | C |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
負数に置き換える
A | B | C |
0 | 1 | -2 |
3 | -4 | 5 |
-6 | 7 | -8 |
この例でいう”条件”と”任意の値に置き換える処理(以下 変換処理)”は以下の通りです。
- 条件:データフレーム内の偶数
- 変換処理:条件を満たす値に”-1”をかける
Pandasの mask() を使えば、このような処理を簡単に実現できます。
pandas.DataFrame.maskを使い方 -基礎編-
いくつかサンプルコードを作成してみます。
サンプル❶ -偶数を負数に変換-
最初に紹介した偶数を負数に変換する処理は以下のコードで実現できます。
1 2 3 4 5 6 7 8 9 10 |
import pandas as pd import numpy as np # Create the dataframe df = pd.DataFrame(np.arange(9).reshape(-1, 3), columns=['A', 'B', 'C']) print(df) # Replace "df % 2 == 0" with "-df" df_mask = df.mask(df % 2 == 0, -df) print(df_mask) |
改めて、イメージを載せておきます(下記参照)
データフレーム内の偶数にマスクする
A | B | C |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
負数に置き換える
A | B | C |
0 | 1 | -2 |
3 | -4 | 5 |
-6 | 7 | -8 |
以降のサンプルでは”import”のコードを省略します。
サンプル❷ -閾値以上の値を”0”に変換-
閾値以上の値を”0”に変換するコードは以下の通りです。
1 2 3 4 5 6 7 |
# Create the dataframe df = pd.DataFrame(np.arange(9).reshape(-1, 3), columns=['A', 'B', 'C']) print(df) # Replace "df >= 5" with 0 df_mask = df.mask(df >= 5, 0) print(df_mask) |
※閾値を”5”に設定
データフレーム内の5以上にマスクする
A | B | C |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
”0”に置き換える
A | B | C |
0 | 1 | 2 |
3 | 4 | 0 |
0 | 0 | 0 |
サンプル➌ -欠損データ(NaN)を”-1”に変換-
欠損データ(NaN)を”-1”に変換するコードは以下の通りです。
1 2 3 4 5 6 7 8 |
# Create the dataframe df = pd.DataFrame({"A": [0, 3, None], "B": [1, None, 7], "C": [2, 5, 8]}) # Replace "None" with -1 df_mask = df.mask(df.isna(), -1) print(df_mask) |
データフレーム内のNaNにマスクする
A | B | C |
0 | 1 | 2 |
3 | NaN | 5 |
NaN | 7 | 8 |
“-1″に置き換える
A | B | C |
0 | 1 | 2 |
3 | -1 | 5 |
-1 | 7 | 8 |
pandas.DataFrame.maskを使い方 -応用編-
ここまでのサンプルはデータフレーム全体に対する処理でしたが、任意の列(カラム)に対して処理することもできます。
サンプル❹ -C列の閾値より小さい値を”0”に変換し、D列に出力-
C列の”3″より小さい値を検索し、”0″に変換したものをD列に出力します。
1 2 3 4 5 6 7 8 9 |
# Create the dataframe df = pd.DataFrame({"A": [0, 3, None], "B": [1, None, 7], "C": [2, 5, 8]}) print(df) # Replace "df['C'] < 3" with 0 and Create df["D"] df["D"] = df['C'].mask(df['C'] < 3, 0) print(df) |
C列の”3″より小さい値にマスクする
A | B | C |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
”0”に置き換えて、D列に出力
A | B | C | D |
0 | 1 | 2 | 0 |
3 | 4 | 5 | 5 |
6 | 7 | 8 | 8 |
※C列のマスクしてない値については、何もぜずにD列へコピーされます
サンプル➎ -A列とB列の一部の値をコピーして、D列に出力-
最後に、A列とB列の一部の値をコピーしてD列に出力してみます。
1 2 3 4 5 6 7 8 9 10 |
# Create the dataframe df = pd.DataFrame({"A": [0, 3, 6], "B": [1, 4, 7], "C": [2, 5, 8], "M": ["T", "F", "T"]}) print(df) # Creating df["D"] from df["A"] and df["B"] df['D'] = df['A'].mask(df['M'] == "T", df['B']) print(df) |
M列の”T”にマスクする(B列の一部の値を指定)
A | B | C | M |
0 | 1 | 2 | T |
3 | 4 | 5 | F |
6 | 7 | 8 | T |
A列をD列にコピーし、かつ一部をB列の値に変換して、D列に出力
A | B | C | M | D |
0 | 1 | 2 | T | 1 |
3 | 4 | 5 | F | 3 |
6 | 7 | 8 | T | 7 |
※M列の”T”や”F”はラベルなどを想定
まとめ -pandas.DataFrame.maskを使い方-
データ分析などに役立つ Pandas の mask() について紹介し、いくつか実践的なサンプルも作成してみました。
今までfor文使って線形探索していた処理が、スッキリしたコードで実現できました。
本記事が、より良いソースコードを書くときの参考になれば嬉しいです。