【Pandas関数適用術】map, apply, applymapを使いこなしてデータ処理を効率化しよう!🚀
Pandasでデータ分析を行う際、DataFrameやSeriesの個々の要素、行、または列に対して特定の処理を適用したい場面は頻繁にあります。そんな時に役立つのが、**map、apply、applymap**という3つのメソッドです。これらを適切に使い分けることで、ループ処理を書くことなく、より効率的かつ簡潔にデータ操作を行うことができます。この記事では、それぞれのメソッドの特性と使い方を、短いサンプルコードと丁寧な解説でご紹介します。
map, apply, applymapとは?なぜ使い分けるのか?
これらのメソッドは、Pandasオブジェクト(SeriesやDataFrame)に関数を適用するためのツールですが、適用範囲や得意な処理が異なります。
-
map: Seriesの各要素に対して関数を適用したり、値を置換したりする際に使います。 -
apply: SeriesまたはDataFrameの行全体、または列全体に対して関数を適用する際に使います。最も汎用性が高いメソッドです。 -
applymap: DataFrameの各要素に対して関数を適用する際に使います。
これらを使い分けることで、コードの可読性を高め、処理速度を最適化できます。
mapメソッドの使い方(Seriesの要素向け)
mapは主にSeriesで使われ、各要素を変換したり、辞書やSeriesを使って値をマッピング(置換)したりするのに非常に便利です。
関数を適用して各要素を変換する
Seriesの各要素にシンプルな関数を適用したい場合に便利です。
import pandas as pd
s = pd.Series([1, 2, 3, 4])
print("オリジナルSeries:\n", s)
# 各要素を2倍にする
s_mapped = s.map(lambda x: x * 2)
print("\nmapで2倍にしたSeries:\n", s_mapped)
解説:
lambda x: x * 2という匿名関数がsの各要素(1, 2, 3, 4)に適用され、新しいSeriesが生成されます。
辞書を使って値を置換する(マッピング)
特定の値を別の値に置き換えたい場合に非常に効率的です。
s_str = pd.Series(['apple', 'banana', 'apple', 'orange'])
print("\nオリジナルSeries (文字列):\n", s_str)
# 辞書を使って値を置換
mapping = {'apple': 'リンゴ', 'banana': 'バナナ'}
s_mapped_dict = s_str.map(mapping)
print("\nmapで辞書置換したSeries:\n", s_mapped_dict)
解説:
s_strの要素がmapping辞書のキーと一致すれば、対応する値に置換されます。辞書にない’orange’はNaNになります。
applyメソッドの使い方(行・列全体向け)
applyはSeriesとDataFrameの両方で使え、行または列全体に関数を適用する最も汎用的なメソッドです。
Seriesに行(列)に関数を適用する
Seriesではmapと同様に要素に適用されますが、より複雑な処理も可能です。
s = pd.Series([1, 2, 3, 4])
# Seriesの合計を計算 (applyでも可能だが、s.sum()の方が一般的)
s_apply_sum = s.apply(lambda x: x * 2) # この場合mapと同じ
print("\napplyで2倍にしたSeries:\n", s_apply_sum)
DataFrameの行または列に関数を適用する
axis引数を使って、行方向(axis=1)または列方向(axis=0、デフォルト)に関数を適用します。
df = pd.DataFrame({
'A': [10, 20, 30],
'B': [1, 2, 3]
})
print("\nオリジナルDataFrame:\n", df)
# 列ごとに合計を計算 (axis=0がデフォルト)
df_col_sum = df.apply(lambda col: col.sum(), axis=0)
print("\napplyで列合計を計算したSeries:\n", df_col_sum)
# 行ごとに合計を計算 (axis=1)
df_row_sum = df.apply(lambda row: row.sum(), axis=1)
print("\napplyで行合計を計算したSeries:\n", df_row_sum)
解説:
-
axis=0(列方向):lambda col: col.sum()が’A’列、’B’列のSeriesそれぞれに適用され、その合計値が計算されます。 -
axis=1(行方向):lambda row: row.sum()が各行のSeriesに適用され、その行の合計値が計算されます。
複数の列に条件付きで関数を適用する
applyを使うと、複数の列を考慮した複雑な条件処理も行えます。
df_multi = pd.DataFrame({
'Score1': [70, 85, 90],
'Score2': [60, 95, 80],
'Passed': [True, False, True]
})
print("\nオリジナルDataFrame (条件付き):\n", df_multi)
# Score1が80以上かつScore2が70以上なら'Excellent'、そうでなければ'Good'と評価
def evaluate_scores(row):
if row['Score1'] >= 80 and row['Score2'] >= 70:
return 'Excellent'
else:
return 'Good'
df_multi['Evaluation'] = df_multi.apply(evaluate_scores, axis=1)
print("\napplyで評価列を追加したDataFrame:\n", df_multi)
解説:
evaluate_scores関数は各行を受け取り、その行の’Score1’と’Score2’の値に基づいて評価を返します。この関数がaxis=1で行ごとに適用され、新しい’Evaluation’列が作成されます。
applymapメソッドの使い方(DataFrameの要素向け)
applymapは、DataFrameの各要素すべてに同じ関数を適用したい場合に特化しています。SeriesのmapのDataFrame版と考えるとわかりやすいです。
df_elem = pd.DataFrame({
'X': [1.1, 2.2, 3.3],
'Y': [4.4, 5.5, 6.6]
})
print("\nオリジナルDataFrame (applymap用):\n", df_elem)
# 各要素を整数に変換
df_elem_int = df_elem.applymap(lambda x: int(x))
print("\napplymapで各要素を整数に変換したDataFrame:\n", df_elem_int)
解説:
lambda x: int(x)という匿名関数が、DataFramedf_elemのすべての要素に適用され、浮動小数点数が整数に変換されています。
どのメソッドを選ぶべきか?使い分けのポイント
| メソッド | 適用範囲 | 主な用途 | 注意点 |
map |
Seriesの各要素 | – 各要素の変換<br>- 辞書やSeriesでの値のマッピング | DataFrameには直接適用できない |
apply |
Series全体 or DataFrameの行/列全体 | – 行/列ごとの集計(合計、平均など)<br>- 行/列全体を使った複雑な条件処理 | 各要素への適用はapplymapの方が明確な場合がある |
applymap |
DataFrameの各要素 | – DataFrame全体の要素単位の変換(データ型変換、フォーマット変更など) | Seriesには直接適用できない<br>Pythonのループに近い処理になるため、大規模データでは速度に注意 |
💡 ヒント:
-
Seriesの個々の要素を変換するなら
map。 -
DataFrameの全ての個々の要素を変換するなら
applymap。 -
DataFrameの行または列全体を一つの単位として処理するなら
apply。
まとめ
Pandasのmap、apply、applymapメソッドは、データ操作を効率化するための強力なツールです。それぞれの適用範囲と特性を理解し、適切に使い分けることで、よりクリーンでパフォーマンスの高いコードを書くことができます。データクレンジング、特徴量エンジニアリング、集計など、様々なデータ分析の場面でこれらのメソッドをぜひ活用してみてください。


