Pythonでの時系列データの扱い6 〜 データの再サンプリング(ダウンサンプリングとアップサンプリング)

「Pythonでの時系列データの扱い5 〜 タイムスタンプから期間への変換」の続き。

今回は再サンプリングがテーマ。
再サンプリングとは。

・時系列をある頻度から別の頻度に変換すること。
・高い頻度のデータを低い頻度のデータに変換することを「ダウンサンプリング」と言う。
・低い頻度のデータを高い頻度のデータに変換することを「アップサンプリング」と言う。
・pandas.Series.resampleメソッドとpandas.DataFrame.resampleを使用する。

実はこれ、「pandasを使用して複数のzipファイルに格納されているtickデータ(CSVファイル)から1時間足を作成する」で既に実践していた。この時実践していたのはtick(高い頻度のデータ)から1時間足(低い頻度のデータ)を作ることだったので、ダウンサンプリング。

それでは、resampleの簡単な例。
◎ダウンサンプリング
日毎のデータをサンプルデータ用に作成する。

#coding:utf-8
import pandas as pd
import numpy as np

## indexの作成(1日毎)
idx_ = pd.date_range(
    start='1/1/2016',
    periods=100,
    freq='D'
)
print "idx_"
print idx_

## 時系列データの作成
ts = pd.Series(
    np.random.rand(len(idx_)),
    index=idx_
)
print "日毎のデータ"
print ts

## resampleして1日毎のデータから月毎のデータに変換
resampleTs = ts.resample(
    'M',
    how='mean',
    kind='period'
)
print "月毎のデータ"
print resampleTs

実行結果は次。

DatetimeIndex(['2016-01-01', '2016-01-02', '2016-01-03', '2016-01-04',
'2016-01-05', '2016-01-06', '2016-01-07', '2016-01-08',
'2016-01-09', '2016-01-10', '2016-01-11', '2016-01-12',
'2016-01-13', '2016-01-14', '2016-01-15', '2016-01-16',
・・・・・・・・・
日毎のデータ
2016-01-01 0.615831
2016-01-02 0.384943
2016-01-03 0.889771
2016-01-04 0.518139
2016-01-05 0.972221
2016-01-06 0.865543
2016-01-07 0.919368
2016-01-08 0.789843
2016-01-09 0.043300
........
2016-04-04 0.051582
2016-04-05 0.212444
2016-04-06 0.771627
2016-04-07 0.475766
2016-04-08 0.957511
2016-04-09 0.530452

月毎のデータ
2016-01 0.511491
2016-02 0.472638
2016-03 0.489978
2016-04 0.518693
Freq: M, dtype: float64

次に、1分間隔のデータを用意してダウンサンプリングする。

#coding:utf-8
import pandas as pd
import numpy as np

## indexの作成(1分毎)
idx_ = pd.date_range(
    start='1/1/2016',
    periods=288,
    freq='T'
)

## 1分間隔時系列データ
ts = pd.Series(
    np.arange(len(idx_)),
    index=idx_
)
print "1分間隔データ"
print ts

## ダウンサンプリング
print "5分間隔データへ変換"

print "closed='right'"
print ts.resample(
    '5min',
    how='sum',
    closed='right'
)

print "closed='left'"
print ts.resample(
    '5min',
    how='sum',
    closed='left'
)

print "label='left'"
print ts.resample(
    '5min',
    how='sum',
    closed='left',
    label='left'
)

print "label='left'"
print ts.resample(
    '5min',
    how='sum',
    closed='left',
    label='right'
)

実行結果は次。

1分間隔データ
2016-01-01 00:00:00 0
2016-01-01 00:01:00 1
2016-01-01 00:02:00 2
2016-01-01 00:03:00 3
2016-01-01 00:04:00 4
2016-01-01 00:05:00 5
2016-01-01 00:06:00 6
2016-01-01 00:07:00 7
2016-01-01 00:08:00 8
2016-01-01 00:09:00 9
2016-01-01 00:10:00 10
2016-01-01 00:11:00 11
Freq: T, dtype: int32

Backend TkAgg is interactive backend. Turning interactive mode on.
D:/dev_git/pythonDevTools/PythonForDataAnalysis/chap8_matplotlib/timeSeriesPlot3.py:53: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).sum()
closed='right'
5分間隔データへ変換
D:/dev_git/pythonDevTools/PythonForDataAnalysis/chap8_matplotlib/timeSeriesPlot3.py:60: FutureWarning: how in .resample() is deprecated
closed='right'
the new syntax is .resample(...).sum()
2015-12-31 23:55:00 0
closed='left'
2016-01-01 00:00:00 15
2016-01-01 00:05:00 40
2016-01-01 00:10:00 11
Freq: 5T, dtype: int32
closed='left'
D:/dev_git/pythonDevTools/PythonForDataAnalysis/chap8_matplotlib/timeSeriesPlot3.py:68: FutureWarning: how in .resample() is deprecated
2016-01-01 00:00:00 10
the new syntax is .resample(...).sum()
2016-01-01 00:05:00 35
label='left'
2016-01-01 00:10:00 21
D:/dev_git/pythonDevTools/PythonForDataAnalysis/chap8_matplotlib/timeSeriesPlot3.py:76: FutureWarning: how in .resample() is deprecated
Freq: 5T, dtype: int32
the new syntax is .resample(...).sum()
label='left'
label='right'
2016-01-01 00:00:00 10
2016-01-01 00:05:00 35
2016-01-01 00:10:00 21
Freq: 5T, dtype: int32
label='left'
2016-01-01 00:05:00 10
2016-01-01 00:10:00 35
2016-01-01 00:15:00 21
Freq: 5T, dtype: int32

Process finished with exit code 0

幾つか仕様が変更されているようなので、howを使用せずに、.sum()を使用するようにコードも修正。

#coding:utf-8
import pandas as pd
import numpy as np

## indexの作成(1日毎)
idx_ = pd.date_range(
    start='1/1/2016',
    periods=100,
    freq='D'
)
print "idx_"
print idx_

## 時系列データの作成
ts = pd.Series(
    np.random.rand(len(idx_)),
    index=idx_
)
print "日毎のデータ"
print ts

## resampleして1日毎のデータから月毎のデータに変換
resampleTs = ts.resample(
    'M',
    how='mean',
    kind='period'
)
print "月毎のデータ"
print resampleTs

## indexの作成(1分毎)
idx_ = pd.date_range(
    start='1/1/2016',
    periods=12,
    freq='T'
)

## 1分間隔時系列データ
ts = pd.Series(
    np.arange(len(idx_)),
    index=idx_
)
print "1分間隔データ"
print ts

## ダウンサンプリング
print "5分間隔データへ変換"

print "closed='right'"
print ts.resample(
    '5min',
    closed='right'
).sum()

print "closed='left'"
print ts.resample(
    '5min',
    closed='left'
).sum()

print "label='left'"
print ts.resample(
    '5min',
    closed='left',
    label='left'
).sum()

print "label='left'"
print ts.resample(
    '5min',
    closed='left',
    label='right'
).sum()


◎アップサンプリング
これまでと逆のことをする。
つまり、月毎のデータを作成して、日毎のデータに変換する。

#coding:utf-8
import pandas as pd
import numpy as np

## indexの作成(月毎)
idx_ = pd.date_range(
    start='1/1/2016',
    periods=10,
    freq='M'
)
print "idx_"
print idx_

## 時系列データの作成
ts = pd.Series(
    np.random.rand(len(idx_)),
    index=idx_
)
print "月毎のデータ"
print ts

resampleTs = ts.resample(
    'D',
    kind='period'
).sum()
print resampleTs

実行結果は次。
月末にデータが入り、それ以外のデータはNaNとなる。

月毎のデータ
2016-01-31 0.275584
2016-02-29 0.933670
2016-03-31 0.333093
2016-04-30 0.862430
2016-05-31 0.418452
2016-06-30 0.045042
2016-07-31 0.856275
2016-08-31 0.847731
2016-09-30 0.970612
2016-10-31 0.652977
Freq: M, dtype: float64
Backend TkAgg is interactive backend. Turning interactive mode on.
2016-01-31 0.275584
2016-02-01 NaN
2016-02-02 NaN
・・・・・
2016-02-25 NaN
2016-02-26 NaN
2016-02-27 NaN
2016-02-28 NaN
2016-02-29 0.933670
・・・・・
2016-10-28 NaN
2016-10-29 NaN
2016-10-30 NaN
2016-10-31 0.652977

以上。

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理