pandasで日付データを操作する際に必要な知識をまとめた.
初めに,pythonにおける日付を取り扱うデータ型に代表的なものが3種類あり(datetime.datetime
, np.datetime64
, Timestamp
),それぞれの相互変換の方法を説明する.その後,エクセルからpd.read_excel
でデータを読み込む際にセルの設定やカラムに何が入るかによってデータ型が異なる点の指摘とTimestamp
型への変換方法.最後に,日付データの図示方法を説明する.
目的としては,pandasにおいて日付データを処理出来るようになることである.pandasではTimestamp
型を用いて内部処理しているため,如何にしてTimestamp
型に変換していくかがポイントである.
本記事で使用したコードは,git clone https://github.com/akitoshiblog/datetime_usage.git
で手に入る.
下準備
以下のライブラリーをimportし,変数の値,オブジェクト表示,データ型を確認する用の関数を定義する.
import datetime import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates %matplotlib inline def print_variable(v,s): """Print variabels with text, value, object representation, type. """ print(f"{s} : {v}, {repr(v)}, {type(v)}")
日付に関連したオブジェクト3種類の生成
ここでは,3つの日付データの型を宣言している.
ある特定の日付以前を取り出したいといったときに,特にTimestamp
型の宣言方法を知っておく必要がある.
d1 = datetime.datetime(2020,1,2) # datetime object d2 = np.datetime64("2020-01-02") # np.datetime64 object d3 = pd.Timestamp(2020,1,2) # Timestamp object print_variable(d1,"d1") print_variable(d2,"d2") print_variable(d3,"d3")
d1 : 2020-01-02 00:00:00, datetime.datetime(2020, 1, 2, 0, 0), <class 'datetime.datetime'> d2 : 2020-01-02, numpy.datetime64('2020-01-02'), <class 'numpy.datetime64'> d3 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'>
3つの型の相互変換
以下のコードにより全ての型同士の変換パターンが網羅されている.
結果は全て, 2020/01/02が保持されていることを確認出来る.
# datetime.datetime to np.datetime64 d1_2 = np.datetime64(d1) # datetime.datetime to Timestamp d1_3 = pd.Timestamp(d1) # np.datetime64 to datetime.datetime d2_1 = d2.astype(datetime.datetime) # np.datetime64 to Timestamp d2_3 = pd.Timestamp(d2) # Timestamp to datetime.datetime d3_1 = d3.to_pydatetime() # Timestamp to np.datetime64 d3_2 = d3.to_datetime64() print_variable(d1_2,"d1_2") print_variable(d1_3,"d1_3") print_variable(d2_1,"d2_1") print_variable(d2_3,"d2_3") print_variable(d3_1,"d3_1") print_variable(d3_2,"d3_2")
d1_2 : 2020-01-02T00:00:00.000000, numpy.datetime64('2020-01-02T00:00:00.000000'), <class 'numpy.datetime64'> d1_3 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> d2_1 : 2020-01-02, datetime.date(2020, 1, 2), <class 'datetime.date'> d2_3 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> d3_1 : 2020-01-02 00:00:00, datetime.datetime(2020, 1, 2, 0, 0), <class 'datetime.datetime'> d3_2 : 2020-01-02T00:00:00.000000000, numpy.datetime64('2020-01-02T00:00:00.000000000'), <class 'numpy.datetime64'>
文字列からTimestampに変換する
pd.to_datetime
関数はかなり広い幅の変換を可能にする.
以下のパターンは全て正常にTimestamp
オブジェクトへ変換することが可能.
ex1 = pd.to_datetime("20200102") ex2 = pd.to_datetime("2020-01-02") ex3 = pd.to_datetime("2020 01 02") ex4 = pd.to_datetime("2020-1 2") ex5 = pd.to_datetime("2020/01/02") ex6 = pd.to_datetime("2020/01/02", format='%Y/%m/%d') ex7 = pd.to_datetime(1577923200000000000, unit="ns") ex8 = pd.to_datetime(1577923200, unit="s") print_variable(ex1, "ex1") print_variable(ex2, "ex2") print_variable(ex3, "ex3") print_variable(ex4, "ex4") print_variable(ex5, "ex5") print_variable(ex6, "ex6") print_variable(ex7, "ex7") print_variable(ex8, "ex8")
ex1 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex2 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex3 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex4 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex5 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex6 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex7 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> ex8 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'>
エクセルファイルからの読み込み,Timestampへデータを変換
サンプルのエクセルデータはgithub上に上がっている.
このデータを読み込むと以下のようになる.
df = pd.read_excel("./sample_datetime.xlsx") display(df) print(df.dtypes)
カラムA,Bはdatetime64[ns]となり,これがpandasにおけるTimestamp
の型である.
カラムCはエクセルの設定上で,文字列として登録した.そのためデータフレームの見た目上では日付データの用に見えるがこれは文字列として保存されている.日付型として取り扱うためには日付型への変換が必要である特定.
カラムDは日付型と文字列が混じっている場合である.
各データセルに入っているデータの型を確認してみる.
for c in df.columns: v = df[c].iloc[0] print_variable(v,f"{c}0")
A0 : 2020-01-05 00:00:00, Timestamp('2020-01-05 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> B0 : 2020-01-02 00:00:00, Timestamp('2020-01-02 00:00:00'), <class 'pandas._libs.tslibs.timestamps.Timestamp'> C0 : 2020-01-02, '2020-01-02', <class 'str'> D0 : 2020-01-02 00:00:00, datetime.datetime(2020, 1, 2, 0, 0), <class 'datetime.datetime'> E0 : 10, 10, <class 'numpy.int64'>
すると,カラムDの0インデックスの場所にはpythonの組み込みオブジェクトであるdatetime.datetime
型が入力されていることが分かる.また,カラムCには改めて文字列が入力されていることが確認出来る.
次に以下のコードによって,カラムC,DをTimestamp
型に変換することが出来る. errors="coerce"
を指定すると変換出来なかった値がNaT
に置換され,カラム全体としてはTimestamp
型として処理出来るようになる.
また,Timestamp
同士の引き算を行うとTimedelta
型のオブジェクトとなる.
このデータ型の取り扱いの1つの工夫としては単位日数もしくは単位時間などで割り,数値型として処理することである.すると,日付データ特有の処理に困らなくて済む.
df = pd.read_excel("./sample_datetime.xlsx") df["C"] = pd.to_datetime(df["C"]) df["D"] = pd.to_datetime(df["D"], errors="coerce") df["diff"] = df["A"] - df["B"] df["diff_f"] = (df["A"] - df["B"])/pd.Timedelta(1,"D") display(df) print(df.dtypes)
図示
x軸に日付データを取った際の図示の方法にはmatplotlibの機能を使ったものと,pandasの機能を使ったものがある.個人的には,pandasの機能を使うと予期せぬx軸の設定が適用されたりするため,matplotlibの機能のみを用いて図を作成しておくのが良いと考える.
単純な図示方法は,シリーズをx軸,y軸に渡す.
plt.plot(df["A"], df["E"])
x軸の角度を変えたり,表記のフォーマットを変えたりするには以下のようにする.
日付のフォーマットの指定方法としては,strftime() and strptime() Format Codes の公式ドキュメントを参照のこと.
fig = plt.figure(figsize=(5,3)) ax = fig.add_subplot(111) ax.plot(df["A"],df["E"]) ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%b-%d")) plt.xticks(rotation=30) plt.show()
pandasを用いた図示方法も載せておく.
x軸の日付の表記方法が違うことが分かる.
df.plot(x="A", y ="E")
———-雑感(`・ω・´)———-
pandas.to_datetime, pandas official API reference のAPIリファレンスからpandasのメソッドを確認しておくと発見がある.
特に,Seriesに対する .dt
の中にはシリーズ全体に対してTimestamp
オブジェクトに対する操作を同時に行えるメソッド群が存在しているのでいくつか眺めておくと良いかもしれない.
また以下の本で詳細にdatetime objectに関する説明が書いてある.
コメント