【問38~問39】データサイエンス100本ノック 解説

※アフィリエイト広告を利用しています。

ファイル

はじめに

問38~問39のコードの説明を初心者や初学者でもわかるような方法でまとめました。

データサイエンス100本ノックのはじめ方は、以下のブログ記事を参考にしてください。

>>【Google Colabはじめ方】データサイエンス100本ノックーデータサイエンティスト協会

問38 顧客データフレーム(df_customer)とレシート明細データフレーム(df_receipt)から、各顧客ごとの売上金額合計を求めよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが”Z”から始まるもの)は除外すること。なお、結果は10件だけ表示させれば良い。

このあたりからやることが増えてきて難しくなってきす。

まず、「各顧客ごと売上金額合計」を求めます。

売上であるamountdf_receiptにありますので、これを各顧客を表すcustomer_idごとに合計を求めます。合計をもとめるにはsum()、そして、インデックスが消えないように、最後に.reset_index()を使用します。

#各顧客ごとの売上金額合計
df_amount_sum = df_receipt.groupby('customer_id').amount.sum().reset_index()

次に、顧客データフレーム(df_customer)から「性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが”Z”から始まるもの)は除外」したものを抽出したデータフレームを作りましょう。

抽出には、query()を使用します。

「性別コード(gender_cd)が女性(1)であるもの」は問4と同じように一致を表す==を使用します。なお、gender_cdはint型です。

そして、「非会員(顧客IDが”Z”から始まるもの)は除外」は問34問35と同様に、‘not customer_id.str.startswith(“Z”)’, engine=’python’とし、これを&で結びます(なお、andにしてもコードは通ります)。

#性別コード(gender_cd)が女性(1)で非会員(顧客IDが"Z"から始まるもの)を除外
df_tmp = df_customer.query('gender_cd ==1 & not customer_id.str.startswith("Z")',engine='python')

最後に、mergeして、「売上実績がない顧客については売上金額を0」として10件表示します。

mergeの仕方ですが、共通カラムcustomer_idを軸に、amountのカラムを左外部結合します。左外部結合するには、how=’left’とします。

また、「売上実績がない顧客については売上金額を0」にするには、欠損値を他の値に置換(穴埋め)するfillna()を使いますので、fillna(0)とします。

#結合して売上実績がない顧客について売上金額を0として表示
pd.merge(df_tmp['customer_id'],df_amount_sum,how='left',on='customer_id').fillna(0).head(10)

なお、今回は欠損値の穴埋めを行い、10件表示するだけなので、ここで終わりですが、fillna()の結果もとのデータフレームに適用するには、inplace=Trueを入力する必要があります。

問39 レシート明細データフレーム(df_receipt)から売上日数の多い顧客の上位20件と、売上金額合計の多い顧客の上位20件を抽出し、完全外部結合せよ。ただし、非会員(顧客IDが”Z”から始まるもの)は除外すること。

① 売上金額合計の多い顧客の上位20件

直近の問題の処理と似ているので、「非会員(顧客IDが”Z”から始まるもの)は除外」した「売上金額合計の多い顧客の上位20件」を抽出したデータフレームを作りましょう。

売上金額合計については、sum()を使用し、これを‘customer_id’ごとに抽出します。

df_sum = df_receipt.groupby('customer_id').amount.sum().reset_index()

次に、非会員(顧客IDが”Z”から始まるもの)の除外には、query()を使用します。

これは、問38でも使用した処理ですね。

df_sum = df_sum.query('not customer_id.str.startswith("Z")',engine='python')

最後に、「売上金額合計の多い顧客」順並び替えるため、sort_values()を使用し、20件格納します。

df_sum = df_sum.sort_values('amount',ascending=False).head(20)

② 売上日数の多い顧客上位20件

「非会員(顧客IDが”Z”から始まるもの)は除外」した「売上日数の多い顧客上位20件」を抽出したデータフレームを作成します。

df_receiptcustomer_id CS006214000001の人をみてみると同じ日付複数のものがあります。

問題文の指示どおり売上日数で抽出するには、同じ日付で複数のものを1回にしなければいけません。

つまり、重複していないデータのみを抽出したデータフレームを作成する必要があります。

これには、重複した行を抽出するduplicated()を使用し、subsetを用いて重複を判定する列を指定した上で、頭に論理否定演算子である~を使用することで、重複していないデータのみを抽出します。

df_sales_ymd = df_receipt[~df_receipt.duplicated(subset=['customer_id','sales_ymd'])]

次に、売上日数をカウントするので、count()を使用します。

df_sales_ymd = df_sales_ymd.groupby('customer_id').sales_ymd.count().reset_index()

そして、(顧客IDが”Z”から始まるもの)を除外し、売上日数の多い顧客上位20件を抽出します。

df_sales_ymd = df_sales_ymd.query('not customer_id.str.startswith("Z")', engine='python')
df_sales_ymd = df_sales_ymd.sort_values('sales_ymd',ascending=False).head(20)

最後に、外部結合します。外部結合は、how=’outer’とします。

pd.merge(df_sum,df_sales_ymd,how='outer',on='customer_id')

*結果が長いので10件以降は省略

Pythonのコードやライブラリーについて知りたい場合

Pythonデータ分析よく使われている言語です。

この機会にPythonコードの打ち方・ライブラリーについてもっと知りたいと思った方は、以下のブログ記事をご覧ください。

独学でデータ分析をしている方へ

機械学習データサイエンスデータ分析独学で学ぶには、どうしたらよいかをまとめてみましたので、興味がある方はこちらのブログ記事をご覧ください。