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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

1873閲覧

時系列データでの値修正

jun.k

総合スコア28

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/09/08 07:00

あるDataFrameにおいて、indexに日時(時間毎プロット)、columnsは日時に対応した価格が入っている時に、欠損ではないのですが明らかに間違いと思われる価格が複数入っているため、これを前日時の値に修正したいと考えています。

初めは対象となる日時を可視化して確認・修正していたのですが、量が多いので効率的に返還する方法はないかと・・・。イメージしているのは1時間前(1列前)の値より±10%変化したら1時間前の値に変更するというものです。

For文で判定させて修正しようとも思ったのですが、ひとつ前の行をどのように指定すればよいのかわかりませんでした。

初歩的な質問で申し訳ありませんが、よろしくお願い致します。

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

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

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

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

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

guest

回答3

0

既に解決済みですが・・別解を書きかけていたので投稿します。

pandas にて前行の値との計算や比較を行うときは DataFrame.shift() をお使います。

例えば 「前行との変動率」

Python

1((df['value'].shift(1) - df['value']).abs())/df['valalue']

のように書けます。

ですので「変動率が10%以上の場合は前の行の値を入れる」はこんな感じになるかと思います。

Python

1df.ix[(((df['value'].shift(1)-df['value']).abs())/df['value']) > 0.1,'value'] = df['value'].shift()

ただ、この方法だと、外れ値の下の行も変動率が高くなってしまい、対象になってしまうので、もう少し条件を追加する必要がありそうです。

たとえば条件を「1行前との変動率、2行前との変動率共に10%以上」にした例では

Python

1df.ix[((((df['value'].shift(1)-df['value']).abs())/df['value']) > 0.1) & ((((df['value'].shift(2)-df['value']).abs())/df['value']) > 0.1),'value'] = df['value'].shift()

となります

投稿2017/09/08 09:46

magichan

総合スコア15898

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

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

jun.k

2017/09/08 10:41

ありがとうございました。ただデータが2行以上連続して外れ値の場合のあるため、for文で修正しながらのほうがよいかと思い、ご指摘いただいたshiftを使って組んでみたのですが、エラーが出てしまいうまくいきませんでした for i in df['value']: if abs(i.shift(1)-i)>10: i.shift(1)=i shiftがうまく機能するのであればこちらの方が分かりやすいかと思ったのですが。
guest

0

ベストアンサー

単純に、前の値を別変数に保持しておきます。
ループでは変化を見て、異常なら前の値で置き換えます。

Python

1import pandas as pd 2import datetime as dt 3 4# テストデータ 5hours = [h for h in range(10)] 6dates = list(map(lambda h: dt.datetime(2017,9,8,h,0,0),hours)) 7vals = [1000+h*10 for h in hours] 8vals[2] = vals[5] = 9999 # 異常値 9df = pd.DataFrame( {'val':vals},index=dates) 10print(df) 11 12# 異常値は前の値に補正 13vals = df['val'] 14prev = vals[0] 15for i,v in enumerate(vals): 16 if abs((v - prev) / prev) >= 0.1: 17 vals[i] = prev 18 prev = vals[i] 19print(df)

投稿2017/09/08 07:43

can110

総合スコア38266

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

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

jun.k

2017/09/08 09:03

これだと初めのループの際に、prevもvも1行目の値が入るので計算できないんじゃないかと思ったのですが、試したらできました。ありがとうございました!!
guest

0

こんなの使ってみるのもありかもしれないですね。

Python

1def couple(arg_list): 2 if len(arg_list) < 2: 3 return 4 for i in range(1, len(arg_list)): 5 yield arg_list[i-1], arg_list[i] 6 7def main(): 8 my_list = [3] 9 for before, after in couple(my_list): 10 print(before, after) 11 12if __name__ == '__main__': 13 main() 14 15"""出力 163 5 175 1 181 6 19"""

もっといい方法があるかもわかりませんが。

投稿2017/09/08 07:29

LouiS0616

総合スコア35660

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

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

jun.k

2017/09/08 08:57

ありがとうございました。ちょっと理解するのに時間がかかりそうなのですが、試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問