このエントリーをはてなブックマークに追加

Advent Calendar 2013 - 23

Python で解析! - DataFrame 16

今回は Period について。Timestamp が時刻、Period が時間を取り扱う。時間というより、期間の方が語感としては近いかもしれない。

1. Period

だいたいの言語で、日付型や時刻型は用意されているが、期間を表すオブジェクトというのは、珍しい気がする。日付型なり、時刻型なり…を使って、開始日、終了日を自分で管理するのに慣れてしまっているだけかもしれないが…。

# 2013年の期間オブジェクトを作る。
p1 = pd.Period('2013')

p1
Period('2013', 'A-DEC')

p1.start_time
Timestamp('2013-01-01 00:00:00', tz=None)

p1.end_time
Timestamp('2013-12-31 23:59:59.999999999', tz=None)
# 2013年1月の期間オブジェクトを作る。
p2 = pd.Period('2013-01')

p2
Period('2013-01', 'M')

p2.start_time
Timestamp('2013-01-01 00:00:00', tz=None)

p2.end_time
Timestamp('2013-01-31 23:59:59.999999999', tz=None)

日単位や時単位の Period も作れるのだが、文字列をうまくパースしてくれない。リファレンスのサンプルには載っているのだが、やってみるとエラーが表示される。代替として、個別のパラメーターを指定して作成してみることにする。

p3 = pd.Period(year=2013, month=12, day=24, freq='D')

p3
Period('2013-12-24', 'D')

p3.start_time
Timestamp('2013-12-24 00:00:00', tz=None)

p3.end_time
Timestamp('2013-12-24 23:59:59.999999999', tz=None)

時単位の場合。

p4 = pd.Period(year=2013, month=12, day=24, hour=9, freq='H')

p4
Period('2013-12-24 09:00', 'H')

p4.start_time
Timestamp('2013-12-24 09:00:00', tz=None)

p4.end_time
Timestamp('2013-12-24 09:59:59.999999999', tz=None)

Period は、自由な期間 (任意の開始時刻、終了時刻) を表現することはできない。1 時間、1日、ひと月、1四半期などの、用意されている範囲で活用するもののようだ。

2. PeriodIndex

Period のリストを渡して作ってみる。

pi1 = pd.PeriodIndex([pd.Period('2011'), pd.Period('2012'), pd.Period('2013')])

pi1
<class 'pandas.tseries.period.PeriodIndex'>
freq: A-DEC
[2011, ..., 2013]
length: 3

type(pi1)
pandas.tseries.period.PeriodIndex

開始、終了を指定して作ってみる。

pi2 = pd.PeriodIndex(start='2013-1', end='2013-12', freq='M')

pi2
<class 'pandas.tseries.period.PeriodIndex'>
freq: M
[2013-01, ..., 2013-12]
length: 12

月間や年間の集計などの用途で活用できそうだ。

3. 活用例

PeriodIndex を使った DataFrame を作ってみる。

df = pd.DataFrame({
  'uu': [1000, 2000, 3000, 4000, 5000, 60000]
}, index=pd.PeriodIndex(start='2012-10', end='2013-3', freq='M'))

2012 年分だけ抽出する。

df['2012']
           uu
2012-10  1000
2012-11  2000
2012-12  3000

2012年12月分だけ抽出する。

df['2012-12']
           uu
2012-12  3000

ロジックを書かずに、こーゆーことができるのが便利だ。

df[df.index >= pd.datetime(2012, 12, 15)]
            uu
2012-12   3000
2013-01   4000
2013-02   5000
2013-03  60000

イコールを含まない場合はこうなる。

df[df.index > pd.datetime(2012, 12, 15)]
            uu
2013-01   4000
2013-02   5000
2013-03  60000

直感的な振る舞いではない気もするが、妥当な振る舞いのような気もする。ま、どちらかと言えば、事例のフィルター条件があまりよろしくないので、実際に活用する場合は、分かりやすいフィルター条件を心がけたいところ。

今回はこんなところで。