Pandas DataFrameで日時データのタイムゾーン変換
Category: python
TimeStampデータのタイムゾーン変換問題
PandasでTimeStampデータのタイムゾーンを変換する場合には少し気をつけないといけない。 例を使って説明していく。
以下のような test.csv というデータファイルがあるとする。 時刻データがUTCであるとし、JSTに変換したいと仮定する。
2016-03-19 03:49:12,168
2016-03-19 03:50:11,110
2016-03-30 02:10:30,9
2016-03-30 02:12:47,36
2016-03-30 02:15:03,113
2016-03-30 02:29:03,17
2016-03-30 02:31:03,8
2016-03-30 02:37:36,14
2016-03-30 02:40:37,11
2016-03-30 23:13:23,199
まずはPandasでこれを読み込む。
>>> import pandas as pd
>>> data = pd.read_csv("test.csv", header=None, names=["on_create", "value"])
>>> data
on_create value
0 2016-03-19 03:49:12 168
1 2016-03-19 03:50:11 110
2 2016-03-30 02:10:30 9
3 2016-03-30 02:12:47 36
4 2016-03-30 02:15:03 113
5 2016-03-30 02:29:03 17
6 2016-03-30 02:31:03 8
7 2016-03-30 02:37:36 14
8 2016-03-30 02:40:37 11
9 2016-03-30 23:13:23 199
現時点では on_create 列は文字列になっているので、TimeStamp型に変換する。
>>> type(data.on_create[0])
<type 'str'>
>>> data.on_create = pd.to_datetime(data.on_create, utc=True)
>>> type(data.on_create[0])
<class 'pandas.tslib.Timestamp'>
Padasには tz_convert なるものがあるのでこれを適用してみる。 が、エラーを食らってしまう。
>>> data.tz_convert('Asia/Tokyo')
TypeError: index is not a valid DatetimeIndex or PeriodIndex
DataFrameの列(Series)に対して適用しても同じ。
>>> data.on_create.tz_convert('Asia/Tokyo')
TypeError: index is not a valid DatetimeIndex or PeriodIndex
どうすればいいか?
tz_convert はindexに対して適用する手法らしい。 なので、以下のようにindexに変換してから適用する。
>>> data.index = pd.DatetimeIndex(data.on_create, name='on_create')
タイムゾーンが指定されていないのでUTCとして指定する。
>>> data.index = data.index.tz_localize('UTC')
タイムゾーンをJSTに変換する。
>>> data.index = data.index.tz_convert('Asia/Tokyo')
>>> data
on_create value
on_create
2016-03-19 12:49:12+09:00 2016-03-19 03:49:12 168
2016-03-19 12:50:11+09:00 2016-03-19 03:50:11 110
2016-03-30 11:10:30+09:00 2016-03-30 02:10:30 9
2016-03-30 11:12:47+09:00 2016-03-30 02:12:47 36
2016-03-30 11:15:03+09:00 2016-03-30 02:15:03 113
2016-03-30 11:29:03+09:00 2016-03-30 02:29:03 17
2016-03-30 11:31:03+09:00 2016-03-30 02:31:03 8
2016-03-30 11:37:36+09:00 2016-03-30 02:37:36 14
2016-03-30 11:40:37+09:00 2016-03-30 02:40:37 11
2016-03-31 08:13:23+09:00 2016-03-30 23:13:23 199
もちろん以下のようにして一気に適用してもOK。
>>> data.index = pd.DatetimeIndex(data.on_create, name='on_create').tz_localize('UTC').tz_convert('Asia/Tokyo')
indexのままでも使えるが、必要があれば元のデータをタイムゾーン変換済みデータで置き換え、indexを振り直す。
>>> data.on_create = data.index
>>> data = data.reset_index(drop=True)
>>> data
on_create value
0 2016-03-19 12:49:12+09:00 168
1 2016-03-19 12:50:11+09:00 110
2 2016-03-30 11:10:30+09:00 9
3 2016-03-30 11:12:47+09:00 36
4 2016-03-30 11:15:03+09:00 113
5 2016-03-30 11:29:03+09:00 17
6 2016-03-30 11:31:03+09:00 8
7 2016-03-30 11:37:36+09:00 14
8 2016-03-30 11:40:37+09:00 11
9 2016-03-31 08:13:23+09:00 199
まとめ
PandasのDataFrameでTimeStamp型を使うならindexにしとけ!