一覧へ

apply、map、applymap — データの変換を行う3つのツール

pandasのapply、map、applymapという3つの関数の違いを明確に理解し、状況に応じて適切なツールを選びます。

中級
|
10
|
検証済み (2026-07)
applymapapplymapデータ変換ベクトル演算
進捗0/17 (0%)

apply、map、applymap — データ変換の3つのツール

このトピックを修了すると

applymapapplymap の3つの関数の違いを明確に理解し、状況に応じた適切なツールを選択できるようになり、パフォーマンスの違いを理解できます。


なぜ3つも関数があるのか

pandasでデータを変換するための関数が3つもあるので、最初は混乱するかもしれません。それぞれ適用範囲が異なります。

関数対象適用単位
map()Series (1次元)個別の値ごと
apply()Series または DataFrame行または列ごと
applymap()DataFrame (2次元)個別の値ごと

一言で言うと:mapはSeriesの各値に、applymapはDataFrameの各値に、applyは行/列全体に関数を適用します。


map — Seriesの各値を変換

map()はSeries専用です。各値に関数を適用するか、辞書でマッピングします。

関数マッピング

python
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Carol"],
"score": [85.7, 92.3, 78.1]
})
# 各名前を大文字に
df["name"].map(str.upper)
# 0 ALICE
# 1 BOB
# 2 CAROL
# 各スコアを四捨五入
df["score"].map(round)
# 0 86
# 1 92
# 2 78

辞書マッピング

python
grade_map = {
"A": "Excellent",
"B": "Good",
"C": "Average"
}
grades = pd.Series(["A", "B", "C", "A", "B"])
grades.map(grade_map)
# 0 Excellent
# 1 Good
# 2 Average
# 3 Excellent
# 4 Good

辞書にない値は NaN になります。これは、実務でカテゴリエンコーディングによく使用されます。

lambdaと組み合わせて

python
df["score"].map(lambda x: "Pass" if x >= 80 else "Fail")
# 0 Pass
# 1 Pass
# 2 Fail

apply — 行または列単位で関数を適用

apply() は、SeriesとDataFrameの両方で使用できます。

Series.apply — mapと類似

python
df["score"].apply(lambda x: round(x, 1))
# map() と同じ結果

Seriesでは、map()とほぼ同じです。違いは、apply() が追加の引数を渡せることです。

DataFrame.apply — 列(または行)単位

python
df = pd.DataFrame({
"math": [85, 92, 78],
"english": [90, 88, 95],
"science": [88, 91, 82]
})
# 各科目(列)の平均
df.apply("mean") # axis=0 (デフォルト、列方向)
# math 85.0
# english 91.0
# science 87.0
# 各生徒(行)の平均
df.apply("mean", axis=1) # axis=1 (行方向)
# 0 87.666667
# 1 90.333333
# 2 85.000000

axis=0 は「上から下へ」(各列に適用)、axis=1 は「左から右へ」(各行に適用)です。

行単位で複数のカラムを参照

python
df = pd.DataFrame({
"name": ["Alice", "Bob", "Carol"],
"math": [85, 92, 78],
"english": [90, 88, 95]
})
# 各生徒の2科目のうち、高い点数
df.apply(lambda row: max(row["math"], row["english"]), axis=1)
# 0 90
# 1 92
# 2 95

行(axis=1)単位の apply で、row はその行の Series です。複数のカラムを参照して、複合的な計算を行うことができます。


applymap — DataFrameのすべての値を変換

applymap() はDataFrame専用で、すべてのセルに適用します。

python
df = pd.DataFrame({
"math": [85.7, 92.3, 78.1],
"english": [90.2, 88.9, 95.4],
"science": [88.1, 91.7, 82.3]
})
# すべての値を整数に
df.applymap(int)
# math english science
# 0 85 90 88
# 1 92 88 91
# 2 78 95 82
# すべての値にフォーマットを適用
df.applymap(lambda x: f"{x:.1f}%")
# math english science
# 0 85.7% 90.2% 88.1%
# 1 92.3% 88.9% 91.7%
# 2 78.1% 95.4% 82.3%

注記: pandas 2.1 以降、applymap()map() に統合されました。DataFrame.map() で同じ操作ができます。しかし、多くのコードベースではまだ applymap() を使用しているので、覚えておく必要があります。


3つの関数を比較 — 一目で

python
import pandas as pd
df = pd.DataFrame({
"A": [1, 2, 3],
"B": [4, 5, 6]
})
# map: Series の各値 → 値
df["A"].map(lambda x: x * 10) # Series → Series
# 0 10
# 1 20
# 2 30
# apply (Series): map と類似
df["A"].apply(lambda x: x * 10) # Series → Series (同じ結果)
# apply (DataFrame, axis=0): 列単位
df.apply(sum) # DataFrame → Series
# A 6
# B 15
# apply (DataFrame, axis=1): 行単位
df.apply(sum, axis=1) # DataFrame → Series
# 0 5
# 1 7
# 2 9
# applymap: DataFrame の各値 → 値
df.applymap(lambda x: x * 10) # DataFrame → DataFrame
# A B
# 0 10 40
# 1 20 50
# 2 30 60

パフォーマンス — ベクトル演算を優先

applymapapplymap は、内部で Python のループを回します。pandas の組み込み演算(ベクトル演算)の方がはるかに高速です。

python
import numpy as np
df = pd.DataFrame({"value": range(1_000_000)})
# 遅い — apply (Python ループ)
%timeit df["value"].apply(lambda x: x * 2)
# ~200ms
# 高速 — ベクトル演算 (C で実行)
%timeit df["value"] * 2
# ~2ms (100倍高速)

ルール: 単純な算術、比較、文字列メソッドはベクトル演算を使用します。apply() は、ベクトル演算で表現できない複雑なロジックでのみ使用します。

python
# 悪い — apply で条件分岐
df["label"] = df["value"].apply(lambda x: "high" if x > 500000 else "low")
# 良い — np.where (ベクトル演算)
df["label"] = np.where(df["value"] > 500000, "high", "low")
# 悪い — apply で文字列処理
df["upper"] = df["name"].apply(str.upper)
# 良い — str accessor (ベクトル演算)
df["upper"] = df["name"].str.upper()

実践的なパターン — 複合変換

ベクトル演算で不可能な場合に apply を使用します。

python
df = pd.DataFrame({
"name": ["Alice Smith", "Bob Lee", "Carol Park"],
"birth": ["1995-03-15", "1988-11-22", "2001-07-08"],
"department": ["Sales", "Dev", "HR"]
})
def create_employee_id(row):
dept_code = row["department"][:2].upper()
last_name = row["name"].split()[-1].upper()
year = row["birth"][:4]
return f"{dept_code}-{last_name}-{year}"
df["emp_id"] = df.apply(create_employee_id, axis=1)
print(df["emp_id"])
# 0 SA-SMITH-1995
# 1 DE-LEE-1988
# 2 HR-PARK-2001

複数のカラムを参照して、複雑な文字列を作成する処理 — これはベクトル演算で表現することが難しく、apply(axis=1) が適切です。


まとめ

状況ツール
Series の各値を変換map() または apply()
辞書で値をマッピングmap(dict)
DataFrame の各セルを変換applymap() (または pandas 2.1+ map())
列単位の集計apply(func, axis=0)
行単位の複合計算apply(func, axis=1)
単純な算術/比較ベクトル演算 (apply を使用しない)

3つの関数を選ぶ順序:1) ベクトル演算でできるか? → ベクトル演算。2) Series の各値か? → map。3) DataFrame の各セルか? → applymap。4) 行/列単位の複合ロジックか? → apply。 この順序を覚えておけば、パフォーマンスと可読性の両方を高めることができます。


よくある間違い

間違い問題解決
df.map(func) (pandas < 2.1)AttributeErrordf.applymap(func) または pandas をアップグレード
df.apply(func) でスカラを返す期待と異なる結果axis を確認 — 0 は列、1 は行
単純な算術に apply を使用100 倍遅くなるベクトル演算に置き換える
map にないキーNaN が発生fillna() でデフォルト値を指定

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...