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

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

ただいまの
回答率

88.62%

python データフレームの一行上の値を使って条件分岐がしたい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 308

yuudai

score 62

前提・実現したいこと

if文の中でデータフレームの一行上の値を使って計算がしたいです。

一行前がema_10 > ema_20 > ema_40 > ema_80 > ema_320もしくはその逆ならdropna_df['perfect_order']=1
(dropna_dfとemaの行数は一緒。dropna_dfに'perfect_order'という行はまだ存在していない)
elseも似たような処理をする

データフレームの一行上の値をif条件分岐で使いたい。
回答もしくは修正依頼をお待ちしております。よろしくお願いします。

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

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

該当のソースコード

一応自分が試してみたソースコードを載せるが見当違いのことをしてると思う。

ema.head()
-------------------------------------------------------------------------------------------------------
                       ema_10        ema_20        ema_40        ema_80        ema_320
time                    
2001-01-02 23:03:00    114.430000    114.430000    114.430000    114.430000    114.430000
2001-01-02 23:48:00    114.413500    114.414250    114.414625    114.414813    114.414953
2001-01-03 00:03:00    114.408073    114.409017    114.409504    114.409751    114.409938
2001-01-03 00:18:00    114.412002    114.412188    114.412328    114.412410    114.412477
2001-01-03 00:33:00    114.420040    114.418915    114.418429    114.418207    114.418050
ema_count = 0

if ema['ema_10'].shift(1) > ema['ema_20'].shift(1) > ema['ema_40'].shift(1) > ema['ema_80'].shift(1) > ema['ema_320'].shift(1) \
or ema['ema_10'].shift(1) < ema['ema_20'].shift(1) < ema['ema_40'].shift(1) < ema['ema_80'].shift(1) < ema['ema_320'].shift(1):
    dropna_df['perfect_order'] = 1
else:
    if ema['ema_10'] > ema['ema_20'] > ema['ema_40'] > ema['ema_80'] > ema['ema_320'] \
    or ema['ema_10'] < ema['ema_20'] < ema['ema_40'] < ema['ema_80'] < ema['ema_320']:
        ema_count += 1
        dropna_df['perfect_order'] = 1
    else:
        dropna_df['perfect_order'] = 0

試したこと

そもそもshift()で解決できるのだろうかと思っている。
iterrows()で一行ずつ取り出して処理していったら良いのかなと思い下記のコードでどういう値が取り出せるかを見てみるとタプルが返ってきた。

for row in ema.iterrows():
    print(row)
    break
[Timestamp('2001-01-02 23:03:00'), ema_10     114.43
ema_20     114.43
ema_40     114.43
ema_80     114.43
ema_320    114.43
Name: 2001-01-02 23:03:00, dtype: float64]

print(row[0])だと
2001-01-02 23:03:00

print(row[1])だと
ema_10     114.43
ema_20     114.43
ema_40     114.43
ema_80     114.43
ema_320    114.43
Name: 2001-01-02 23:03:00, dtype: float64

print(row[2])だと
IndexError: tuple index out of range

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

まず、すべてのデータをshift()するよりも、行ごとの結果を求めてその結果をshift()したほうが簡単かと思います。

でデータの判定ですが、

  • 行の値の並びが単調増加is_monotonic_increasingである または 単調減少is_monotonic_decreasingである
  • なおかつ 同じ値が存在しない(nunique() == 5)

という条件ではどうでしょうか

コードとしては以下のようになります。

import pandas as pd
import io

data="""
time,ema_10,ema_20,ema_40,ema_80,ema_320
2001-01-02 23:03:00,114.430000,114.430000,114.430000,114.430000,114.430000
2001-01-02 23:48:00,114.413500,114.414250,114.414625,114.414813,114.414953
2001-01-03 00:03:00,114.408073,114.409017,114.409504,114.409751,114.409938
2001-01-03 00:18:00,114.412002,114.412188,114.412328,114.412410,114.412477
2001-01-03 00:33:00,114.420040,114.418915,114.418429,114.418207,114.418050
"""

df = pd.read_csv(io.StringIO(data), parse_dates=['time'], index_col='time')

df['perfect_order'] = ((df.apply(lambda s: s.is_monotonic_increasing, axis=1) | df.apply(lambda s: s.is_monotonic_decreasing, axis=1)) & (df.nunique(axis=1) == 5)).astype('uint8').shift(1)
print(df)
#                         ema_10      ema_20      ema_40      ema_80     ema_320  perfect_order 
#time
#2001-01-02 23:03:00  114.430000  114.430000  114.430000  114.430000  114.430000            NaN
#2001-01-02 23:48:00  114.413500  114.414250  114.414625  114.414813  114.414953            0.0
#2001-01-03 00:03:00  114.408073  114.409017  114.409504  114.409751  114.409938            1.0
#2001-01-03 00:18:00  114.412002  114.412188  114.412328  114.412410  114.412477            1.0
#2001-01-03 00:33:00  114.420040  114.418915  114.418429  114.418207  114.418050            1.0

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/23 00:01

    ありがとうございます。無事動きました。

    キャンセル

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

  • ただいまの回答率 88.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る