4 minutes
データサイエンス100本ノックをPythonでやってみた [31-40]
データサイエンス 100 本ノックとは
The-Japan-DataScientist-Society/100knocks-preprocess: データサイエンス 100 本ノック(構造化データ加工編)
Google Colab で データサイエンス 100 本ノックをするにあたって
以下の ipynb ファイルを使用させていただきました。
実行ファイル
データサイエンス 100 本ノック by tomowarkar
031
P-031: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標本標準偏差を計算し、降順で TOP5 を表示せよ。
df_receipt.groupby("store_cd")\
.agg(sample_std=("amount", lambda x: x.std(ddof=0)))\
.sort_values("sample_std", ascending=False).head(5)
sample_std
store_cd
S13052 663.391816
S14011 553.456916
S14034 544.903736
S13001 543.536561
S13015 543.409938
032
P-032: レシート明細データフレーム(df_receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。
pandas.Series.quantile
を使います。
df_receipt.amount.quantile([i/100 for i in range(0, 101, 25)])
0.00 10.0
0.25 102.0
0.50 170.0
0.75 288.0
1.00 10925.0
Name: amount, dtype: float64
033
P-033: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330 以上のものを抽出せよ。
df_receipt.groupby("store_cd")\
.agg(mean_amount=("amount", "mean"))\
.query("mean_amount >= 330")
mean_amount
store_cd
S12013 330.194130
S13001 348.470386
S13003 350.915519
S13004 330.943949
S13015 351.111960
S13019 330.208616
S13020 337.879932
S13052 402.867470
S14010 348.791262
S14011 335.718333
S14026 332.340588
S14045 330.082073
S14047 330.077073
034
P-034: レシート明細データフレーム(df_receipt)に対し、顧客 ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客 ID が"Z"から始まるのものは非会員を表すため、除外して計算すること。
df_receipt[~df_receipt.customer_id.str.startswith("Z")]\
.groupby("customer_id").amount.sum().mean() #> 2547.742234529256
035
P-035: レシート明細データフレーム(df_receipt)に対し、顧客 ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出せよ。ただし、顧客 ID が"Z"から始まるのものは非会員を表すため、除外して計算すること。なお、データは 10 件だけ表示させれば良い。
mean_amount = df_receipt[~df_receipt.customer_id.str.startswith("Z")]\
.groupby("customer_id").amount.sum().mean()
df_receipt[~df_receipt.customer_id.str.startswith("Z")]\
.groupby("customer_id")\
.agg({"amount":"sum"})\
.query(f"amount >= {mean_amount}").head(10)
amount
customer_id
CS001115000010 3044
CS001205000006 3337
CS001214000009 4685
CS001214000017 4132
CS001214000052 5639
CS001215000040 3496
CS001304000006 3726
CS001305000005 3485
CS001305000011 4370
CS001315000180 3300
036
P-036: レシート明細データフレーム(df_receipt)と店舗データフレーム(df_store)を内部結合し、レシート明細データフレームの全項目と店舗データフレームの店舗名(store_name)を 10 件表示させよ。
pd.merge(
df_receipt,
df_store[['store_cd','store_name']],
how='inner',
on='store_cd'
).head(10)
sales_ymd sales_epoch store_cd ... quantity amount store_name
0 20181103 1257206400 S14006 ... 1 158 葛が谷店
1 20181116 1258329600 S14006 ... 1 48 葛が谷店
2 20170118 1200614400 S14006 ... 1 220 葛が谷店
3 20190524 1274659200 S14006 ... 1 80 葛が谷店
4 20190419 1271635200 S14006 ... 1 148 葛が谷店
5 20181119 1258588800 S14006 ... 1 88 葛が谷店
6 20171211 1228953600 S14006 ... 1 80 葛が谷店
7 20191021 1287619200 S14006 ... 1 405 葛が谷店
8 20170710 1215648000 S14006 ... 1 330 葛が谷店
9 20190805 1280966400 S14006 ... 1 115 葛が谷店
[10 rows x 10 columns]
037
P-037: 商品データフレーム(df_product)とカテゴリデータフレーム(df_category)を内部結合し、商品データフレームの全項目とカテゴリデータフレームの小区分名(category_small_name)を 10 件表示させよ。
pd.merge(
df_product,
df_category[['category_small_cd','category_small_name']],
how='inner',
on='category_small_cd'
).head(10)
product_cd category_major_cd ... unit_cost category_small_name
0 P040101001 4 ... 149.0 弁当類
1 P040101002 4 ... 164.0 弁当類
2 P040101003 4 ... 173.0 弁当類
3 P040101004 4 ... 186.0 弁当類
4 P040101005 4 ... 201.0 弁当類
5 P040101006 4 ... 224.0 弁当類
6 P040101007 4 ... 254.0 弁当類
7 P040101008 4 ... 315.0 弁当類
8 P040101009 4 ... 374.0 弁当類
9 P040101010 4 ... 435.0 弁当類
[10 rows x 7 columns]
別解
tmp = list(set(df_product.columns) & set(df_category.columns))
pd.merge(df_product, df_category[tmp+['category_small_name']], how='inner', on=tmp).head(10)
038
P-038: 顧客データフレーム(df_customer)とレシート明細データフレーム(df_receipt)から、各顧客ごとの売上金額合計を求めよ。ただし、買い物の実績がない顧客については売上金額を 0 として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客 ID が’Z'から始まるもの)は除外すること。なお、結果は 10 件だけ表示させれば良い。
pd.merge(
df_customer[(~df_customer.customer_id.str.startswith("Z")) & (df_customer.gender_cd == 1)].customer_id,
df_receipt.groupby("customer_id").agg({"amount": "sum"}),
how='left',
on='customer_id'
).fillna(0).head(10)
customer_id amount
0 CS021313000114 0.0
1 CS031415000172 5088.0
2 CS028811000001 0.0
3 CS001215000145 875.0
4 CS015414000103 3122.0
5 CS033513000180 868.0
6 CS035614000014 0.0
7 CS011215000048 3444.0
8 CS009413000079 0.0
9 CS040412000191 210.0
039
P-039: レシート明細データフレーム(df_receipt)から売上日数の多い顧客の上位 20 件と、売上金額合計の多い顧客の上位 20 件を抽出し、完全外部結合せよ。ただし、非会員(顧客 ID が’Z'から始まるもの)は除外すること。
group = df_receipt[(~df_receipt.customer_id.str.startswith("Z"))].groupby("customer_id")
pd.merge(
group.agg({"amount":"sum"}).query('amount.rank(ascending=False, method="first") <= 20', engine="python"),
group.agg({"sales_ymd":"nunique"}).query('sales_ymd.rank(ascending=False, method="first") <= 20', engine="python"),
how='outer',
on='customer_id'
)
amount sales_ymd
customer_id
CS001605000009 18925.0 NaN
CS006515000023 18372.0 NaN
CS007514000094 15735.0 NaN
CS009414000059 15492.0 NaN
CS010214000010 18585.0 22.0
CS011414000106 18338.0 NaN
CS011415000006 16094.0 NaN
CS015415000185 20153.0 22.0
CS015515000034 15300.0 NaN
CS016415000101 16348.0 NaN
CS016415000141 18372.0 20.0
CS017415000097 23086.0 20.0
CS021515000089 17580.0 NaN
CS028415000007 19127.0 21.0
CS030415000034 15468.0 NaN
CS031414000051 19202.0 19.0
CS032414000072 16563.0 NaN
CS034415000047 16083.0 NaN
CS035414000024 17615.0 NaN
CS038415000104 17847.0 NaN
CS007515000107 NaN 18.0
CS010214000002 NaN 21.0
CS014214000023 NaN 19.0
CS014415000077 NaN 18.0
CS021514000045 NaN 19.0
CS021515000056 NaN 18.0
CS021515000172 NaN 19.0
CS021515000211 NaN 18.0
CS022515000028 NaN 18.0
CS022515000226 NaN 19.0
CS030214000008 NaN 18.0
CS031414000073 NaN 18.0
CS039414000052 NaN 19.0
CS040214000008 NaN 23.0
別解
こっちのがシュッとしている
df_receipt[(~df_receipt.customer_id.str.startswith("Z"))]\
.groupby("customer_id")\
.agg({"amount":"sum", "sales_ymd":"nunique"})\
.query('amount.rank(ascending=False, method="first") <= 20 | sales_ymd.rank(ascending=False, method="first") <= 20', engine="python"
)
amount sales_ymd
customer_id
CS001605000009 18925 9
CS006515000023 18372 15
CS007514000094 15735 13
CS007515000107 11188 18
CS009414000059 15492 17
CS010214000002 13120 21
CS010214000010 18585 22
CS011414000106 18338 16
CS011415000006 16094 11
CS014214000023 8405 19
CS014415000077 14076 18
CS015415000185 20153 22
CS015515000034 15300 7
CS016415000101 16348 12
CS016415000141 18372 20
CS017415000097 23086 20
CS021514000045 9741 19
CS021515000056 12036 18
CS021515000089 17580 12
CS021515000172 13974 19
CS021515000211 10148 18
CS022515000028 13512 18
CS022515000226 8556 19
CS028415000007 19127 21
CS030214000008 10357 18
CS030415000034 15468 13
CS031414000051 19202 19
CS031414000073 9317 18
CS032414000072 16563 13
CS034415000047 16083 14
CS035414000024 17615 11
CS038415000104 17847 14
CS039414000052 11438 19
CS040214000008 13523 23
040
P-040: 全ての店舗と全ての商品を組み合わせると何件のデータとなるか調査したい。店舗(df_store)と商品(df_product)を直積した件数を計算せよ。
len(set(df_store.store_cd)) * len(set(df_product.product_cd)) #>531590
別解
from itertools import product
pd.DataFrame(
product(df_store.store_cd, df_product.product_cd),
columns=['store_cd', 'product_cd']
)