当ページのリンクには広告が含まれています。
目次
この記事の対象者
・ データサイエンティストを目指している人
・ Pythonで時系列ずらしの方法を学びたい人
以降はデータサイエンス100本ノックの問題を題材に、時系列ずらしの方法について学んでいきます。
データサイエンス100本ノックの始め方は、以下の記事を参考にしていただければと思います。
>>データサイエンス100本ノックの始め方を確認する
第41問目: データフレームの行ずらし
P-041: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前日からの売上金額増減を計算せよ。なお、計算結果は10件表示すればよい。
まずは、df_receipt
のsales_ymd
列とamount
列のみ抽出し、sales_ymd
でグルーピングすれば良いね。「前日からの売上金額増減の計算」はどうやればいいだろう?
「前日からの売上金額増減の計算」は、与えられたデータフレームの行を1行ずらして差分をとる ことで、前日からの売上金額の増減を計算することができます。
まずは、df_receipt
のsales_ymd
列とamount
列のみ抽出し、sales_ymd
でグルーピングします。
その後に、amount
に対して合計値を計算し、index
を再割り当てましょう。
df_receiptのsales_ymd列とamount列のみ抽出し、sales_ymdでグルーピング 1 2 df_sales_amount_by_date = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').sum().reset_index() df_sales_amount_by_date
出力 1 2 3 4 5 6 7 8 9 10 11 12 13 sales_ymd amount 0 20170101 33723 1 20170102 24165 2 20170103 27503 3 20170104 36165 4 20170105 37830 ... ... ... 1029 20191027 37484 1030 20191028 40161 1031 20191029 36091 1032 20191030 26602 1033 20191031 25216 1034 rows × 2 columns
繰り返しになりますが、この問題に対する方針を整理します。
この問題においては、df_sales_amount_by_date
というデータフレームを1行下にずらしたデータフレームを作成し、両者のデータフレームのamountの差分を取ることで、前日からの売上金額の増減を計算していきたいと思います。
ここで作ったdf_sales_amount_by_date
と、当該データフレームを1行下にシフトしたデータフレームを結合します。
データフレームの行または列をずらすにはshift()
を使用します。
>>pandas.DataFrame.shift
shift()
は、引数に数値を指定することでずらし幅を指定することが出来ます。
引数に数値を指定しなかった場合は、下方向に1行ずれます。行数はそのままなので、最後の行のデータは削除されます。
``df_sales_amount_by_date``と、当該データフレームを1行下にシフトしたデータフレームを結合 1 2 df_sales_amount_by_date = pd.concat([df_sales_amount_by_date, df_sales_amount_by_date.shift()], axis=1) df_sales_amount_by_date
出力 1 2 3 4 5 6 7 8 9 10 11 12 13 sales_ymd amount sales_ymd amount 0 20170101 33723 NaN NaN 1 20170102 24165 20170101.0 33723.0 2 20170103 27503 20170102.0 24165.0 3 20170104 36165 20170103.0 27503.0 4 20170105 37830 20170104.0 36165.0 ... ... ... ... ... 1029 20191027 37484 20191026.0 51771.0 1030 20191028 40161 20191027.0 37484.0 1031 20191029 36091 20191028.0 40161.0 1032 20191030 26602 20191029.0 36091.0 1033 20191031 25216 20191030.0 26602.0 1034 rows × 4 columns
出力されたデータフレームのカラム名を見てみると、sales_ymd
というカラム名とamount
というカラム名が2つずつあり区別できません。
なので、カラム名を1列目から順番にsales_ymd
, amount
, lag_ymd
, lag_amount
に変更しています。
カラム名を変更 1 2 df_sales_amount_by_date.columns = ['sales_ymd', 'amount', 'lag_ymd', 'lag_amount'] df_sales_amount_by_date
出力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 sales_ymd amount lag_ymd lag_amount 0 20170101 33723 NaN NaN 1 20170102 24165 20170101.0 33723.0 2 20170103 27503 20170102.0 24165.0 3 20170104 36165 20170103.0 27503.0 4 20170105 37830 20170104.0 36165.0 ... ... ... ... ... 1029 20191027 37484 20191026.0 51771.0 1030 20191028 40161 20191027.0 37484.0 1031 20191029 36091 20191028.0 40161.0 1032 20191030 26602 20191029.0 36091.0 1033 20191031 25216 20191030.0 26602.0 1034 rows × 4 columns
df_sales_amount_by_date
に新しいカラムdiff_amount
を作成し、amount
列とlag_amount
列の差を取ったデータを追加します。
新しいカラムdiff_amountを作成し、amount列とlag_amount列の差を取ったデータを追加 1 2 df_sales_amount_by_date['diff_amount'] = df_sales_amount_by_date['amount'] - df_sales_amount_by_date['lag_amount'] df_sales_amount_by_date.head(10)
出力 1 2 3 4 5 6 7 8 9 10 11 sales_ymd amount lag_ymd lag_amount diff_amount 0 20170101 33723 NaN NaN NaN 1 20170102 24165 20170101.0 33723.0 -9558.0 2 20170103 27503 20170102.0 24165.0 3338.0 3 20170104 36165 20170103.0 27503.0 8662.0 4 20170105 37830 20170104.0 36165.0 1665.0 5 20170106 32387 20170105.0 37830.0 -5443.0 6 20170107 23415 20170106.0 32387.0 -8972.0 7 20170108 24737 20170107.0 23415.0 1322.0 8 20170109 26718 20170108.0 24737.0 1981.0 9 20170110 20143 20170109.0 26718.0 -6575.0
これで完成です。
第42問目: データフレームの行ずらし(2)
P-042: レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、1日前、2日前、3日前のデータを結合せよ。結果は10件表示すればよい。
まずはdf_receipt
のsales_ymd
列とamount
列のみを抽出し、sales_ymd
をグルーピングします。その後にamount
列に対して合計値を計算し、indexを再割り当てします。 算出方法は以下に示すとおり3パタンあります。どの方法でも構いません。
1 2 3 4 5 6 7 8 9 10 11 12 # パタン1 df_sales_amount_by_date1 = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').sum().reset_index() df_sales_amount_by_date1 # パタン2 df_sales_amount_by_date2 = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').amount.sum().reset_index() df_sales_amount_by_date2 # パタン3 df_sales_amount_by_date3 = df_receipt[['sales_ymd', 'amount']].groupby('sales_ymd').agg({'amount': 'sum'}).reset_index() df_sales_amount_by_date3
出力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 sales_ymd amount 0 20170101 33723 1 20170102 24165 2 20170103 27503 3 20170104 36165 4 20170105 37830 ... ... ... 1029 20191027 37484 1030 20191028 40161 1031 20191029 36091 1032 20191030 26602 1033 20191031 25216 1034 rows × 2 columns
1日前、2日前、3日前のデータを結合させていくことを考えます。
1つずつデータフレームを作成してから結合していってもよいのですが、ここでは少し応用を効かせてfor文を用いて処理を進めます。
i
を1〜3で3回ループさせるようにします。
i
が1
の場合、df_sales_amount_by_date
と1行シフトしたdf_sales_amount_by_date
を結合します。
i!=1
の場合は、df_lag
と2行、3行とシフトしたデータフレームと結合します。
1 2 3 4 5 6 7 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) df_lag
出力 1 2 3 4 5 6 7 8 9 10 11 12 13 sales_ymd amount sales_ymd amount sales_ymd amount sales_ymd amount 0 20170101 33723 NaN NaN NaN NaN NaN NaN 1 20170102 24165 20170101.0 33723.0 NaN NaN NaN NaN 2 20170103 27503 20170102.0 24165.0 20170101.0 33723.0 NaN NaN 3 20170104 36165 20170103.0 27503.0 20170102.0 24165.0 20170101.0 33723.0 4 20170105 37830 20170104.0 36165.0 20170103.0 27503.0 20170102.0 24165.0 ... ... ... ... ... ... ... ... ... 1029 20191027 37484 20191026.0 51771.0 20191025.0 28833.0 20191024.0 31868.0 1030 20191028 40161 20191027.0 37484.0 20191026.0 51771.0 20191025.0 28833.0 1031 20191029 36091 20191028.0 40161.0 20191027.0 37484.0 20191026.0 51771.0 1032 20191030 26602 20191029.0 36091.0 20191028.0 40161.0 20191027.0 37484.0 1033 20191031 25216 20191030.0 26602.0 20191029.0 36091.0 20191028.0 40161.0 1034 rows × 8 columns
すると上記のような新たなデータフレームdf_lag
を得ることができます。
カラム名を見るとamount
という名前のカラムが複数存在します。区別がつかないので、名前を変更します。
列名は1列目から順にsales_ymd
, amount
, lag_ymd_1
, lag_amount_1
, lag_ymd_2
, lag_amount_2
, lag_ymd_3
, lag_amount_3
に変更します。
1 2 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
1 2 3 4 5 6 7 8 9 10 11 12 13 sales_ymd amount lag_ymd_1 lag_amount_1 lag_ymd_2 lag_amount_2 lag_ymd_3 lag_amount_3 0 20170101 33723 NaN NaN NaN NaN NaN NaN 1 20170102 24165 20170101.0 33723.0 NaN NaN NaN NaN 2 20170103 27503 20170102.0 24165.0 20170101.0 33723.0 NaN NaN 3 20170104 36165 20170103.0 27503.0 20170102.0 24165.0 20170101.0 33723.0 4 20170105 37830 20170104.0 36165.0 20170103.0 27503.0 20170102.0 24165.0 ... ... ... ... ... ... ... ... ... 1029 20191027 37484 20191026.0 51771.0 20191025.0 28833.0 20191024.0 31868.0 1030 20191028 40161 20191027.0 37484.0 20191026.0 51771.0 20191025.0 28833.0 1031 20191029 36091 20191028.0 40161.0 20191027.0 37484.0 20191026.0 51771.0 1032 20191030 26602 20191029.0 36091.0 20191028.0 40161.0 20191027.0 37484.0 1033 20191031 25216 20191030.0 26602.0 20191029.0 36091.0 20191028.0 40161.0 1034 rows × 8 columns
処理としては概ね完了かと思いますが、NaN
と表示されている欠損値の削除を行います。
欠損値の削除は、dropna
メソッドを使えばOK。
1 df_lag.dropna().head(10)
出力 1 2 3 4 5 6 7 8 9 10 11 sales_ymd amount lag_ymd_1 lag_amount_1 lag_ymd_2 lag_amount_2 lag_ymd_3 lag_amount_3 3 20170104 36165 20170103.0 27503.0 20170102.0 24165.0 20170101.0 33723.0 4 20170105 37830 20170104.0 36165.0 20170103.0 27503.0 20170102.0 24165.0 5 20170106 32387 20170105.0 37830.0 20170104.0 36165.0 20170103.0 27503.0 6 20170107 23415 20170106.0 32387.0 20170105.0 37830.0 20170104.0 36165.0 7 20170108 24737 20170107.0 23415.0 20170106.0 32387.0 20170105.0 37830.0 8 20170109 26718 20170108.0 24737.0 20170107.0 23415.0 20170106.0 32387.0 9 20170110 20143 20170109.0 26718.0 20170108.0 24737.0 20170107.0 23415.0 10 20170111 24287 20170110.0 20143.0 20170109.0 26718.0 20170108.0 24737.0 11 20170112 23526 20170111.0 24287.0 20170110.0 20143.0 20170109.0 26718.0 12 20170113 28004 20170112.0 23526.0 20170111.0 24287.0 20170110.0 20143.0
リンク
まとめ 本記事は、「【Python】時系列ずらしの方法を学ぶ | データサイエンス100本ノック【問41〜問42 回答】」というテーマでまとめました。
新たに学んだ事項としてはshift
とdropna
かと思います。
>> 続きはこちら
なお、データサイエンティストに必要な知識は、TechAcademyのデータサイエンスコース での学習がおすすめです。