これはデータサイエンティストの卵がわけもわからないまま100本ノックを行っていく奮闘録である。
完走できるか謎。途中で消えてもQiitaにあげてないだけと思ってください。
ネタバレも含みますのでやろうとされている方は注意
悲報:問題が進まない(執筆時41本目)
コレは見づらい!この書き方は危険!等ありましたら教えていただきたいです。心にダメージを負いながら糧とさせていただきます。
この解き方は間違っている!この解釈の仕方は違う!等もありましたらコメントください。
今回は36~40まで。
[前回]33~35
[目次付き初回]
#36本目
P-036: レシート明細データフレーム(df_receipt)と店舗データフレーム(df_store)を内部結合し、レシート明細データフレームの全項目と店舗データフレームの店舗名(store_name)を10件表示させよ。
ついに来ました表の結合
SQL的に言うと
SELECT *
FROM receipt r INNER JOIN store s
ON r.___ = s.___
といったところでしょうか。(射影は無視)
pandasだと(参考)
pd.maerge(df_receipt,df_store,on='store_cd',how='inner')
となるらしいので
df=pd.merge(df_receipt,df_store[['store_cd','store_name']],on='store_cd',how='inner')
df.head(10)
'''模範解答'''
pd.merge(df_receipt, df_store[['store_cd','store_name']], how='inner', on='store_cd').head(10)
#37本目
P-037: 商品データフレーム(df_product)とカテゴリデータフレーム(df_category)を内部結合し、商品データフレームの全項目とカテゴリデータフレームの小区分名(category_small_name)を10件表示させよ。
df=pd.merge(df_product,df_category[['category_major_cd', 'category_medium_cd','category_small_cd','category_small_name']]
,on=['category_major_cd', 'category_medium_cd','category_small_cd'],how='inner')
df.head(10)
'''模範解答'''
pd.merge(df_product
, df_category[['category_major_cd', 'category_medium_cd','category_small_cd','category_small_name']]
, how='inner', on=['category_major_cd', 'category_medium_cd','category_small_cd']).head(10)
まぁ、これは、ね。
#38本目
P-038: 顧客データフレーム(df_customer)とレシート明細データフレーム(df_receipt)から、各顧客ごとの売上金額合計を求めよ。ただし、買い物の実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが'Z'から始まるもの)は除外すること。なお、結果は10件だけ表示させれば良い。
先頭「Z」を消すのは慣れてきました。
今回行うのは左外部結合をしてNull(Nan)値を0にするということ。
Nanを0にするには.fillna(0)
を使えばOK
df_cst=df_customer[df_customer.customer_id.str.contains('^[^Z]')].query("gender_cd == '1'")
df_rct=df_receipt.groupby('customer_id').agg({'amount':'sum'}).reset_index()
df=pd.merge(df_cst,df_rct,on='customer_id',how='left').fillna(0)
df.head(10)
'''模範解答'''
df_amount_sum = df_receipt.groupby('customer_id').amount.sum().reset_index()
df_tmp = df_customer.query('gender_cd == "1" and not customer_id.str.startswith("Z")', engine='python')
pd.merge(df_tmp['customer_id'], df_amount_sum, how='left', on='customer_id').fillna(0).head(10)
模範解答では計算してから選択(Z始まり除外と女性)していますが、自分は先に選択をしてから計算してます。
#39本目
P-039: レシート明細データフレーム(df_receipt)から売上日数の多い顧客の上位20件と、売上金額合計の多い顧客の上位20件を抽出し、完全外部結合せよ。ただし、非会員(顧客IDが'Z'から始まるもの)は除外すること。
この問題、完全に間違えて時間かかりました。
最初、
df=df_receipt[df_receipt.customer_id.str.contains('^[^Z]')]
df_day=df.groupby('customer_id').agg({'sales_ymd':'count'}).sort_values('sales_ymd',ascending=False).reset_index().head(20)
df_amo=df_amo.groupby('customer_id').agg({'amount':'sum'}).sort_values('amount',ascending=False).reset_index().head(20)
pd.merge(df_amo,df_day,on='customer_id',how='outer')
このように書いて自信満々で答え合わせしました。
内容としては
-
df_day
に売上日数の多い顧客、上位20件 -
df_amo
に売上金額合計の多い顧客、上位20件
のつもりでした。
しかし、df_receipt
には
- 「同じ人が」「同じ日に」「違うものを」
買ったデータもあることを失念していて、これを一つの行をしてまとめないといけませんでした。
なので、(参考)重複した行を削除する
df_day=df[~df.duplicated(subset=['customer_id', 'sales_ymd'])]
を追加し
df=df_receipt[df_receipt.customer_id.str.contains('^[^Z]')]
df_day=df[~df.duplicated(subset=['customer_id', 'sales_ymd'])]
df_day=df_day.groupby('customer_id').agg({'sales_ymd':'count'}).sort_values('sales_ymd',ascending=False).reset_index().head(20)
df_amo=df_amo.groupby('customer_id').agg({'amount':'sum'}).sort_values('amount',ascending=False).reset_index().head(20)
pd.merge(df_amo,df_day,on='customer_id',how='outer')
'''模範解答'''
df_sum = df_receipt.groupby('customer_id').amount.sum().reset_index()
df_sum = df_sum.query('not customer_id.str.startswith("Z")', engine='python')
df_sum = df_sum.sort_values('amount', ascending=False).head(20)
df_cnt = df_receipt[~df_receipt.duplicated(subset=['customer_id', 'sales_ymd'])]
df_cnt = df_cnt.query('not customer_id.str.startswith("Z")', engine='python')
df_cnt = df_cnt.groupby('customer_id').sales_ymd.count().reset_index()
df_cnt = df_cnt.sort_values('sales_ymd', ascending=False).head(20)
pd.merge(df_sum, df_cnt, how='outer', on='customer_id')
と、なりました。(やった。模範解答より短くなった)
#40本目
P-040: 全ての店舗と全ての商品を組み合わせると何件のデータとなるか調査したい。店舗(df_store)と商品(df_product)を直積した件数を計算せよ。
len(df_store)*len(df_product)
え、ダメ?
```模範解答```
df_store_tmp = df_store.copy()
df_product_tmp = df_product.copy()
df_store_tmp['key'] = 0
df_product_tmp['key'] = 0
len(pd.merge(df_store_tmp, df_product_tmp, how='outer', on='key'))
#今回はここまで