条件に応じて値を書き換えたいとき、apply でラムダ式を書くことが多いかもしれません。しかし pandas には where と mask という専用メソッドがあり、ベクトル化された処理で高速に条件付きの値置換ができます。
where の基本
where は「条件を満たす値はそのまま残し、満たさない値を指定した値に置換する」メソッドです。
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie", "Diana"],
"score": [85, 42, 73, 91]
})
df["result"] = df["score"].where(df["score"] >= 60, "不合格")
print(df)
60 点以上のスコアはそのまま残り、60 点未満の値は「不合格」に置き換わります。SQL の CASE WHEN に近い感覚で使えるメソッドです。
mask の基本
mask は where の逆で、「条件を満たす値を置換し、満たさない値はそのまま残す」という動作をします。
df["masked"] = df["score"].mask(df["score"] < 60, 0)
print(df)
この例では 60 点未満のスコアが 0 に置き換えられ、60 点以上の値はそのまま残ります。
条件が True の値を残し、False の値を置換する
条件が True の値を置換し、False の値を残す
DataFrame 全体に適用する
where と mask は Series だけでなく DataFrame 全体にも適用できます。
df_num = pd.DataFrame({
"math": [85, 42, 73],
"english": [91, 58, 65],
"science": [76, 38, 82]
})
result = df_num.where(df_num >= 60, "×")
print(result)
60 点未満のセルがすべて「×」に置き換わります。一括で条件判定できるため、ループを書く必要がありません。
NumPy の where との使い分け
より複雑な条件分岐が必要な場合は、NumPy の np.where も選択肢に入ります。
import numpy as np
df["grade"] = np.where(df["score"] >= 80, "A",
np.where(df["score"] >= 60, "B", "C"))
np.where はネストすることで 3 段階以上の分岐が書けます。ただしネストが深くなると読みにくくなるため、分岐が多い場合は pd.cut やカスタム関数を検討したほうがよいでしょう。
置換値に別の列を使う
置換値として固定値ではなく、別の列や計算結果を渡すこともできます。
df["adjusted"] = df["score"].where(df["score"] >= 60, df["score"] + 20)
条件を満たさないスコアに 20 点を加算する処理です。固定値だけでなく柔軟な置換ができるのが where / mask の強みと言えます。
where と mask を覚えておくと、apply でラムダ式を書く場面を減らせます。ベクトル化された処理なのでパフォーマンスも良好であり、大きなデータセットほど差が出てきます。