【Python】pandas でデータ操作 (後編)

pandas でデータ操作する時の Tips (後編) です。今回は時系列データの処理を中心に取り上げます。

環境は Python 2.7.11, pandas 0.20.3 です。

今回扱う内容は以下です。

  1. 一定頻度の日時の取得
  2. 差分系列の取得
  3. 前方/後方へのシフト
  4. リサンプリング
  5. 窓関数の移動
  6. OHLCの計算

1. 一定頻度の日時の取得

pandas.date_range は一定の頻度の DatetimeIndex を返す。DatetimeIndex には 日時の list が含まれる。

date_range を使い時系列データを作る。

In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: np.random.seed(seed=123)

In [4]: rng = pd.date_range('1/1/2018', periods=72, freq='H')

In [5]: len(rng)
Out[5]: 72

In [6]: ts = pd.Series(np.random.randn(len(rng)), index=rng)

In [7]: ts.head()
Out[7]:
2018-01-01 00:00:00   -1.085631
2018-01-01 01:00:00    0.997345
2018-01-01 02:00:00    0.282978
2018-01-01 03:00:00   -1.506295
2018-01-01 04:00:00   -0.578600
Freq: H, dtype: float64

date_range で freq=’WOM-1MON’ を指定すると, periods 週数の間隔で日時を取得できる。また, pandas.DatetimeIndex の weekofyear 属性にアクセスし年間における週数を取得できる。

In [8]: rng = pd.date_range('1/1/2018', periods=4, freq='WOM-1MON')

In [9]: rng.weekofyear
Out[9]: Int64Index([1, 6, 10, 14], dtype='int64')

In [10]: rng
Out[10]: DatetimeIndex(['2018-01-01', '2018-02-05', '2018-03-05', '2018-04-02'], dtype='datetime64[ns]', freq='WOM-1MON')

2. 差分系列の取得

pandas.Series.diff は時系列の差分を計算する。

In [11]: ts.diff(periods=1).head()
Out[11]:
2018-01-01 00:00:00         NaN
2018-01-01 01:00:00    2.082976
2018-01-01 02:00:00   -0.714367
2018-01-01 03:00:00   -1.789273
2018-01-01 04:00:00    0.927694
Freq: H, dtype: float64

pandas.Series.pct_change は時系列の変化率を計算する。

In [12]: ts.pct_change().head()
Out[12]:
2018-01-01 00:00:00         NaN
2018-01-01 01:00:00   -1.918678
2018-01-01 02:00:00   -0.716268
2018-01-01 03:00:00   -6.323001
2018-01-01 04:00:00   -0.615878
Freq: H, dtype: float64

また, 対数差分は ts.apply(lambda x: np.log(x)).diff(periods=1) のようにして得られる。

3. 前方/後方へのシフト

pandas.DataFrame.shift は時系列データを時間的に前方または後方へシフトする。 lag 特徴量を作る時に便利。

In [13]: ts.shift(periods=1).head()
Out[13]:
2018-01-01 00:00:00         NaN
2018-01-01 01:00:00   -1.085631
2018-01-01 02:00:00    0.997345
2018-01-01 03:00:00    0.282978
2018-01-01 04:00:00   -1.506295
Freq: H, dtype: float64

In [14]: ts.shift(periods=-1).head()
Out[14]:
2018-01-01 00:00:00    0.997345
2018-01-01 01:00:00    0.282978
2018-01-01 02:00:00   -1.506295
2018-01-01 03:00:00   -0.578600
2018-01-01 04:00:00    1.651437
Freq: H, dtype: float64

4. リサンプリング

pandas.Series.resample は指定した offset でリサンプリングを行う。 つまり頻度を別の頻度に変換する。resample が返す DatetimeIndexResampler に対して集約関数を適用することで Series が返る。

In [15]: ts.resample('30T').mean().head()
Out[15]:
2018-01-01 00:00:00   -1.085631
2018-01-01 00:30:00         NaN
2018-01-01 01:00:00    0.997345
2018-01-01 01:30:00         NaN
2018-01-01 02:00:00    0.282978
Freq: 30T, dtype: float64

In [16]: ts.resample('12H').first().head()
Out[16]:
2018-01-01 00:00:00   -1.085631
2018-01-01 12:00:00    1.491390
2018-01-02 00:00:00   -1.253881
2018-01-02 12:00:00    0.002846
2018-01-03 00:00:00    0.978736
Freq: 12H, dtype: float64

In [17]: ts.resample('12H').sum().head()
Out[17]:
2018-01-01 00:00:00   -3.468756
2018-01-01 12:00:00    8.225207
2018-01-02 00:00:00   -8.186823
2018-01-02 12:00:00    0.877066
2018-01-03 00:00:00    8.139284
Freq: 12H, dtype: float64

頻度基準となる offset に指定できる文字列は以下。詳細は Time Series / Date functionality 参照。

Alias Description
B business day frequency
C custom business day frequency
D calendar day frequency
W weekly frequency
M month end frequency
SM semi-month end frequency (15th and end of month)
BM business month end frequency
CBM custom business month end frequency
MS month start frequency
SMS semi-month start frequency (1st and 15th)
BMS business month start frequency
CBMS custom business month start frequency
Q quarter end frequency
BQ business quarter end frequency
QS quarter start frequency
BQS business quarter start frequency
A, Y year end frequency
BA, BY business year end frequency
AS, YS year start frequency
BAS, BYS business year start frequency
BH business hour frequency
H hourly frequency
T, min minutely frequency
S secondly frequency
L, ms milliseconds
U, us microseconds
N nanoseconds

5. 窓関数の移動

pandas.Series.rolling は窓関数を移動しながら mean, max, sum などの集約関数を適用する。

In [18]: ts.rolling(window=3).max().head(10)
Out[18]:
2018-01-01 00:00:00         NaN
2018-01-01 01:00:00         NaN
2018-01-01 02:00:00    0.997345
2018-01-01 03:00:00    0.997345
2018-01-01 04:00:00    0.282978
2018-01-01 05:00:00    1.651437
2018-01-01 06:00:00    1.651437
2018-01-01 07:00:00    1.651437
2018-01-01 08:00:00    1.265936
2018-01-01 09:00:00    1.265936
Freq: H, dtype: float64

6. OHLCの計算

pandas.core.resample.Resampler.ohlc は金融時系列でよく使われる OHLC (Open-High-Low-Close) を計算する。

In [19]: ts.resample('12H').ohlc()
Out[19]:
                         open      high       low     close
2018-01-01 00:00:00 -1.085631  1.651437 -2.426679 -0.094709
2018-01-01 12:00:00  1.491390  2.205930 -0.935834  1.175829
2018-01-02 00:00:00 -1.253881  0.927462 -2.798589 -0.173636
2018-01-02 12:00:00  0.002846  2.392365 -1.727669  0.412912
2018-01-03 00:00:00  0.978736  2.238143 -1.294085  1.069393
2018-01-03 12:00:00 -0.772709  1.417299 -1.326265 -0.831155

In [20]: ts.resample('H').ohlc().head()
Out[20]:
                         open      high       low     close
2018-01-01 00:00:00 -1.085631 -1.085631 -1.085631 -1.085631
2018-01-01 01:00:00  0.997345  0.997345  0.997345  0.997345
2018-01-01 02:00:00  0.282978  0.282978  0.282978  0.282978
2018-01-01 03:00:00 -1.506295 -1.506295 -1.506295 -1.506295
2018-01-01 04:00:00 -0.578600 -0.578600 -0.578600 -0.578600

その他. メモリ使用率の取得

pandas.Series.memory_usage, pandas.DataFrame.memory_usage は Series/DataFrame のメモリ使用率 (Byte) を返す。

より詳細な情報は, pandas.DataFrame.info で memory_usage=’deep’ を指定することで得られる。

In [21]: ts.memory_usage()
Out[21]: 3712

In [22]: ts.to_frame().memory_usage()
Out[22]:
Index    3136
0         576
dtype: int64

In [23]: ts.to_frame().info(memory_usage='deep')
<class 'pandas.core.frame.dataframe'="">
DatetimeIndex: 72 entries, 2018-01-01 00:00:00 to 2018-01-03 23:00:00
Freq: H
Data columns (total 1 columns):
0    72 non-null float64
dtypes: float64(1)
memory usage: 3.6 KB

おわりに

前編では欠測値の削除・補完, 重複値の削除など前処理について, 中編では pandas.DataFrame の連結・結合・グループ化について, そして最後の後編では時系列データの処理を中心に紹介しました。

参考にしました『Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理』 (第3版) は実用的な内容で手元に置いておくと便利ですが, 一部 duplicated となっている関数も含まれているので公式ドキュメントと合わせて活用すると良いと思います。