【解説】対数化の実装方法 | データサイエンス100本ノック【問61〜62 回答】

【解説】対数化の実装方法 | データサイエンス100本ノック【問61〜62 回答】

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




目次

この記事の対象者



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

・ 対数化についてPythonのコードを書きながら理解したい人



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


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


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


第61問目: 常用対数化

P-061: レシート明細データフレーム(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、合計した売上金額を常用対数化(底=10)して顧客ID、売上金額合計とともに表示せよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。結果は10件表示させれば良い。

常用対数に変換する場合は、numpy.log10を使用します。

常用対数化の方法
1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd

columns = ['product', 'price']
data = [['pen', 200], ['book', 500], ['pen', 120]]
df = pd.DataFrame(data, columns=columns)

np.log10(df['price'])
出力
1
2
3
4
0    2.301030
1 2.698970
2 2.079181
Name: price, dtype: float64

常用対数化の方法が理解できたところで問題を解いていきましょう。

まずはdf_receiptの構造を確認しましょう

1
df_receipt.head(5)
出力
1
2
3
4
5
6
7

sales_ymd sales_epoch store_cd receipt_no receipt_sub_no customer_id product_cd quantity amount
0 20181103 1541203200 S14006 112 1 CS006214000001 P070305012 1 158
1 20181118 1542499200 S13008 1132 2 CS008415000097 P070701017 1 81
2 20170712 1499817600 S14028 1102 1 CS028414000014 P060101005 1 170
3 20190205 1549324800 S14042 1132 1 ZZ000000000000 P050301001 1 25
4 20180821 1534809600 S14025 1102 2 CS025415000050 P060102007 1 90

問題文より、df_receiptの売上金額(amount)を顧客ID(customer_id)毎に合計値を算出します。この際、顧客IDが”Z”で始まるものを除外しておきます。

>> 検索結果に対するサブクエリとgroupbyメソッドを復習する

1
2
df_sales_amount = df_receipt.query('not customer_id.str.startswith("Z")', engine='python').groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_sales_amount
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	customer_id	amount
0 CS001113000004 1298
1 CS001114000005 626
2 CS001115000010 3044
3 CS001205000004 1988
4 CS001205000006 3337
... ... ...
8301 CS051212000001 336
8302 CS051513000004 551
8303 CS051515000002 265
8304 CS052212000002 192
8305 CS052514000001 178
8306 rows × 2 columns

売上金額(amount)を常用対数に変換し、amount_log10というカラムに代入します。

1
2
df_sales_amount['amount_log10'] = np.log10(df_sales_amount['amount'])
df_sales_amount.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
customer_id	amount	amount_log10
0 CS001113000004 1298 3.113275
1 CS001114000005 626 2.796574
2 CS001115000010 3044 3.483445
3 CS001205000004 1988 3.298416
4 CS001205000006 3337 3.523356
5 CS001211000025 456 2.658965
6 CS001212000027 448 2.651278
7 CS001212000031 296 2.471292
8 CS001212000046 228 2.357935
9 CS001212000070 456 2.658965

これで完了ではありますが、常用対数化には注意点が必要です。

それは常用対数化するデータの中に0が含まれている場合の対応です。

常用対数化する際に$log_{10} (0)$は計算できないのです。高校数学で学ぶ真数条件というものですね。

これに対処するために、一般的には1を加える対応を行います。なぜ1なのかという理由は特に存在しないようです。

真数条件よりデータに1を加える
1
2
df_sales_amount['amount_log10'] = np.log10(df_sales_amount['amount']+1)
df_sales_amount.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	amount	amount_log10
0 CS001113000004 1298 3.113609
1 CS001114000005 626 2.797268
2 CS001115000010 3044 3.483587
3 CS001205000004 1988 3.298635
4 CS001205000006 3337 3.523486
5 CS001211000025 456 2.659916
6 CS001212000027 448 2.652246
7 CS001212000031 296 2.472756
8 CS001212000046 228 2.359835
9 CS001212000070 456 2.659916

これで完成です。

第62問目: 自然対数化

P-062: レシート明細データフレーム(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、合計した売上金額を自然対数化(底=e)して顧客ID、売上金額合計とともに表示せよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。結果は10件表示させれば良い。

自然対数に変換するには、numpy.logを使用すれば可能です。

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd

columns = ['product', 'price']
data = [['pen', 200], ['book', 500], ['pen', 120], ['book', 500], ['book', 0]]
df = pd.DataFrame(data, columns=columns)

np.log(df['price'])
出力
1
2
3
4
5
6
0    5.298317
1 6.214608
2 4.787492
3 6.214608
4 -inf
Name: price, dtype: float64

自然対数の場合も、データに0が含まれる場合は、変換できるように+1をします

では問題を解いていきます。

前門と同様に売上金額を顧客IDごとに合計したデータを算出します。

1
2
df_sales_amount = df_receipt.query('not customer_id.str.startswith("Z")', engine='python').groupby('customer_id').agg({'amount': 'sum'}).reset_index()
df_sales_amount
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	customer_id	amount
0 CS001113000004 1298
1 CS001114000005 626
2 CS001115000010 3044
3 CS001205000004 1988
4 CS001205000006 3337
... ... ...
8301 CS051212000001 336
8302 CS051513000004 551
8303 CS051515000002 265
8304 CS052212000002 192
8305 CS052514000001 178
8306 rows × 2 columns

売上金額を自然対数に変換し、amount_logeという新たなカラムに代入します。

1
2
df_sales_amount['amount_loge'] = np.log(df_sales_amount['amount']+1)
df_sales_amount.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	amount	amount_loge
0 CS001113000004 1298 7.169350
1 CS001114000005 626 6.440947
2 CS001115000010 3044 8.021256
3 CS001205000004 1988 7.595387
4 CS001205000006 3337 8.113127
5 CS001211000025 456 6.124683
6 CS001212000027 448 6.107023
7 CS001212000031 296 5.693732
8 CS001212000046 228 5.433722
9 CS001212000070 456 6.124683

これで完成です。

まとめ: 対数化を学びました。

本記事は、「【解説】対数化の実装方法 | データサイエンス100本ノック【問61〜62 回答】」というテーマでまとめました。

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

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

>> [続き]第63〜65問の回答・解説を確認する

コメント