データサイエンス 100 本ノックとは

The-Japan-DataScientist-Society/100knocks-preprocess: データサイエンス 100 本ノック(構造化データ加工編)

Google Colab で データサイエンス 100 本ノックをするにあたって

以下の ipynb ファイルを使用させていただきました。

noguhiro2002/100knocks-preprocess_ForColab-AzureNotebook: データサイエンス 100 本ノック(構造化データ加工編)For Azure_Notebook/Google_Colabo

実行ファイル

データサイエンス 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']
)