42561
1分毎に、OP、HP、LP、CP、A、Bの値を取ったデータがあります。  
(列BはAが3以上となる場合を1、そうでない場合は0としている列です)

ここで、Bが1となる時のCPの値からLPがn分以内に2000以上下がる時にTrue、そうでない場合をFalseとするような列Cを作ろうと思いました。

作成したコードは以下の通りです。(ohlcと言う名前のcsvからデータを読み込んでいます。このcsvファイルは
<https://free.filesend.to/filedn_infoindex?rp=1da6d667519e74efb78c8265cedb405o>
からダウンロードできます)

```

    import pandas as pd
    import numpy as np
    
    n=10
    margin=2000
    
    df=pd.read_csv('ohlc', header=0)
    Bsum=df['B'].sum()
    
    for i in range(1,n):
      df['C']=False
      for j in range(1,i+1):
        df['C']=df['C']|(df['CP']-df['LP'].shift(-i)>=margin)
      df['C']=df['C']&df['B']
    
      print("C/B n="+str(i)+": "+str(df['C'].sum()/Bsum))
    
```

コードでは、Bが1となる時に、列Cが1(True)となる割合をnの数値ごとに画面に出力しています。  
この割合は、nの値が増えるごとに増えていくはずです。  
(6分以内に2000以上下がる場合の数より、7分以内に2000以上下がる場合の数の方が多くなるはず)

しかし、n=10で試してみると、

```

    C/B n=5: 0.271777003484
    C/B n=6: 0.289198606272
    C/B n=7: 0.271777003484
    
```

となり、n=6からn=7にかけ減少していて、意図した結果になっていません。

このコードは何が間違っているのでしょうか？  
また、より効率の良いコードにするための案(例えば、二番目のforループはpandsの機能を用いれば実は無くせるなど)がありましたら、ご教示頂けると有り難いです。
CC BY-SA 3.0
2018-03-21T07:50:12.107
42538
2018-03-22T04:40:11.823
2018-03-21T09:12:29.897
25791
25791
question
python pandas
Pythonのpandasを用いて、特定のセルとその後ろの複数行(列が異なる)を用いた条件から、新たな列を作成する方法
結果が意図したものになっていない理由は

```

    for i in range(1,n):
        df['C']=False
        # ...略
    
```

と **'C列'** の値をループ毎に初期化していることが原因かと思われまので  
この部分を

```

    df['C']=False
    for i in range(1,n):
        # ...略
    
```

のように修正するとよいのではないでしょうか。

* * *

次に、より効率のよい方法ですが、

現在 for文にて処理している箇所は `rolling().min()` を使用して

```

    df['CX'] = ((df.CP-df.LP.rolling(n).min().shift(-(n-1))) >= margin) & df.B
    
```

のように書き換えることができます。
CC BY-SA 3.0
2018-03-22T04:40:11.823
42561
2018-03-22T04:40:11.823
24801
42538
answer