【Pandas】UNIX time ⇆ Timestamp、formatなど日付操作のまとめ
Pythonでのデータ分析を効率的に行うためのライブラリ「Pandas」の日付操作で先日少しハマってしまった。自分への戒めとして、Pandasの日付操作をまとめたので、紹介する。
まず、Pandas で処理する場合だけでなく、何をプログラムするにしても、どんな「型」が定義されているのかを確認することはきほんの「き」であると実感した。これは、こういう感じのタイプだろうな、ぐらいの曖昧な理解をしてると、私のように見事にハマる可能性が高いのでご注意ください。
今回は、データ分析でよくある CSV データを読み込む場合を想定する。CSV データには、UNIX時間が含まれるデータがあることとする。
pandas.read_csv — pandas 1.0.5 documentation
pandas.read_csv
を利用することで、pandas.DataFrame
として読み込むことができる。(Pandas には2つの主要なデータ構造があり、Series が1次元のデータ、DataFrame が2次元のデータである。)
>>> import pandas as pd >>> df = pd.read_csv('./testcsv') >>> print(df) timestamp 0 1594589999 1 1594632119 2 1594810919
読み込んだ時点では、列の dtype は Object
型であり、各要素は str
型である。
文字列からTimestamp型に変換
まず、日付の操作をするために、UNIX time の文字列データを日付のデータに変換する。
pandas.to_datetime — pandas 1.0.5 documentation
pandas.to_datetime()
関数を使うことで、日時を表した文字列の列データを、列の dtype が datetime64[ns]
型、各要素が Timestamp
型である列データに変換することができる。(Timestamp 型はPythonの標準ライブラリ datetime の datetime 型を継承し拡張した型である。)
様々なパラメータを設定可能であるが、以下は注意しておくべきかと思われる。(設定していないことで、予期していない変換になることがある。)
params | default | 説明 |
---|---|---|
utc | None | 文字列にtimezoneがきちんと入っていない場合、UTCに変換され、tz属性がNoneとなる。タイムゾーンが設定されていないので、注意が必要である。UNIX timeの文字列の場合は、utc=Trueを必ず設定することをお勧めする。 |
format | None | 標準的な書式でない場合は、書式文字列を指定する。 例)%Y/%m/%d %H:%M:%S 書式化コード |
unit | 'ns' | UNIX timeが「ns」でない場合には s, ms の指定をする必要がある。 |
# オプションパラメータを設定しなかった場合 >>> x = pd.to_datetime(df['datetime']) >>> print(x) 0 1970-01-01 00:00:01.594589999 1 1970-01-01 00:00:01.594632119 2 1970-01-01 00:00:01.594810919 Name: datetime, dtype: datetime64[ns] # 単位のオプションパラメータを追加した場合 >>> x = pd.to_datetime(df['datetime'], unit='s') >>> print(x) 0 2020-07-12 21:39:59 1 2020-07-13 09:21:59 2 2020-07-15 11:01:59 Name: datetime, dtype: datetime64[ns] # 単位とタイムゾーンのオプションパラメータを追加した場合 >>> x = pd.to_datetime(df['datetime'], unit='s', utc=True) >>> print(x) 0 2020-07-12 21:39:59+00:00 1 2020-07-13 09:21:59+00:00 2 2020-07-15 11:01:59+00:00 Name: datetime, dtype: datetime64[ns, UTC]
タイムゾーンの確認をしたい場合は、以下の通りである。(Pandas で列全体を一括処理したい場合は、 dtアクセサリ を使う。 )
>>> x.dt.tz <UTC>
UTC を JST に変換する
次に、時間表記はやはり日本時間にしたいので、タイムゾーンを日本( Asia/Tokyo
)に設定する。
pandas.Series.dt.tz_convert — pandas 1.0.5 documentation
タイムゾーンを変換するには tz_convert()
メソッドを使う。
>>> x = x.dt.tz_convert('Asia/Tokyo') >>> print(x) 0 2020-07-13 06:39:59+09:00 1 2020-07-13 18:21:59+09:00 2 2020-07-15 20:01:59+09:00 Name: datetime, dtype: datetime64[ns, Asia/Tokyo]
もしタイムゾーンの設定を忘れていた場合は、以下のエラーが発生する。
>>> x = x.dt.tz_convert('Asia/Tokyo') TypeError: Cannot convert tz-naive timestamps, use tz_localize to localize
この場合には、エラー文にも記載があるように、タイムゾーン情報が設定されていない(naiveな)データに新たにタイムゾーンを設定するためのメソッド tz_localize()
を使う。
pandas.Series.tz_localize — pandas 1.0.5 documentation
今回の例では、UNIX time を使っているので、UTCに設定する。(to_datetime() でパラメータ utc=True を忘れた場合に、まずは UTC に設定して、タイムゾーンを東京に変更する必要がある。)
>>> x = x.dt.tz_localize('UTC').dt.tz_convert('Asia/Tokyo') >>> print(x) 0 2020-07-13 06:39:59+09:00 1 2020-07-13 18:21:59+09:00 2 2020-07-15 20:01:59+09:00 Name: datetime, dtype: datetime64[ns, Asia/Tokyo]
Timestampから文字列にフォーマットする
Timestamp
型を所定の形式の文字列に変換したい場合は、Python標準ライブラリの datetime
型と同様に strftime()
で任意のフォーマットの文字列に変換することが可能である。列データを一括で変換することがほとんどだと思うので、dtアクセサリを使う。
pandas.Series.dt.strftime — pandas 1.0.5 documentation
>>> x = x.dt.strftime('%Y/%m/%d %H:%M') >>> print(x) 0 2020/07/13 06:39 1 2020/07/13 18:21 2 2020/07/15 20:01 Name: datetime, dtype: object
TimestampからUNIX timeに変換する
Timestamp
型を UNIX time にしたい場合は、Timestamp
型のメソッド timestamp()
を使う。ただし、timestamp()
は Timestamp
型にはあるが、dtアクセサには用意されていないため、列での一括処理を行う場合は、map()
を使う。
>>> print(x.map(lambda x: x.timestamp())) 0 1.594590e+09 1 1.594632e+09 2 1.594811e+09 Name: datetime, dtype: float64
timestamp()
の返り値は、浮動小数点 float
型となっている。整数にしたい場合は、 int()
を用いる。
>>> print(x.map(lambda x: int(x.timestamp()))) 0 1594589999 1 1594632119 2 1594810919 Name: datetime, dtype: int64
まとめ
Pandas の日付操作に関して、整理を行なった。基本的な操作であるが、どのデータを操作しているのかをしっかりと区別して、メソッドの使い分けが必要である。
それでは、ステキな開発ライフを。