【Python】Pandasでcsvデータを読み込んだら時間計算でハマったので対処法を書く
データ分析でCSVファイルを読み込むとき、PythonのPandasは非常に便利なライブラリですが日時データの計算で予期せぬエラーや思わぬ挙動に悩まされることも少なくありません。実際に時間計算でハマったので備忘録のために書き留めておきます。
目次
対象のCSVファイルと最初のプログラム
まず用意したのがこちらのCSVファイル。日足のドル円データです。左列に日時が入っています。
こちらが最初のソースコード。CSVを呼び出したあとに時間計算しているのがわかると思います。
import pandas as pd df = pd.read_csv('usd_jpy_data.csv') df = df[['Date', 'Open', 'High', 'Low', 'Close']] df['weeks'] = (df['Date'] - df['Date'][0]) print(df)
TypeError: unsupported operand type(s) for -: ‘str’ and ‘str’
このエラー TypeError: unsupported operand type(s) for -: ‘str’ and ‘str’ は、「文字列同士の引き算はできない」という意味です。Pythonでは文字列(str型)に対して直接数値演算を行うことができないため、このエラーが出ます。
解決法
#New!の行が示すように、pandasのto_datetime関数で文字列から日時型に変換すればOKです。まあ、ここはハマったというほどのものではありません。
import pandas as pd df = pd.read_csv('usd_jpy_data.csv') df = df[['Date', 'Open', 'High', 'Low', 'Close']] df['Date'] = pd.to_datetime(df['Date']) #New! df['weeks'] = (df['Date'] - df['Date'][0]) print(df)
インデックス列が日付でない
上記プログラムを実行するとエラーは出なくなります。しかし、以下のように左端に連番のインデックス行が現れてしまいます。
Date Open High Low Close weeks 0 2023-11-06 00:00:00+00:00 149.449005 149.830002 149.382004 149.449005 0 days 1 2023-11-07 00:00:00+00:00 149.988998 150.686996 149.968994 149.988998 1 days 2 2023-11-08 00:00:00+00:00 150.395996 150.981995 150.345993 150.395996 2 days 3 2023-11-09 00:00:00+00:00 150.863998 151.175995 150.798004 150.863998 3 days 4 2023-11-10 00:00:00+00:00 151.348999 151.559006 151.225006 151.348999 4 days
そこで、時間列(Date列)をインデックス列として認識させましょう。#New!の行を追加します。
import pandas as pd df = pd.read_csv('usd_jpy_data.csv') df = df[['Date', 'Open', 'High', 'Low', 'Close']] df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace = True) #New df['weeks'] = (df['Date'] - df['Date'][0]) print(df)
KeyError: ‘Date’
で、最後にこのエラーが出ました。Date列をインデックス列として設定してしまったため、df[‘Date’]で値を取り出せなくなったわけです。
これについてはかなり悩みましたが、苦肉の策でデータ列をコピーすることにしました。#New!の行のところです。
import pandas as pd df = pd.read_csv('usd_jpy_data.csv') df = df[['Date', 'Open', 'High', 'Low', 'Close']] df['Date'] = pd.to_datetime(df['Date']) df['Date2'] = df['Date'] #New df.set_index('Date', inplace = True) df['weeks'] = (df['Date2'] - df['Date2'][0]) print(df)
この結果、エラーは発生せず以下のような出力をするようになりました。Date2が余計ですが日付計算をさせる以上は致し方なしかなと。
Open High Low Close Date2 weeks Date 2023-11-06 00:00:00+00:00 149.449005 149.830002 149.382004 149.449005 2023-11-06 00:00:00+00:00 0 days 2023-11-07 00:00:00+00:00 149.988998 150.686996 149.968994 149.988998 2023-11-07 00:00:00+00:00 1 days 2023-11-08 00:00:00+00:00 150.395996 150.981995 150.345993 150.395996 2023-11-08 00:00:00+00:00 2 days 2023-11-09 00:00:00+00:00 150.863998 151.175995 150.798004 150.863998 2023-11-09 00:00:00+00:00 3 days 2023-11-10 00:00:00+00:00 151.348999 151.559006 151.225006 151.348999 2023-11-10 00:00:00+00:00 4 days
スポンサーリンク