Slide 1

Slide 1 text

前処理するとき便利だからよく
 pandas.DataFrame.apply(lambda)
 使っちゃうけど遅いから本当は
 pandas.Series.map()
 使った方がいいと思う
 PyData.Fukuoka #6
 LT
 @shinpsan


Slide 2

Slide 2 text

自己紹介
 下積みの父@shinpsan
 小売業のデータサイエンティスト(12月まで。年明け転職します)
 MENSA会員
 合同会社ocojoで副業
 
 twitter : 
 仕事 : 
 特技:
 趣味: 
 


Slide 3

Slide 3 text

話すこと
 タイトルに書いたことが全てです。
 pandasの基本的なところなのでみんな知ってる内容かも。
 
 知ってる方はヒマだと思うので、心の中で
 「シカ」って10回言った後、
 「サンタクロースが乗っているのは?」に答えてて下さい


Slide 4

Slide 4 text

背景
 クソみたいなデータ渡されたと文句言いながら、
 いつもクソみたいなコード書いてることを反省。
 


Slide 5

Slide 5 text

再現データ
 ラベル 営業時間 値1 値2 値3 ● 1ファイルにつき何個か値が格納された ファイルが大量にある ● それを集めてきて1つのテーブルにした もの ● ラベルが元のファイル名

Slide 6

Slide 6 text

やりたいこと(持っていきたい方向)
 店舗の営業時間体系ごとの
 ● 三角おにぎり
 ● パックおにぎり
 ● 寿司
 のラベルをつけて集計とか
 可視化とかいろいろ


Slide 7

Slide 7 text

再現データ
 
 ラベル 営業時間 値1 値2 値3 ● おにぎり、寿司、パックおにぎり 判別はラベルの文字列から可能 ● 営業時間は9~21時 or 24時間営業

Slide 8

Slide 8 text

クソみたいなところ①
 ラベル 営業時間 値1 値2 値3 ラベルの文字列の長さがバラバラ

Slide 9

Slide 9 text

クソみたいなところ②
 ラベル 営業時間 値1 値2 値3 おにぎり、寿司の判別は文字列の先頭 パックおにぎりの判別は文字列の最後

Slide 10

Slide 10 text

クソみたいなところ③
 ラベル 営業時間 値1 値2 値3 ラベルに区切り文字とか入って無い

Slide 11

Slide 11 text

手順1
 ラベル 営業時間 値1 値2 値3 ラベル列の各行に関して、 先頭7文字が”ONIGIRI” かどうか、 先頭5文字が”SUSHI” かどうか、 最後4文字が”pack” かどうか 判別

Slide 12

Slide 12 text

手順2
 ラベル 営業時間 値1 値2 値3 営業時間列の各行に関して、 “9-21” or “24h” 判別

Slide 13

Slide 13 text

手順3
 ラベル 営業時間 値1 値2 値3 手順1,2の判別を元に 新たなラベル列作成 新ラベル おにぎり_9-21 おにぎり_24h ・ ・ ・

Slide 14

Slide 14 text

ここで本題
 どんな処理書く?
 ● for + iterrows()
 ● df.apply()
 ● Series.map()


Slide 15

Slide 15 text

①for i, row in {pd.DataFrame}.iterrow():
 ラベル 営業時間 値1 値2 値3 データフレームの1行1行に対して ループ処理 処理 ↓ 処理 ↓ 処理 ↓ 処理 ↓ 処理 ↓

Slide 16

Slide 16 text

①for i, row in {pd.DataFrame}.iterrow():


Slide 17

Slide 17 text

②{pd.DataFrame}.apply(lambda x: {})
 ラベル 営業時間 値1 値2 値3 データフレームの各行に対して 同じ処理を一括適応 lambda x のxには各行が1行のDFにみたいにして渡される x[“ラベル”]みたいにして使うとこ選べる ✖ 処理 ✖ 処理 ✖ 処理 ✖ 処理 ✖ 処理

Slide 18

Slide 18 text

②{pd.DataFrame}.apply(lambda x: {})


Slide 19

Slide 19 text

③{pd.Series}.map(lambda x: {})
 ラベル ✖ 処理 ✖ 処理 ✖ 処理 ✖ 処理 ✖ 処理 Seriesの各要素に対して 同じ処理を一括適応

Slide 20

Slide 20 text

③{pd.Series}.map(lambda x: {})


Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

実行速度比較 1万行まで
 iterrowsだと1万行のデータで 1~2秒かかる データの行数 処理にかかった時間

Slide 23

Slide 23 text

実行速度比較 10万行まで
 df.apply()だと10万行のデータで ~2秒かかる

Slide 24

Slide 24 text

実行速度比較 1000万行まで
 Series.map()だと1000万行のデータで 約5秒かかる

Slide 25

Slide 25 text

まとめ
 ただの肌感ですが、jupyterで分析してて、
 そこまで気にならない待ち時間は2秒くらい
 ● for + iterrows 1万行
 ● df.apply 10万行
 ● Series.map 400万行
 まぁ、結論としてループは使わない。
 df.apply()は何も考えずに記述できるけど遅いから、
 Series.map()でやる方がいいですね。


Slide 26

Slide 26 text

enjoy!
 答え:そり(トナカイには乗っていない)