pandasの時系列データのタイムゾーンを処理(tz_convert, tz_localize)

pandasにおいて時系列データのタイムゾーンを処理するにはtz_convert(), tz_localize()を使います。

pandas.Series.tz_convert — pandas 0.23.4 documentation pandas.Series.tz_localize — pandas 0.23.4 documentation

ここでは、まず単独の要素を例にtz_convert(), tz_localize()の処理内容を説明し、その後にデータ列に対する扱いを説明します。

文字列からTimestamp型に変換: pd.to_datetime() タイムゾーンを変換: tz_convert() タイムゾーンを新たに設定: tz_localize() タイムゾーンを削除する際の注意点 データ列に対する処理

pandas.DataFrame, pandas.Seriesを時系列データとして扱う方法については以下の記事を参照。

文字列からTimestamp型に変換: pd.to_datetime()

文字列をTimestamp型に変換するにはpd.to_datetime()関数を使います。 以下のようにTのあとに時刻、さらにそのあとに+09:00というタイムゾーンの情報が含まれている文字列を例とします。このフォーマットはISO 8601で規定されています。

ISO 8601 - Wikipedia

import pandas as pd

s = '2018-01-01T12:00+09:00'

print(s)
# 2018-01-01T12:00+09:00

print(type(s))
# <class 'str'>

これをpd.to_datetime()に渡すと、タイムゾーンが考慮されUTC(協定世界時)に変換された時刻のTimestamp型オブジェクトが返る。 Timestamp型オブジェクトはtz属性でタイムゾーンを取得できるが、この場合はなにも設定されていません。

ts = pd.to_datetime(s)

print(ts)
# 2018-01-01 03:00:00

print(type(ts))
# <class 'pandas._libs.tslibs.timestamps.Timestamp'>

print(ts.tz)
# None

pd.to_datetime()の引数utcをTrueとするとタイムゾーンがUTCに設定される。

ts_utc = pd.to_datetime(s, utc=True)

print(ts_utc)
# 2018-01-01 03:00:00+00:00

print(ts_utc.tz)
# UTC

タイムゾーンを変換: tz_convert()

タイムゾーンを変換するにはtz_convert()メソッドを使います。 第一引数にタイムゾーン名を指定します。

ts_jst = ts_utc.tz_convert('Asia/Tokyo')

print(ts_jst)
# 2018-01-01 12:00:00+09:00

print(ts_jst.tz)
# Asia/Tokyo

タイムゾーンが変換されても同時刻を指しているので、エポック秒(UNIX time)はtz_convert()前後で変わらない。Timestamp型オブジェクトのエポック秒はvalue属性で取得できます。

print(ts_utc.value)
# 1514775600000000000

print(ts_jst.value)
# 1514775600000000000

print(ts_utc == ts_jst)
# True

他のタイムゾーンへの変換も同じ。

ts_pst = ts_utc.tz_convert('US/Pacific')

print(ts_pst)
# 2017-12-31 19:00:00-08:00

print(ts_pst.tz)
# US/Pacific

同じ時差を表す複数のタイムゾーン名が存在します。

print(ts_utc.tz_convert('America/Los_Angeles'))
# 2017-12-31 19:00:00-08:00

タイムゾーン名の一覧は以下のページなどを参照。

タイムゾーンIDとタイムゾーン名 タイムゾーンの一覧 - cybozu.com ヘルプ

タイムゾーンを新たに設定: tz_localize()

タイムゾーン情報が設定されていないTimestamp型オブジェクトに新たにタイムゾーン情報を設定する場合、tz_convert()を使うとエラーになる。

print(ts)
# 2018-01-01 03:00:00

print(ts.tz)
# None

# print(ts.tz_convert('Asia/Tokyo'))
# TypeError: Cannot convert tz-naive Timestamp, use tz_localize to localize

新たにタイムゾーン情報を設定する場合はtz_localize()を使います。

ts_jst_localize = ts.tz_localize('Asia/Tokyo')

print(ts_jst_localize)
# 2018-01-01 03:00:00+09:00

print(ts_jst_localize.tz)
# Asia/Tokyo

tz_localize()はタイムゾーンの変換ではないので、同じオブジェクトに異なるタイムゾーンを設定すると、違う時刻を示すオブジェクトとなります。

print(ts.tz_localize('US/Pacific'))
# 2018-01-01 03:00:00-08:00

print(ts.tz_localize('Asia/Tokyo').value == ts.tz_localize('US/Pacific').value)
# False

すでにタイムゾーンが設定されているオブジェクトに対してtz_localize()で新たなタイムゾーンを上書きすることはできない。

print(ts_jst)
# 2018-01-01 12:00:00+09:00

# ts_jst.tz_localize('US/Pacific')
# TypeError: Cannot localize tz-aware Timestamp, use tz_convert for conversions

タイムゾーンを削除する際の注意点

タイムゾーン情報を削除したい場合は、tz_convert()またはtz_localize()の第一引数にNoneを指定すればよいが、それぞれ結果が異なる。 tz_convert()の第一引数にNoneを指定すると、UTCに変換された上でタイムゾーン情報が削除され、tz_localize()の第一引数にNoneを指定すると、現地時刻のままタイムゾーン情報が削除される。

print(ts_jst)
# 2018-01-01 12:00:00+09:00

print(ts_jst.tz)
# Asia/Tokyo

print(ts_jst.tz_convert(None))
# 2018-01-01 03:00:00

print(ts_jst.tz_localize(None))
# 2018-01-01 12:00:00

データ列に対する処理

これまでの例は単体の要素に対する処理だったが、pandas.DataFrameの列に対する場合は注意が必要。 以下のpandas.DataFrameを例とします。

df = pd.DataFrame({'date': ['2018-01-01T12:00+09:00',
                            '2018-01-02T00:00+09:00',
                            '2018-01-03T10:00-05:00',
                            '2018-01-03T19:00-08:00'],
                   'value': [0, 1, 2, 3]})

print(df)
#                      date  value
# 0  2018-01-01T12:00+09:00      0
# 1  2018-01-02T00:00+09:00      1
# 2  2018-01-03T10:00-05:00      2
# 3  2018-01-03T19:00-08:00      3

日時の文字列を含む列をpd.to_datetime()で変換すると、データ型(dtype)がdatetime64[ns]となります。引数utcを指定することも可能。いずれの場合もUTCの時刻に変換される。

print(pd.to_datetime(df['date']))
# 0   2018-01-01 03:00:00
# 1   2018-01-01 15:00:00
# 2   2018-01-03 15:00:00
# 3   2018-01-04 03:00:00
# Name: date, dtype: datetime64[ns]

print(pd.to_datetime(df['date'], utc=True))
# 0   2018-01-01 03:00:00+00:00
# 1   2018-01-01 15:00:00+00:00
# 2   2018-01-03 15:00:00+00:00
# 3   2018-01-04 03:00:00+00:00
# Name: date, dtype: datetime64[ns, UTC]

この列に対してtz_convert()やtz_localize()でタイムゾーンを処理しようとするとエラーとなります。

# print(pd.to_datetime(df['date'], utc=True).tz_convert('Asia/Tokyo'))
# TypeError: index is not a valid DatetimeIndex or PeriodIndex


tz_convert(), tz_localize()が使えるのは列がインデックスに指定されている場合のみ。
df_ts = df.set_index('date')

print(df_ts)
#                         value
# date                         
# 2018-01-01T12:00+09:00      0
# 2018-01-02T00:00+09:00      1
# 2018-01-03T10:00-05:00      2
# 2018-01-03T19:00-08:00      3

print(df_ts.index)
# Index(['2018-01-01T12:00+09:00', '2018-01-02T00:00+09:00',
#        '2018-01-03T10:00-05:00', '2018-01-03T19:00-08:00'],
#       dtype='object', name='date')

print(pd.to_datetime(df_ts.index, utc=True))
# DatetimeIndex(['2018-01-01 03:00:00+00:00', '2018-01-01 15:00:00+00:00',
#                '2018-01-03 15:00:00+00:00', '2018-01-04 03:00:00+00:00'],
#               dtype='datetime64[ns, UTC]', name='date', freq=None)

print(pd.to_datetime(df_ts.index, utc=True).tz_convert('Asia/Tokyo'))
# DatetimeIndex(['2018-01-01 12:00:00+09:00', '2018-01-02 00:00:00+09:00',
#                '2018-01-04 00:00:00+09:00', '2018-01-04 12:00:00+09:00'],
#               dtype='datetime64[ns, Asia/Tokyo]', name='date', freq=None)

print(pd.to_datetime(df_ts.index, utc=True).tz_convert('Asia/Tokyo').tz_localize(None))
# DatetimeIndex(['2018-01-01 12:00:00', '2018-01-02 00:00:00',
#                '2018-01-04 00:00:00', '2018-01-04 12:00:00'],
#               dtype='datetime64[ns]', name='date', freq=None)

タイムゾーンを処理した上でインデックスに指定するには、indexを上書きすれば問題ありません。ここでは日本標準時に統一した上でタイムゾーン情報を削除しています。

df_ts.index = pd.to_datetime(df_ts.index, utc=True).tz_convert('Asia/Tokyo').tz_localize(None)

print(df_ts)
#                      value
# date                      
# 2018-01-01 12:00:00      0
# 2018-01-02 00:00:00      1
# 2018-01-04 00:00:00      2
# 2018-01-04 12:00:00      3

print(df_ts.index)
# DatetimeIndex(['2018-01-01 12:00:00', '2018-01-02 00:00:00',
#                '2018-01-04 00:00:00', '2018-01-04 12:00:00'],
#               dtype='datetime64[ns]', name='date', freq=None)

print(df_ts['2018-01-04'])
#                      value
# date                      
# 2018-01-04 00:00:00      2
# 2018-01-04 12:00:00      3

シェア

関連カテゴリー

Python pandas 時系列データ

pandas.DataFrame, Seriesを時系列データとして処理 pandasで行・列の差分・変化率を取得するdiff, pct_change pandasで時系列データのOHLC(四本値)を算出・ダウンサンプリング pandasでデータを行・列(縦・横)方向にずらすshift pandasで窓関数を適用するrollingを使って移動平均などを算出 pandasの時系列データにおける頻度(引数freq)の指定方法 pandasで時系列データをリサンプリングするresample, asfreq pandas, Matplotlib(mpl_finance)でローソク足チャートを作成 pandasで時系列データの曜日や月、四半期、年ごとの合計や平均を算出 pandasで行数、列数、全要素数(サイズ)を取得 pandasで欠損値NaNが含まれているか判定、個数をカウント pandas.DataFrame, Seriesを順位付けするrank 『Pythonデータサイエンスハンドブック』は良書(NumPy, pandasほか) pandasで欠損値NaNを除外(削除)・置換(穴埋め)・抽出

Last Updated: 6/26/2019, 10:34:03 PM