【Python初心者でも分かる】データサイエンティスト協会の100本ノック|新たなデータフレームの作成

スポンサーリンク
Python
ゼロ知識の初心者がデータサイエンスを完全無料で学習する方法5選
データサイエンスの知識や技術、またはPythonについて学びたい。でも「大学に行くほど本気度がない」、「スクールに行くほどお金がない」、なんせ「時間がない」という方も多いはずです。というよりほとんどの方がそうだと思います(当然わたし...
初心者に人気のプログラミング言語Pythonは独学可能か?
Pythonは非常に人気のあるプログラミング言語で、まったくの初心者でも独学が可能と言われています。 Pythonはさまざまな目的に使える、汎用性のあるプログラミング言語です。 プログラミングは「独学が難しい」と言われていま...

データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。

今回は40~44本です。内容は主に、「新たなデータフレームを作成する方法」について解説していきます。

Pythonの環境設定は以下の記事を参考にして下さい。

【2021年最新】M1 mac でanacondaをインストールする方法

【2021年最新】WindowsでAnacondaをインストールする方法

  1. 新たなデータフレームを作成する方法
    1. P-040: 全ての店舗と全ての商品を組み合わせると何件のデータとなるか調査したい。店舗(df_store)と商品(df_product)を直積した件数を計算せよ。
    2. P-041: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前日からの売上金額増減を計算せよ。なお、計算結果は10件表示すればよい。
    3. P-042: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、1日前、2日前、3日前のデータを結合せよ。結果は10件表示すればよい。
    4. P-043: レシート明細データフレーム(df_receipt)と顧客データフレーム(df_customer)を結合し、性別(gender)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータフレーム(df_sales_summary)を作成せよ。性別は0が男性、1が女性、9が不明を表すものとする。 ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。
    5. P-044: 前設問で作成した売上サマリデータフレーム(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータフレームから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を’00’、女性を’01’、不明を’99’とする。

新たなデータフレームを作成する方法

まずは、以下からダウンロードして下さい。

GitHubからデータをダウンロードする方法

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本ノックを解説|ソート(順序で整列)

データサイエンティスト協会の100本ノックを解説|グループ分け



コメント

タイトルとURLをコピーしました