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

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

ファイル

はじめに

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

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

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

問42  レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、1日前、2日前、3日前のデータを結合せよ。結果は10件表示すればよい。

df_receipt)の売上金額(amount)を日付(sales_ymdごとに集計するには、groupby( )を使用します。

売上金額(amount)の合計は、amount.sum()で求めます。

df_sales_amount_by_date = df_receipt[['sales_ymd','amount']].groupby('sales_ymd').amount.sum().reset_index()

次は、「各日付のデータに対し、1日前2日前3日前のデータを結合」する必要があります。

結合は、pd.concat()を使用します。アナログな方法としては、1日前2日前3日前のデータフレームをそれぞれ作成してから、それらを一つずつ結合するという方法もあります。

しかし、同じようなコードを複数回書くのは大変なので、今回は繰り返しの構文であるfor文を使用します。

つまり、i1の場合、df_sales_amount_by_date日付を一行ずらしたdf_sales_amount_by_dateを結合します。

それ以外の場合には、日付を一行ずらしたdf_sales_amount_by_date二行、三行シフトしたデータフレームと結合します。

それでは、for文を作っていきます。日付を一行ずつずらしたものを入れるため、iには1,2,3が入ります。

よって、for i in range(1,4)となります。 

次に、もしiなら、df_sales_amount_by_date一行ずらしたdf_sales_amount_by_dateを結合し、i1じゃない場合には、2行ずらしたもの3行ずらしたもの結合するものを作成します。

そのコードが以下です。

for i in range(1,4):
    if i == 1:
        df_lag = pd.concat([df_sales_amount_by_date,df_sales_amount_by_date.shift(i)],axis=1)
    else:
        df_lag = pd.concat([df_lag,df_sales_amount_by_date.shift(i)],axis=1)

これで、1日前2日前3日前のデータが結合できました

カラム名が同じでわかりずらいので、変えます

df_lag.columns = ['sales_ymd','amount','lag_ymd_1', 'lag_amount_1', 'lag_ymd_2', 'lag_amount_2', 'lag_ymd_3', 'lag_amount_3']

最後に、NaNと表示されている欠損値の削除を行い、10件表示します。

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

df_lag.dropna().head(10)

問43 レシート明細データフレーム(df_receipt)と顧客データフレーム(df_customer)を結合し、性別(gender)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータフレーム(df_sales_summary)を作成せよ。性別は0が男性、1が女性、9が不明を表すものとする。ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。

まず、(df_receipt)と顧客データフレーム(df_customer)を結合し、年代のカラムを作成します。

結合には、pd.merge( )結合し、軸とするカラムはcustermer_idです。

df_tmp = pd.merge(df_receipt,df_customer,how='inner',on='customer_id')

そして、この結合したものに、年代(era)のカラムを追加します。

年代(era)の作り方ですが、ageがあるので、これを用いて計算します。

計算式は、age10分の1をかけて、floor関数小数点を切り捨てたあとに、それを10倍します。

例えば、22歳の場合、22×10分の1(小数点以下切り捨て)×10=20となるので、20代と算出できます。

これをlamda式で書くと、以下のようになります。

df_tmp['era'] = df_tmp['age'].apply(lambda x: math.floor(x/10)*10)

今回の最終ゴールである「売上サマリデータフレーム(df_sales_summary)」の項目構成は、年代女性の売上金額男性の売上金額性別不明の売上金額の4項目で、縦に年代横に性別クロス集計です。

ということは、年代があって、のカラムに女性の売上金額男性の売上金額性別不明の売上金額となる表を作成する必要があります。

では、ゴールの表の元となるものを作成するために、pd.pivot_table( )を使用します。

( )内には、(データフレーム, index=行とするカラム, columns=列とするカラム, values=計算対象のカラム, aggfunc=計算方法)が入ります。

df_sales_summary = pd.pivot_table(df_tmp,index='era',columns='gender_cd',values='amount',aggfunc='sum').reset_index()

カラム名を年代女性男性性別不明にして表を完成させます。

df_sales_summary.columns=['era','male','female','unknown']

問44 前設問で作成した売上サマリデータフレーム(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータフレームから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を”00″、女性を”01″、不明を”99″とする。

問43で作成した(df_sales_summary)から性別を縦持ち性別を行で表示)するため、まず、set_index()を用いて、eraインデックスに変換します。

そして、male, female, unknownを、eraごとに行で表示するようにstack()で変換します。

df_sales_summary = df_sales_summary.set_index('era').stack().reset_index()

「性別コードは男性を”00“、女性を”01“、不明を”99“とする」必要があるので、replace()を使用して、male00, female01, unknown99に変更します。

df_sales_summary = df_sales_summary.replace({'male':'00','female':'01','unknown':'99'})

最後に、「年代性別コード売上金額の3項目に変換」する必要があるので、カラム名をera,gender_cd,amountにします。

df_sales_summary.columns = ['era', 'gender_cd', 'amount']

*コード結果の下部は省略

なお、上記作業を一つずつコードを打っていくときにエラーが出る時がありました。

その時には、問43のコードを再度実行させてから、問44のコードを実行するとエラーが消えます

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

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

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

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

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