pandas でデータ操作する時の Tips (後編) です。今回は時系列データの処理を中心に取り上げます。
環境は Python 2.7.11, pandas 0.20.3 です。
今回扱う内容は以下です。
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 となっている関数も含まれているので公式ドキュメントと合わせて活用すると良いと思います。