【解説】map関数とpandas.Seriesのmapメソッドの違いを学ぶ | データサイエンス100本ノック【問54 回答】

【解説】map関数とpandas.Seriesのmapメソッドの違いを学ぶ | データサイエンス100本ノック【問54 回答】

当ページのリンクには広告が含まれています。




目次

この記事の対象者



・ データサイエンティストを目指している人

・ Pythonのmap関数とpandas.Seriexのmapメソッドの違いを知りたい人



以降はデータサイエンス100本ノックの問題も題材にしながら学んでいきます。


データサイエンス100本ノックの始め方は、以下の記事を参考にしていただければと思います。


>>データサイエンス100本ノックの始め方を確認する


そもそも「関数」と「メソッド」の違いとは

pythonを学んできた型ならふと思う「関数とメソッドの違いってなんだ?」という点から掘り下げていきます。

先人の方がきちんと整理してくれていました。

【Python】関数とメソッドの違いを実例でわかりやすく解説

要約すると以下になります。

  • メソッド: 特定のクラスでしか使えない。データ型に紐付いた関数。
    • 例: replaceメソッドはlist(配列)には使えないが、str(文字列)には使える
  • 関数: 幅広いオブジェクトに使える(特定のクラスで縛られない)。単独で呼び出せるもの。
    • 例: print()等

map関数とpandas.Seriesにおけるmapメソッド

それでは本記事の主題であるmapにフォーカスして整理します。

pythonには「map関数」と「mapメソッド」が存在します。

後者のmapメソッドは、pandasのSeries型に適用できるメソッドです。

それぞれ「map関数」と「mapメソッド」に分けて使い方を紹介します。

1. map関数

map関数は、listの各要素に関数を適用する場合に使う関数です。

map関数の使い方
1
2
3
4
5
# イテレータ(計算の方法を格納)を返す 計算は行わない
map(適用したい関数, 配列)

# 計算結果をlist に返す
list(map(関数, 配列))

イテレータとは複数の要素を順番に取り出す機能を持ったクラスを指します。この、要素を順番に取り出す機能を使うことで、forループを用いるよりも実行時間を短くすることができるので、膨大な要素を持つ配列に関数を適用したい場合にはmap()関数を用います。

このmap関数のように他の関数を引数にできる関数を高階関数と言います。

以下に例を示します。例えばa = [1, -2, 3, -4, 5]という配列の各要素の絶対値を得るには、forループと絶対値を算出する関数であるabs()を用いて、以下のように書きます。

forループを用いて記載
1
2
3
4
5
6
a = [1, -2, 3, -4, 5,]
# forループで関数適用
new = []
for x in a:
new.append(abs(x))
new
出力
1
[1, 2, 3, 4, 5]

これをmap()関数を用いると、以下のように簡潔に書くことができます。

map関数を用いて記載
1
2
3
a = [1, -2, 3, -4, 5,]
# mapで関数適用
list(map(abs, a))
出力
1
[1, 2, 3, 4, 5]

このようにlist()関数で囲むことによりmap()関数の適用結果(abs関数を適用した結果)を再度リストに格納することができます。

2. pandas.Seriesのmapメソッド

pandas.Seriesにおけるmapメソッドは、引数に辞書型を指定することも可能です。

その場合、要素の置換になります。

要素の置換は、過去にデータサイエンス100本ノックの第44問目replaceメソッドを使用しました。

しかし、こちらの記事によると、pandas.Seriesまたはpandas.DataFrameの列(=pandas.Series)のすべての要素を別の値に置換する場合、map()のほうが高速になるようです。

pandas.Seriesにおけるmapメソッドの使い方の例を紹介します。

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd

columns = ['都道府県', 'num']
data = [['東京都', 1000], ['大阪府', 700], ['京都府', 500]]
df = pd.DataFrame(data, columns=columns)

print(df['都道府県'].map({'東京都':'0','大阪府':'1','京都府':'2'}))

# >>> 出力結果
# 0 0
# 1 1
# 2 2
# Name: 都道府県, dtype: object

この例を元に、データサイエンス100本ノックの第54問目を解いていきたいと思います。

第54問目: mapメソッドを用いたカテゴリ化

P-054: 顧客データデータフレーム(df_customer)の住所(address)は、埼玉県、千葉県、東京都、神奈川県のいずれかとなっている。都道府県毎にコード値を作成し、顧客ID、住所とともに抽出せよ。値は埼玉県を11、千葉県を12、東京都を13、神奈川県を14とすること。結果は10件表示させれば良い。

まずはdf_customerの構造を確認します。

df_customerの構造を確認
1
df_customer.head(5)
出力
1
2
3
4
5
6
	customer_id	customer_name	gender_cd	gender	birth_day	age	postal_cd	address	application_store_cd	application_date	status_cd
0 CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 0-00000000-0
1 CS037613000071 六角 雅彦 9 不明 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0
2 CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C
3 CS028811000001 堀井 かおり 1 女性 1933-03-27 86 245-0016 神奈川県横浜市泉区和泉町********** S14028 20160115 0-00000000-0
4 CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2

問題文には都道府県毎にコード値を作成し、顧客ID、住所とともに抽出せよ、と記載されているので、df_customerの顧客IDと住所のデータを抽出します。

1
2
df_tmp = df_customer[['customer_id', 'address']]
df_tmp
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
14

customer_id address
0 CS021313000114 神奈川県伊勢原市粟窪**********
1 CS037613000071 東京都江東区南砂**********
2 CS031415000172 東京都渋谷区代々木**********
3 CS028811000001 神奈川県横浜市泉区和泉町**********
4 CS001215000145 東京都大田区仲六郷**********
... ... ...
21966 CS002512000474 東京都国分寺市光町**********
21967 CS029414000065 千葉県浦安市富士見**********
21968 CS012403000043 神奈川県横浜市中区本牧間門**********
21969 CS033512000184 神奈川県横浜市泉区和泉町**********
21970 CS009213000022 東京都世田谷区駒沢**********
21971 rows × 2 columns

次に、都道府県ごとにコード値を作成します。値は、埼玉県を11, 千葉県を12, 東京都を13, 神奈川県を14とします。

このときaddressカラムのstr型データからどのように都道府県の判別をすればよいかがポイントになります。

ここでは先頭の3文字を.str[0:3で抽出し、抽出した文字列がそれぞれ埼玉県, 千葉県, 東京都, 神奈川となっているかどうかで判別していきます。

1
2
df_prefecturecode = df_customer['address'].str[0:3].map({'埼玉県': '11', '千葉県': '12', '東京都': '13', '神奈川':'14'})
df_prefecturecode
出力
1
2
3
4
5
6
7
8
9
10
11
12
0        14
1 13
2 13
3 14
4 13
..
21966 13
21967 12
21968 14
21969 14
21970 13
Name: address, Length: 21971, dtype: object

これで下準備が整いました。

最後に2つのデータフレームを結合し、顧客IDで、住所、そして都道府県ごとのコード値を出力します。

今回結合する2つのデータフレームには共通するカラムは存在しないので、mergeではなくconcatを用いて結合します。

>> concatの使い方を復習する

1
pd.concat([df_tmp, df_prefecturecode], axis=1).head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	address	address
0 CS021313000114 神奈川県伊勢原市粟窪********** 14
1 CS037613000071 東京都江東区南砂********** 13
2 CS031415000172 東京都渋谷区代々木********** 13
3 CS028811000001 神奈川県横浜市泉区和泉町********** 14
4 CS001215000145 東京都大田区仲六郷********** 13
5 CS020401000016 東京都板橋区若木********** 13
6 CS015414000103 東京都江東区北砂********** 13
7 CS029403000008 千葉県浦安市海楽********** 12
8 CS015804000004 東京都江東区北砂********** 13
9 CS033513000180 神奈川県横浜市旭区善部町********** 14

これで完成です。

まとめ: 関数とメソッドの違いとmapを使ったカテゴリ化を学びました。

本記事は、「【Python】map関数とpandas.Seriesのmapメソッドの違いを学ぶ | データサイエンス100本ノック【問54 回答】」というテーマでまとめました。

本記事で紹介した方法を元に、データサイエンティストとしての知見を深めていただければと思います。

なお、データサイエンティストに必要な知識は、TechAcademyのデータサイエンスコースでの学習がおすすめです。

コメント