質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1034閲覧

pythonでのARモデルの実装時のエラー

AI_engineer

総合スコア15

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/11/02 07:01

前提・実現したいこと

pythonを用いてARモデルの実装を行っていますが、原因不明のエラーにより解決できず困っています。
加速度が記録されたcsvファイルの時系列データの予測を行おうとしています。
エラーは、
test = df['x_ags'].loc['1900-01-01 14:57:55.550000':]
の箇所で出ています。

また、時刻をDataFrameのインデックスに設定していますが、1900-01-01という不要な日付データの消し方もわからずに困っています。
参考までに作成したDataFrameの画像を添付しておきます。

イメージ説明

発生している問題・エラーメッセージ

KeyError: During handling of the above exception, another exception occurred:

該当のソースコード

python

1# dh['Times']カラム(時刻を表す)を新たに作成 2df['Times'] = df['time'].apply(lambda x: datetime.timedelta(seconds=x)) 3df['Times'] = df['Times'].astype(str) 4# timedeltaによって出力されたdays, 秒の小数点第三位以下を削除 5df['Times'] = df['Times'].apply(lambda x: x[7:18]) 6 7df['Times'] = pd.to_datetime(df['Times'], format='%H:%M:%S.%f') 8df = df.set_index('Times') 9 10# ARモデルの作成 11#train, testデータに分割 12test = df['x_ags'].loc['1900-01-01 14:57:55.550000':] 13train = df['x_ags'].loc[:'1900-01-01 14:57:55.530000'] 14 15# ARmodel 16# fitすると、返り値としてARmodelのResultが返ってくる。 17ar = AR(train).fit(maxlag=4, ic='aic') 18 19#予測 20ar_predict = ar.predict(start='1900-01-01 14:57:55.550000',end='1900-01-01 14:58:14.710000') 21 22# plot 23plt.plot(ar_predict) 24plt.plot(test)

試したこと

DataFrameに'1900-01-01 14:57:55.550000'のインデックスがないのかと思い確認しましたがありました。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず、PandasのDatetimeIndexでは、文字列で小数秒が含まれている場合をサポートしていないようです。そのためエラーが出ています。

このことをきちんとドキュメントしてある文章は見当たらないのですが、実際に質問者様のコードで小数秒を削除してみると動作します。また、公式ドキュメントpandas.DatetimeIndex.indexer_between_timeには、Time passed either as object (datetime.time) or as string in appropriate format (“%H:%M”, “%H%M”, “%I:%M%p”, “%I%M%p”, “%H:%M:%S”, “%H%M%S”, “%I:%M:%S%p”,”%I%M%S%p”).との記載があり、直接ではないですが近い機能において小数秒フォーマットに対応していないとの記述はありました。

また、「1900-01-01という不要な日付データの消し方もわからない」ですが、timedelta(相対時間)として取り込んだ時刻を文字列にして、さらに今度はdatetime(絶対日時)にしている操作をしているため、初期日時としての1900-01-01に変換されてしまっていることが、原因です。

対策は以下2通りあります。

###1. 既存コードを尊重する場合(1900-01-01を許容する)

文字列から自動変換ではなく、あらかじめdatetime型を作ってから、インデックス比較に入れると動作します。

Python

1# dh['Times']カラム(時刻を表す)を新たに作成 2df['Times'] = df['time'].apply(lambda x: datetime.timedelta(seconds=x)) 3df['Times'] = df['Times'].astype(str) 4# timedeltaによって出力されたdays, 秒の小数点第三位以下を削除 5df['Times'] = df['Times'].apply(lambda x: x[7:18]) 6 7df['Times'] = pd.to_datetime(df['Times'], format='%H:%M:%S.%f') 8df = df.set_index('Times') 9 10# ARモデルの作成 11# 追加 12boundry_time = datetime.datetime.strptime('1900-01-01 14:57:55.550000', '%H:%M:%S.%f') 13#train, testデータに分割 14test = df['x_ags'].loc[boundry_time:] #修正 15train = df['x_ags'].loc[:boundry_time] #修正

###2. TimedeltaIndexを使う場合(1900-01-01は出ないようにする)

小数3位以下の秒を切り捨てたいのであれば、文字列に変換せずに、取り込み時点でその処理をしておくとシンプルになり、timedeltaのまま扱うことができます。また、TimedeltaIndexだと小数秒の文字列もそのままインデックス比較として使えるようです。

Python

1# 以下、全面改訂 2# dh['Times']カラム(時刻を表す)を新たに作成 3df['Times'] = df['time'].apply(lambda x: datetime.timedelta(seconds=int(x*100)/100)) 4df = df.set_index('Times') 5 6# ARモデルの作成 7#train, testデータに分割 8test = df['x_ags'].loc['14:57:55.550000':] 9train = df['x_ags'].loc[:'14:57:55.550000']

共通の注意

loc内の指定と同じインデックスがある必要はありません。逆に、一致するインデックスがある場合、そのインデックスはtestとtrain両方に取り込まれる仕様のようです。本来の学習データとテストデータの分割としては、あまりよろしくない状態になりますので、注意が必要です。よって、testの切る時刻とtrainの切る時刻は、少しだけずらしておくことが望ましいです。

投稿2020/11/03 04:22

toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AI_engineer

2020/11/03 05:39

回答ありがとうございます。 対応策2のTimedeltaIndexを使用することを試してみましたがうまくいきません。 >小数3位以下の秒を切り捨てたいのであれば、文字列に変換せずに、取り込み時点でその処理をしておくとシンプルになり、timedeltaのまま扱うことができます 小数第三位以下の秒を切り捨てるために取り込み時点でdf['time']に処理を施すとのことですが、この処理にどのような意味があるのかわかりません。 単にdf['time']の値に100をかけて直後に100で割ることに何か意味があるのでしょうか。 また実際にcsvファイルを読み込んだ後、 df['Times'] = df['time'].apply(lambda x: datetime.timedelta(seconds=int(x*100)/100)) df = df.set_index('Times') を行うと、dfのインデックスはTimesになりましたが、 622days 15:12:30 と表示されました。'622days'が新たに表示されてしまったことと実際の時刻が違うことのそれぞれの対処はどのようにすればよいでしょうか。 >また、TimedeltaIndexだと小数秒の文字列もそのままインデックス比較として使えるようです。 この記述方法(TimedeltaIndex)だとARモデルの実装が実際にできるということでしょうか。 プログラミング初学者な為、解決できず申し訳ありません。 お時間ありましたら補足をお願いします。
toast-uz

2020/11/03 05:58

> 100をかけて直後に100で割ることに何か意味があるのでしょうか。 100をかけて、int()で小数を切り捨てて、直後に100で割っています > '622days'が新たに表示されてしまった 元々のdf{'time']の値が、質問文のどこにも条件提示されていませんので、わかりません。 > この記述方法(TimedeltaIndex)だとARモデルの実装が実際にできるということでしょうか それはわかりません。DateTimeIndexが必要なのであれば、対策1をご利用ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問