
Pythonでデータの前処理や変換を行う際に、柔軟かつ強力に使えるメソッドのひとつが pandas の .apply()
です。
この記事では .apply()
の基本的な使い方から、lambda関数との組み合わせ、他のメソッドとの違いまでわかりやすく解説します!
.apply() とは?
.apply()
は、SeriesやDataFrameの各要素、列、行に対して関数を適用できるメソッドです。
特にループ処理を使わず、pandas流の「ベクトル化」した高速処理が可能になります。
データの変換・分類・集計など、さまざまな前処理に活用できます。
具体例①:Seriesに関数を適用する(文字列を大文字に)
Seriesの各文字列を大文字にする例で、.apply()
の挙動を確認していきましょう。
1 2 3 4 5 |
import pandas as pd s = pd.Series(["apple", "banana", "cherry"]) print(s.apply(str.upper)) |
このコードでやっていることは下記です。
str.upper
という文字列を大文字にする関数を、Seriesの各要素に適用apply()
により1行ずつ繰り返さなくても高速処理が可能に
結果は下記となり、各Seriesの要素に関数が適用され、大文字になっています。
1 2 3 4 |
0 APPLE 1 BANANA 2 CHERRY dtype: object |
具体例②:DataFrameの列ごとに関数を適用(行方向)
次は、DataFrameの行ごとに処理を行う方法を紹介します。
ここでは「数学(math)」と「英語(english)」の点数を合計し、新しい列 total
を作成します。
1 2 3 4 5 6 7 8 9 |
df = pd.DataFrame({ "math": [80, 90, 70], "english": [75, 85, 95] }) # 行ごとの合計を新しい列に追加 df["total"] = df.apply(lambda row: row["math"] + row["english"], axis=1) print(df) |
実行結果
1 2 3 4 |
math english total 0 80 75 155 1 90 85 175 2 70 95 165 |
このコードでやっていることは下記です。
-
axis=1
を指定
→ 「列方向(横方向)」に処理を適用します。つまり、行ごとに関数を実行することになります。 -
lambda row: ...
で行データを操作
各行はrow
という引数で受け取り、row["math"]
やrow["english"]
のように列名でアクセスできます。 -
複数列を組み合わせた計算が可能
今回は足し算ですが、条件分岐を使ってフラグ列を作ったり、比率・加重平均などの複雑な計算も柔軟に書けます。
apply(axis=1) は、「行単位で処理」をしたいときに非常に便利です。
列をまたいだ処理をまとめたいときの基本テクニックとして覚えておくと役立ちます。
.apply() の主な引数と使い方
DataFrame.apply()
はとても柔軟で、引数を使い分けることでさまざまな処理ができます。
引数名 | 意味・用途 | 例 |
---|---|---|
func | 適用したい関数。lambda 、組み込み関数、ユーザー定義関数が使える |
lambda x: x*2 , str.upper |
axis | 処理する方向。0 =列単位(デフォルト)、1 =行単位 |
axis=1 で行ごとの処理 |
raw | True にすると NumPy 配列 (ndarray ) で渡されるため高速化。ただし柔軟性は低い |
raw=False が基本 |
result_type | 出力を DataFrame にするか Series にするかを制御(pandas 0.23以降) |
result_type="expand" など |
args | 関数に渡す追加の引数をタプルで指定 | args=(100,) |
1. func
実際に適用する処理を書きます。
1 2 3 |
df["math"].apply(lambda x: x * 2) # 点数を2倍に df["english"].apply(str.upper) # 英語の文字を大文字に |
2. axis
処理する「方向」を指定します。
1 2 3 |
df.apply(sum, axis=0) # 列ごとに合計(デフォルト) df.apply(sum, axis=1) # 行ごとに合計 |
3. raw
行や列を そのまま NumPy 配列 として受け取るかどうか。
高速ですが、列名アクセスはできません。
1 2 3 |
df.apply(lambda x: x.sum(), axis=1, raw=False) # 通常はこちら df.apply(lambda x: x.sum(), axis=1, raw=True) # NumPy配列で処理 |
4. result_type
戻り値の形式を制御できます。
1 2 3 4 5 |
df = pd.DataFrame({"A": [1,2], "B": [3,4]}) # expand → 複数列に展開 df.apply(lambda x: [x["A"], x["B"]*10], axis=1, result_type="expand") |
5. args
関数に追加引数を渡せます。
1 2 3 4 5 |
def add_num(x, n): return x + n df["math"].apply(add_num, args=(100,)) |
具体的な活用シーン
.apply()
は「行」「列」「セル単位の複雑な処理」に強いです。
例えば以下のような場面で役立ちます。
-
文字列変換
-
.apply(str.lower)
-
.apply(lambda x: x.strip())
-
-
数値処理
-
正規化:
.apply(lambda x: x/100)
-
条件分岐でラベル化:
.apply(lambda x: "Pass" if x >= 60 else "Fail")
-
-
複数列を使った特徴量作成
-
df.apply(lambda row: row["math"] + row["english"], axis=1)
-
-
カテゴリ分け
-
年齢 → 年代区分(10代・20代…)
-
点数 → ランク分類(A/B/C など)
-
-
日付や文字列の加工
-
pd.to_datetime
と組み合わせて変換 -
正規表現で文字列を抽出
-
「単純な加算・平均」なら演算子や .sum()
を使う方が速く、「複雑な条件付き処理」なら .apply()
が活きてきます。
他の類似メソッドとの違い
pandas には似たようなメソッドがいくつかあります。
混乱しやすいので整理しておきましょう。
メソッド | 特徴 |
---|---|
apply() |
行や列単位で柔軟な関数適用が可能。最も汎用性が高い |
map() |
Seriesに対してのみ使用。要素単位で処理(辞書や関数で変換) |
applymap() |
DataFrame全体に要素単位で適用(セル単位)。2次元での変換が必要なとき |
transform() |
集計後も元の形を維持。groupbyとの併用で元データサイズを保てる |
使い分けの目安
- 「列ごと・行ごと」→
apply()
- 「1列だけ(Series)」→
map()
- 「セルごとに全部」→
applymap()
- 「groupby と組み合わせて加工」→
transform()
注意点
.apply()
はとても便利ですが、使いどころを間違えると パフォーマンスが悪化 することもあります。
-
ベクトル化された演算の方が速い場合が多い
例:df["x"] * 2
はdf["x"].apply(lambda x: x*2)
より高速 -
文字列処理は
.str
系、条件処理は.where()
の方が効率的
例:df["name"].str.lower()
は.apply(str.lower)
より高速 -
行方向(axis=1)の処理は重くなりやすい
数万行を超えるデータで複雑な関数を使うと、かなり遅くなることがあります。
.apply()
は 柔軟に処理を行いたい場合に使い、速度が重要な場合はベクトル化や専用 API を優先する、という考え方がおすすめです。
まとめ
今回はpandasの.apply()
を紹介しました!
.apply()
は、行・列に対して関数を適用するための柔軟で強力なメソッド- lambda式や自作関数との相性が良く、特徴量エンジニアリングにも向いている
map()
やapplymap()
などとの違いを理解して使い分けることが重要
.apply()
をマスターすれば、pandasでの前処理・変換の自由度が一気に高まります。
実際に手を動かして、どんな関数がどのように適用されるかを体感してみてくださいね!