【Python初心者でも分かる】データサイエンティスト協会の100本ノック|時系列データの処理

スポンサーリンク
Python
【初心者必見】プログラミング言語Pythonでできること5選
プログラミング言語の一つであるPythonはコードが理解しやすく、いろんな用途に使える汎用性があります。ですので、全くの初心者にもおすすめしているサイトが多いです。 ここで改めて、Pythonを勉強したい人やデータ分析、AI開発をして...
初心者に人気のプログラミング言語Pythonは独学可能か?
Pythonは非常に人気のあるプログラミング言語で、まったくの初心者でも独学が可能と言われています。 Pythonはさまざまな目的に使える、汎用性のあるプログラミング言語です。 プログラミングは「独学が難しい」と言われていま...

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

今回は69~74本です。内容は主に、データから新たなデータを作成する「時系列データを処理する方法」について解説していきます。

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

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

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

  1. 時系列データの処理
    1. P-069: レシート明細データフレーム(df_receipt)と商品データフレーム(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分(category_major_cd)が”07″(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分”07″(瓶詰缶詰)の購入実績がある顧客のみとし、結果は10件表示させればよい。
    2. P-070: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。
    3. P-071: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過月数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1ヶ月未満は切り捨てること。
    4. P-072: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過年数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い。(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1年未満は切り捨てること。
    5. P-073: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からのエポック秒による経過時間を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。なお、時間情報は保有していないため各日付は0時0分0秒を表すものとする。
    6. P-074: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、当該週の月曜日からの経過日数を計算し、売上日、当該週の月曜日付とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値でデータを保持している点に注意)。

時系列データの処理

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

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

P-069: レシート明細データフレーム(df_receipt)と商品データフレーム(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分(category_major_cd)が”07″(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分”07″(瓶詰缶詰)の購入実績がある顧客のみとし、結果は10件表示させればよい。

この問題は時系列データの処理ではないです。。。

import pandas as pd
df_receipt = pd.read_csv("receipt.csv")
df_product = pd.read_csv("product.csv")

df_69_1 = pd.merge(df_receipt,df_product,how="inner",on="product_cd").\
    groupby("customer_id").amount.sum().reset_index()

df_69_2 = pd.merge(df_receipt,df_product.query("category_major_cd==7"),
                  how="inner",on="product_cd").groupby("customer_id").amount.sum().reset_index()

df_69_3 = pd.merge(df_69_1,df_69_2,how="inner",on="customer_id")
df_69_3["rate_7"] = df_69_3["amount_y"]/df_69_3["amount_x"]

df_69_3.head(10)

出力:

まず、”df_69_1″ を作る。

次に、”df_69_2″ を作る。

最後に、”df_69_1″ と “df_69_2″ を結合させて、”df_69_3″ を作る。

このような流れです。詳しくみてみましょう。まずは、”df_69_1” からです。

“df_69_1” は、顧客ごとの売り上げ合計(amount)を作成します。

“df_69_2” は、カテゴリ大区分(category_major_cd)が “07”(瓶詰缶詰)のみのデータを抽出し、顧客ごとの売り上げ合計(amount)を作成します。

そして、”df_69_1″ と “df_69_2” を下図のように結合させます。

さらに、df_69_3[“amount_x”] / df_69_3[“amount_y”] を計算することで、比率を求めています。その計算結果を “rate_7” という変数としています。

一度にすべてのコードをみると、よく分からなくなるかもしれません。しかし、一つひとつ確認すると、今まで出てきたコードとほとんど同じだと分かります。

P-070: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。

df_customer = pd.read_csv("customer.csv")

df_70 = pd.merge(df_receipt[["customer_id","sales_ymd"]],
                 df_customer[["customer_id","application_date"]],
                 how="inner",on="customer_id")

df_70 = df_70.drop_duplicates() # 重複した行を削除する

df_70["sales_ymd"]=pd.to_datetime(df_70["sales_ymd"],format="%Y%m%d")
df_70["application_date"]=pd.to_datetime(df_70["application_date"],format="%Y%m%d")

df_70["sales_appli"] = df_70["sales_ymd"]-df_70["application_date"]
df_70.head(10)

出力:

日付データに変換する方法はいくつかありますが、こちらのコードが無難だと思います。

どちらも日付データであれば、数値データと同様に足したり、引いたりすることができます。

ちなみに、コードの中ほどにある drop_duplicates() は重複した行データを削除してくれます。そして、duplicates() は重複したデータのみを抽出します。

P-071: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過月数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1ヶ月未満は切り捨てること。

from dateutil.relativedelta import relativedelta

df_71 = pd.merge(df_receipt[["customer_id","sales_ymd"]],
                 df_customer[["customer_id","application_date"]],
                 how="inner",on="customer_id")
df_71 = df_71.drop_duplicates() # 重複した行を削除する
df_71["sales_ymd"]=pd.to_datetime(df_71["sales_ymd"],format="%Y%m%d")
df_71["application_date"]=pd.to_datetime(df_71["application_date"],format="%Y%m%d")

df_71["elapsed_date"] = df_71[["sales_ymd","application_date"]].apply(lambda x: \
                                    relativedelta(x[0],x[1]).years*12+relativedelta(x[0],x[1]).months,axis=1)
df_71.sort_values('customer_id').head(10)

出力:

前半のコードは前問と同じなので解説は省きます。

以下のコードの詳細を解説します。

「lambda」は計算式を指定する方法です。

relativedelta() 内の x[0]が “sales_ymd” で、x[1]が “application_date” です。それらの年のデータを計算するために(years)として、月のデータを計算するために(months)を指定しています。今回は月数が知りたいので、年のデータに12をかけて月のデータにしています。

P-072: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過年数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い。(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1年未満は切り捨てること。

df_72 = pd.merge(df_receipt[["customer_id","sales_ymd"]],
                 df_customer[["customer_id","application_date"]],
                 how="inner",on="customer_id")

df_72 = df_72.drop_duplicates() # 重複した行を削除する

df_72["sales_ymd"]=pd.to_datetime(df_72["sales_ymd"],format="%Y%m%d")
df_72["application_date"]=pd.to_datetime(df_72["application_date"],format="%Y%m%d")
df_72['elapsed_date'] = df_72[['sales_ymd', 'application_date']].apply(lambda x: \
                                    relativedelta(x[0], x[1]).years, axis=1)
df_72.head(10)

出力:

前問とほとんど同じですね。違いは、年データとして表示させることです。

P-073: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からのエポック秒による経過時間を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。なお、時間情報は保有していないため各日付は0時0分0秒を表すものとする。

import numpy as np

df_73 = pd.merge(df_receipt[["customer_id","sales_ymd"]],
                 df_customer[["customer_id","application_date"]],
                 how="inner",on="customer_id")

df_73 = df_73.drop_duplicates() # 重複した行を削除する

df_73["sales_ymd"]=pd.to_datetime(df_73["sales_ymd"],format="%Y%m%d")
df_73["application_date"]=pd.to_datetime(df_73["application_date"],format="%Y%m%d")
df_73['elapsed_date'] = (df_73["sales_ymd"].astype(np.int64)/10**9)- \
                            (df_73["application_date"].astype(np.int64)/10**9)
df_73.head(10)

出力:

エポック秒とは、UNIX時間のこと。
UNIX時間は、1970年1月1日0時0秒からの経過秒数のこと。

なので、数値データと同じように計算することができます。

こうすると、日付データがエポック秒に変換できているのが分かります。astype(np.int64) を付ければ出来ます。

P-074: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、当該週の月曜日からの経過日数を計算し、売上日、当該週の月曜日付とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値でデータを保持している点に注意)。

df_74 = df_receipt[["customer_id","sales_ymd"]]
df_74 = df_74.drop_duplicates()
df_74["sales_ymd"] = pd.to_datetime(df_74["sales_ymd"],format="%Y%m%d")

df_74["monday"] = df_74["sales_ymd"].apply(lambda x: x - relativedelta(days=x.weekday()))
df_74["elapsed_weekday"] = df_74["sales_ymd"] - df_74["monday"]
df_74.head(10)

出力:

曜日を使って日付データを変換することもできます。

もう少し詳しくみてみましょう。

weelday() を使えばその週の月曜日までの日数が分かります。

これを使って、月曜日の日付データや月曜日までの日数を計算していることになります。

データサイエンティスト協会の100本ノックを解説|ダウンロードから読み込みまで

データサイエンティスト協会の100本ノックを解説|データの抽出

データサイエンティスト協会の100本ノックを解説|変数の一部を使ってデータを抽出する

データサイエンティスト協会の100本ノックを解説|ソート(順序で整列)

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

データサイエンティスト協会の100本ノック|新たなデータフレームの作成

データサイエンティスト協会の100本ノック|日付データ

データサイエンティスト協会の100本ノック|特徴量エンジニアリング

データサイエンティスト協会の100本ノック|変数を整える



コメント

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