Python 時系列分析 1,000本ノック
– ノック22: 時系列データの差分処理 –

Python 時系列分析 1,000本ノック– ノック22: 時系列データの差分処理 –

次の Python コードの出力はどれでしょうか?

Python コード:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import pandas as pd
import numpy as np
np.random.seed(10)
dates = pd.date_range(
start='2023-01-01',
periods=12,
freq='M')
data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12))
df = pd.DataFrame(
data,
index=dates,
columns=['A'])
print(df.diff(1))
import pandas as pd import numpy as np np.random.seed(10) dates = pd.date_range( start='2023-01-01', periods=12, freq='M') data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12)) df = pd.DataFrame( data, index=dates, columns=['A']) print(df.diff(1))
import pandas as pd
import numpy as np

np.random.seed(10)
dates = pd.date_range(
    start='2023-01-01', 
    periods=12, 
    freq='M')
data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12))

df = pd.DataFrame(
    data, 
    index=dates, 
    columns=['A'])

print(df.diff(1))

 

回答の選択肢:

(A) 1ヶ月前との差分
(B) 1ヶ月後との差分
(C) 1年前との差分
(D) 1年後との差分

 

出力例:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
A
2023-01-31 NaN
2023-02-28 0.139442
2023-03-31 -2.026607
2023-04-30 1.087836
2023-05-31 -0.192654
2023-06-30 -1.969321
2023-07-31 0.985597
2023-08-31 0.470936
2023-09-30 0.718116
2023-10-31 0.270289
2023-11-30 0.373555
2023-12-31 0.014262
A 2023-01-31 NaN 2023-02-28 0.139442 2023-03-31 -2.026607 2023-04-30 1.087836 2023-05-31 -0.192654 2023-06-30 -1.969321 2023-07-31 0.985597 2023-08-31 0.470936 2023-09-30 0.718116 2023-10-31 0.270289 2023-11-30 0.373555 2023-12-31 0.014262
                   A
2023-01-31       NaN
2023-02-28  0.139442
2023-03-31 -2.026607
2023-04-30  1.087836
2023-05-31 -0.192654
2023-06-30 -1.969321
2023-07-31  0.985597
2023-08-31  0.470936
2023-09-30  0.718116
2023-10-31  0.270289
2023-11-30  0.373555
2023-12-31  0.014262

 

正解:

(A)

 

解説:

このコードは季節トレンドを持つ時系列データを作るもので、その後でデータを差分変換しています。

詳しく説明します。

‘2023-01-01’から始まる月単位の日付範囲を12期間作ります。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
dates = pd.date_range(
start='2023-01-01',
periods=12,
freq='M')
dates = pd.date_range( start='2023-01-01', periods=12, freq='M')
dates = pd.date_range(
    start='2023-01-01', 
    periods=12, 
    freq='M')

 

datesに格納されているデータは次のようになっています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30',
'2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31',
'2023-09-30', '2023-10-31', '2023-11-30', '2023-12-31'],
dtype='datetime64[ns]', freq='M')
DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31', '2023-09-30', '2023-10-31', '2023-11-30', '2023-12-31'], dtype='datetime64[ns]', freq='M')
DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30',
               '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31',
               '2023-09-30', '2023-10-31', '2023-11-30', '2023-12-31'],
              dtype='datetime64[ns]', freq='M')

 

標準正規分布に従うランダムな数値を持つデータセットを作ります。これに、正弦関数を用いて作った季節性のパターンを加えます。これにより、季節トレンドを持つランダムな時系列データが作られます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12))
data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12))
data = np.random.randn(12) + np.sin(np.linspace(0, 3*np.pi, 12))

 

このデータセットを元に、日付範囲をインデックスとしてデータフレームを作ります。列の名前は ‘A’ とされています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
df = pd.DataFrame(
data,
index=dates,
columns=['A'])
df = pd.DataFrame( data, index=dates, columns=['A'])
df = pd.DataFrame(
    data, 
    index=dates, 
    columns=['A'])

 

dfに格納されているデータは次のようになっています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
A
2023-01-31 1.331587
2023-02-28 1.471029
2023-03-31 -0.555579
2023-04-30 0.532257
2023-05-31 0.339603
2023-06-30 -1.629718
2023-07-31 -0.644120
2023-08-31 -0.173184
2023-09-30 0.544932
2023-10-31 0.815221
2023-11-30 1.188776
2023-12-31 1.203037
A 2023-01-31 1.331587 2023-02-28 1.471029 2023-03-31 -0.555579 2023-04-30 0.532257 2023-05-31 0.339603 2023-06-30 -1.629718 2023-07-31 -0.644120 2023-08-31 -0.173184 2023-09-30 0.544932 2023-10-31 0.815221 2023-11-30 1.188776 2023-12-31 1.203037
                   A
2023-01-31  1.331587
2023-02-28  1.471029
2023-03-31 -0.555579
2023-04-30  0.532257
2023-05-31  0.339603
2023-06-30 -1.629718
2023-07-31 -0.644120
2023-08-31 -0.173184
2023-09-30  0.544932
2023-10-31  0.815221
2023-11-30  1.188776
2023-12-31  1.203037

 

`diff(1)`メソッドを使ってデータを1ラグ(1つ前の時点)との差分変換します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
print(df.diff(1))
print(df.diff(1))
print(df.diff(1))

 

差分変換とは、現在の値から1つ前の値を引くことであり、時系列データに対して傾向(trend)や季節性(seasonality)を削除するためによく用いられます。これを使うと、元のデータが線形のトレンドや定常ではない季節パターンを持っていても、得られた差分データは定常性を持つことが期待できます。

これらを行った結果として、元のデータを1次差分変換した結果が表示されます。ただし、最初の値は(差分をとる前の値が存在しないため)NaNとなります。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
A
2023-01-31 NaN
2023-02-28 0.139442
2023-03-31 -2.026607
2023-04-30 1.087836
2023-05-31 -0.192654
2023-06-30 -1.969321
2023-07-31 0.985597
2023-08-31 0.470936
2023-09-30 0.718116
2023-10-31 0.270289
2023-11-30 0.373555
2023-12-31 0.014262
A 2023-01-31 NaN 2023-02-28 0.139442 2023-03-31 -2.026607 2023-04-30 1.087836 2023-05-31 -0.192654 2023-06-30 -1.969321 2023-07-31 0.985597 2023-08-31 0.470936 2023-09-30 0.718116 2023-10-31 0.270289 2023-11-30 0.373555 2023-12-31 0.014262
                   A
2023-01-31       NaN
2023-02-28  0.139442
2023-03-31 -2.026607
2023-04-30  1.087836
2023-05-31 -0.192654
2023-06-30 -1.969321
2023-07-31  0.985597
2023-08-31  0.470936
2023-09-30  0.718116
2023-10-31  0.270289
2023-11-30  0.373555
2023-12-31  0.014262