HOWTO · Pandas
Lambda 関数を Pandas DataFrame に適用する
このガイドでは、DataFrame.assign()メソッドと DataFrame.apply()メソッドを使用して Lambda 関数を Pandas DataFrame に適用する方法について説明します。
このページの内容
短く単一の式で書ける処理には、pandas と Python の lambda を組み合わせると便利です。列の追加には DataFrame.assign()、行または列ごとの計算には DataFrame.apply()、値の変換には Series.map()、行の抽出には真偽値マスクを使います。何が lambda に渡され、何が返されるかは、使用する操作とその軸によって決まります。
pandas で lambda 関数が行うこと
Python の lambda 式は、lambda value: value * 2 のように、1つの式を含む小さな無名関数を作成します。この式は計算内容を表し、その関数を受け取る pandas の操作によって、列全体、1行、または個々の Series 値のどれが入力になるかが決まります。複数の文が必要な場合や、処理を再利用する場合、関数にわかりやすい名前を付けたい場合は、名前付きの def 関数を使いましょう。
DataFrame.assign() で計算列を追加する
DataFrame.assign() は、指定した列を新規作成または置き換えた DataFrame を返し、元の DataFrame は変更しません。呼び出し可能な値として渡した関数には DataFrame が渡されるため、1つの式で既存の列を1つまたは複数使えます。たとえば、df.assign(percentage=lambda data: data["marks"] / 1000 * 100) は割合を計算し、df.assign(total=lambda data: data["math"] + data["science"]) は2列の値を合計します。新しい列は DataFrame のインデックスに沿って配置されます。
DataFrame.apply() で行または列に関数を適用する
DataFrame.apply() は、既定では各列を関数に渡します。axis=0 は列ごとに関数を適用し、axis=1 は行ごとに適用します。たとえば、各行の base と bonus の値を加算するには、df.apply(lambda row: row["base"] + row["bonus"], axis=1) と書きます。返されるオブジェクトの型は関数の戻り値によって異なり、行ごとにスカラー値を返すと Series になります。列の単純な算術演算には、Python を行ごとに呼び出すより、通常は読みやすく高速な pandas のベクトル化演算を使いましょう。
Series の値を変換または絞り込む
Python 組み込みの map(function, values) は各入力を変換し、イテレーターを返します。結果を list(...) に渡すと、値をリストとして取り出せます。pandas の Series.map(function) も同様に値を変換しますが、元のインデックスに対応した Series を返します。たとえば、df["age"].map(lambda age: age + 1) は年齢を1増やした値を作ります。代入するまでは DataFrame は変更されません。
Python 組み込みの filter(predicate, values) は、判定関数が真となる入力値を残し、イテレーターを返します。pandas の DataFrame を絞り込むときは、真偽値マスクを使うと簡潔で、一致した行とほかの列もまとめて保持できます。例: df[df["age"] < 25]。Series だけを絞る場合は df["age"][df["age"] < 25] と書けます。両者の結果は異なります。Series に対する filter は値を返しますが、DataFrame に対するマスクは行全体を選択します。
lambda で条件分岐を行う
条件式は、lambda が含む1つの式として記述できます。例: lambda income: "Stable" if income >= 5000 else "Unstable"。Series に適用すると、収入ごとにラベルが1つ作られます。しきい値の判定は 5000 を含むため、5000 には Stable、それより小さい値には Unstable が割り当てられます。DataFrame の列に結果を保存するには、たとえば df["category"] = df["income"].apply(lambda income: "Stable" if income >= 5000 else "Unstable") とします。
用途に合う方法を選び、結果を確認する
列を追加するには assign()、行または列ごとに関数を実行するには apply()、各値を変換するには Series.map()、一致する行を選ぶには真偽値マスクを使います。代入する前に、軸、lambda に渡される入力、結果が Series か DataFrame かを確認してください。次の一連の例では、関連するデータを使ってこれらの方法を示します。
このセクションのコードと表示されるラベルや出力は英語のままです。
import pandas as pd
df = pd.DataFrame({"name": ["Ari", "Bea", "Cal"], "math": [80, 92, 75], "science": [85, 88, 90], "income": [4000, 6000, 5000]})
result = df.assign(
total=lambda data: data["math"] + data["science"],
next_income=lambda data: data["income"].map(lambda value: value + 1000),
category=lambda data: data["income"].apply(lambda value: "Stable" if value >= 5000 else "Unstable"),
)
selected = result[result["total"] >= 170]
print(selected[["name", "total", "next_income", "category"]].to_string(index=False))