

データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。
今回は40~44本です。内容は主に、「新たなデータフレームを作成する方法」について解説していきます。
Pythonの環境設定は以下の記事を参考にして下さい。
【2021年最新】M1 mac でanacondaをインストールする方法
【2021年最新】WindowsでAnacondaをインストールする方法
- 新たなデータフレームを作成する方法
- P-040: 全ての店舗と全ての商品を組み合わせると何件のデータとなるか調査したい。店舗(df_store)と商品(df_product)を直積した件数を計算せよ。
- P-041: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前日からの売上金額増減を計算せよ。なお、計算結果は10件表示すればよい。
- P-042: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、1日前、2日前、3日前のデータを結合せよ。結果は10件表示すればよい。
- P-043: レシート明細データフレーム(df_receipt)と顧客データフレーム(df_customer)を結合し、性別(gender)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータフレーム(df_sales_summary)を作成せよ。性別は0が男性、1が女性、9が不明を表すものとする。 ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。
- P-044: 前設問で作成した売上サマリデータフレーム(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータフレームから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を’00’、女性を’01’、不明を’99’とする。
新たなデータフレームを作成する方法
まずは、以下からダウンロードして下さい。
P-040: 全ての店舗と全ての商品を組み合わせると何件のデータとなるか調査したい。店舗(df_store)と商品(df_product)を直積した件数を計算せよ。
import pandas as pd df_store = pd.read_csv("store.csv"). # データを読み込む df_product = pd.read_csv("product.csv") # データを読み込む 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"))
出力:531590
上のコードは、①データの読み込み、②データを処理するためのデータのコピー、③2つのデータに同じ変数である「key」を作成し、全て0にする。これは、データの結合に必要な処理です。④結合したデータ数を出力する。ということを実行しています。
コードで詳しくみてみましょう。
この出力結果は、店舗(df_store)と商品(df_product)の組み合わせ数を表しています。なので、店舗と商品数の数をかければ同じ出力結果になります。
unique() は重複のないデータを出力します。len() でデータ数(行数)を出力します。
len(df_product["product_cd"].unique()) * len(df_store["store_cd"].unique())
出力:531590
P-041: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前日からの売上金額増減を計算せよ。なお、計算結果は10件表示すればよい。
df_receipt = pd.read_csv("receipt.csv") df_41 = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').sum().reset_index() df_41 = pd.concat([df_41, df_41.shift()], axis=1) df_41.columns = ['sales_ymd','amount','lag_ymd','lag_amount'] df_41['diff_amount'] = df_41['amount'] - df_41['lag_amount'] df_41.head(10)
shift() は一行下にずらします。ずらしてからデータを引くことで、その差を出すことができます。
P-042: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、1日前、2日前、3日前のデータを結合せよ。結果は10件表示すればよい。
# コード例1:縦持ちケース df_42 = df_receipt[["sales_ymd","amount"]].groupby("sales_ymd").sum().reset_index() for i in range(1, 4): if i == 1: df_lag = pd.concat([df_42,df_42.shift(i)],axis=1) else: df_lag = df_lag.append(pd.concat([df_42, df_42.shift(i)],axis=1)) df_lag.columns = ["sales_ymd","amount", "lag_ymd","lag_amount"] df_lag.dropna().sort_values(["sales_ymd","lag_ymd"]).head(10)
出力:
これは、縦持ちの場合のコードです。
縦持ちとは、出力結果からも分かるように、「sales_ymd」が縦に並ぶようにすることです。
20170101のデータは最初のデータなので、1つずらすだけです。
20170102のデータは、1つ前のデータである 20170101からの差を1つ「lag_amount」として出力しています。
20170103のデータは、20170101と 20170102からの差を2つ「lag_amount」として出力します。
このように縦に並べています。縦持ちのデータは縦に長くなるので、ロングフォーマットとも呼ばれます。
# コード例2:横持ちケース df_42 = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').sum().reset_index() for i in range(1, 4): if i == 1: df_lag = pd.concat([df_42, df_42.shift(i)],axis=1) else: df_lag = pd.concat([df_lag, df_42.shift(i)],axis=1) df_lag.columns = ['sales_ymd', 'amount', 'lag_ymd_1', 'lag_amount_1', 'lag_ymd_2', 'lag_amount_2', 'lag_ymd_3', 'lag_amount_3'] df_lag.dropna().sort_values(['sales_ymd']).head(10)
これは、横持ちのデータです。
縦にデータを積み重ねていくのではなく、横にデータを積み重ねていきます。
横持ちのデータは横に長くなるので、ワイドフォーマットとも呼ばれます。
P-043: レシート明細データフレーム(df_receipt)と顧客データフレーム(df_customer)を結合し、性別(gender)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータフレーム(df_sales_summary)を作成せよ。性別は0が男性、1が女性、9が不明を表すものとする。 ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。
import math df_customer = pd.read_csv("customer.csv") df_43 = pd.merge(df_receipt,df_customer,how="inner",on="customer_id") df_43["era"] = df_43["age"].apply(lambda x: math.floor(x/10)*10) df_sales_summary = pd.pivot_table(df_43, index="era", columns="gender_cd", values="amount", aggfunc="sum").reset_index() df_sales_summary.columns = ["era","male","female","unknown"] df_sales_summary
上の図で、コードの大まかな説明をして居ます。
設問が複雑になり、コードの理解が追いつかない場合は、コードを1つ1つ実行して、何をしているかを確認することが必要です。
コードごとの解説を詳しくみてみましょう。
あとは、データの配置を変換します。これをピボットテーブルを呼びます。
エクセルにあるピボットテーブルと同じですね。
コードをみてみましょう。
コードの枠色と出力結果の枠色が対応するようにしています。
なんとなく分かるかと思います。
P-044: 前設問で作成した売上サマリデータフレーム(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータフレームから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を’00’、女性を’01’、不明を’99’とする。
df_sales_summary.set_index("era").stack().\ reset_index().replace({"female":"01", "male":"00", "unknown":"99"}).rename(columns={"level_1":"gender_cd", 0: "amount"})
答えは、上のコードを出力結果です。
これも、1つ1つコードを確認してみましょう。
データサイエンティスト協会の100本ノックを解説|ダウンロードから読み込みまで
データサイエンティスト協会の100本ノックを解説|データの抽出
データサイエンティスト協会の100本ノックを解説|変数の一部を使ってデータを抽出する
データサイエンティスト協会の100本ノックを解説|ソート(順序で整列)
コメント