先ほどpythonで開発をしている最中にDataFrameの時系列データの時間列をエポック秒に変換する際に、非常に苦労したので僕の試行錯誤の結果が似たような状況のどなたかの役に立てばと思い備忘録として書いていきたいと思います。
過程
現在FX関連のとあるツールを自作しているのですが、APIから取得したレートの情報の時系列DataFrameについて時間に関しても整数値で扱えた方が何かと都合がいいと思い、Datetimeをエポック秒に変換し始めました。
最初はindexの情報が書き換えられないことを知らず、
#tickは一定期間のOHLCの価格などが入っているDataFrame形式の多次元リスト
tick["Datetime"] = pd.to_datetime(tick["Datetime"]).apply(lambda x: x.timestamp())
この方法で直接indexを置き換えてやろうと思ったのですが、結果は失敗で以下のエラーが出てきました。
KeyError: 'Datetime'
次に、indexの内容は書き換えられないことと、set_index()とreset_index()でindexを設定・解除できることを知り
#indexを削除
tick.reset_index(inplace=True)
#Datetimeをエポック秒に変換
tick["Datetime"] = pd.to_datetime(tick["Datetime"]).apply(lambda x: x.timestamp())
#Datetimeをindexに設定
tick.set_index("Datetime")
print(tick)
これを試してみた結果、
Datetime Open High Low Close Adj Close Volume
0 1.721343e+09 157.287994 157.304993 157.285004 157.300003 157.300003 0
1 1.721343e+09 157.298004 157.306000 157.287994 157.289001 157.289001 0
2 1.721343e+09 157.292007 157.300995 157.281998 157.281998 157.281998 0
3 1.721343e+09 157.285004 157.287994 157.261002 157.261993 157.261993 0
(中略)
56 1.721346e+09 157.130005 157.132996 157.117996 157.132004 157.132004 0
57 1.721347e+09 157.128998 157.139999 157.110001 157.112000 157.112000 0
58 1.721347e+09 157.123993 157.123993 157.123993 157.123993 157.123993 0
無事エポック秒に変換はできたものの、謎のIDが勝手にindexとして追加されてしまいました。正直今の段階ではこのままでも問題はなかったのですが、今後このデータは大量に蓄積していく予定だったのでできる限り余計な情報は省きたいと思いなんとかしてこの列を消して変換後のDatetimeをindexに戻せないかと思い、力業で削除してみました。
#indexを削除
tick.reset_index(inplace=True)
#Datetimeをエポック秒に変換
tick["Datetime"] = pd.to_datetime(tick["Datetime"]).apply(lambda x: x.timestamp())
#ID列を削除
tick.drop(tick.columns[-1], axis=1, inplace=True)
#Datetimeをindexに設定
tick.set_index("Datetime")
print(tick)
結果はなにも変わりませんでした。
Datetime Open High Low Close Adj Close Volume
0 1.721343e+09 157.287994 157.304993 157.285004 157.300003 157.300003 0
1 1.721343e+09 157.298004 157.306000 157.287994 157.289001 157.289001 0
2 1.721343e+09 157.292007 157.300995 157.281998 157.281998 157.281998 0
3 1.721343e+09 157.285004 157.287994 157.261002 157.261993 157.261993 0
(中略)
56 1.721346e+09 157.130005 157.132996 157.117996 157.132004 157.132004 0
57 1.721347e+09 157.128998 157.139999 157.110001 157.112000 157.112000 0
58 1.721347e+09 157.123993 157.123993 157.123993 157.123993 157.123993 0
この後色々調べていった結果、set_indexのパラメータをinplace = Trueにすれば既存のindexを削除して新たにindexを指定できると知り、以下の方法を試した結果
#indexを削除
tick.reset_index(inplace=True)
#Datetimeをエポック秒に変換
tick["Datetime"] = pd.to_datetime(tick["Datetime"]).apply(lambda x: x.timestamp())
#ID列を削除
tick.drop(tick.columns[-1], axis=1, inplace=True)
#Datetimeをindexに設定
tick.set_index("Datetime",inplace = True)
print(tick)
Open High Low Close Adj Close Volume
Datetime
1.721344e+09 157.264008 157.270996 157.261002 157.264008 157.264008 0
1.721344e+09 157.264008 157.270004 157.259995 157.263000 157.263000 0
1.721344e+09 157.263000 157.270996 157.259995 157.261993 157.261993 0
(中略)
1.721347e+09 157.097000 157.126999 157.085007 157.087997 157.087997 0
1.721348e+09 157.087997 157.139999 157.084000 157.119003 157.119003 0
1.721348e+09 157.104996 157.104996 157.104996 157.104996 157.104996 0
無事成功しました。
パラメータ"inplace"について
inlaceは和訳すると「決まった場所に~」という意味で、pandasにおいては元のデータを変更するかどうかを指定する際に使われるようです。一度データを削除してしまうと変更が不可逆になってしまうためデフォルトではFalseになっているようですので、今回は問題ありませんでしたが不用意に指定しない方がよさそうです。
最後に
今回の話題は多くの人にとっては取るに足らない話題かもしれませんが、僕と似たような独学で知識に抜けがある人などの参考になれば幸いです。もしこの文章を読まれた方で理解が間違っている点や改善点などに気づいた方は是非指摘していただけると嬉しいです。拙い文章でしたが最後まで読んでくださりありがとうございました。
追記
少し認識の違いがあったかもしれないので一応書き残しておきます。
①「indexの情報が書き換えられない」
indexの情報が書き換えられないのではなく、エラー内容がKey ErrorなのでDataFrameのKeyとしてindexを指定できないということかもしれないです。結果として書き換えができなかった事実は変わらないのですが認識が間違ってたかもしれないので訂正しておきます。
②最後のコードの
tick.drop(tick.columns[-1], axis=1, inplace=True)
の部分
この方法で指定の列が削除できるのは間違いないのですが、この次の
tick.set_index("Datetime",inplace = True)
の部分でinplace = Trueを指定して既存のindexを削除して新たなIndexを指定しているので不要な一文だったかもしれないです。