

データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。
今回は69~74本です。内容は主に、データから新たなデータを作成する「時系列データを処理する方法」について解説していきます。
Pythonの環境設定は以下の記事を参考にして下さい。
【2021年最新】M1 mac でanacondaをインストールする方法
【2021年最新】WindowsでAnacondaをインストールする方法
- 時系列データの処理
- P-069: レシート明細データフレーム(df_receipt)と商品データフレーム(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分(category_major_cd)が”07″(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分”07″(瓶詰缶詰)の購入実績がある顧客のみとし、結果は10件表示させればよい。
- P-070: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。
- P-071: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過月数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1ヶ月未満は切り捨てること。
- P-072: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からの経過年数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い。(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1年未満は切り捨てること。
- P-073: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、顧客データフレーム(df_customer)の会員申込日(application_date)からのエポック秒による経過時間を計算し、顧客ID(customer_id)、売上日、会員申込日とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。なお、時間情報は保有していないため各日付は0時0分0秒を表すものとする。
- P-074: レシート明細データフレーム(df_receipt)の売上日(sales_ymd)に対し、当該週の月曜日からの経過日数を計算し、売上日、当該週の月曜日付とともに表示せよ。結果は10件表示させれば良い(なお、sales_ymdは数値でデータを保持している点に注意)。
時系列データの処理
まずは、以下からダウンロードして下さい。
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本ノック|新たなデータフレームの作成
コメント