Thomas
Thomas

Reputation: 12107

track state reversal in Pandas by comparing two columns

This is a follow-on to my previous question: detecting value crossing between columns in Pandas

Let's assume I have two columns, df['a'] and df['b'], called 'a' and 'b' here to simplify

In the previous question, I was trying to detect indices where: a[i - 1] < b[i] and a[i] >= b[i]

now, I am trying to track two changes:

a[i - 1] < b[i] and a[i] >= b[i]

and

a[i - 1] >= b[i] and a[i] < b[i]

and create a column with a value set based on the LAST change that occurred.

Here is some pseudo code:

state = 0
result = []
for i in myIndex:
    if a[i - 1] < b[i] and a[i] >= b[i]:
        state = 1
    elif a[i - 1] >= b[i] and a[i] < b[i]:
        state = 0

result.append(state)

is there an idiomatic (non-looping) way to achieve this in Pandas?


Edit:

I realize this question has caused some confusion, so I didn't word it properly. An example here:

Let's assume I have two columns for the outputs of the two conditions I'm tracking:

 cond_A    cond_B
 false     false
 false     true
 false     false
 false     false
 true      false
 false     false

then the output should be (if we set 0 and 1 as output values):

cond_A    cond_B    output
false     false     0
false     true      1
false     false     1
false     false     1
true      false     0
false     false     0

so, if both conditions are false, we reuse the last state, if a condition is true, we set the state.

Upvotes: 1

Views: 117

Answers (2)

ansev
ansev

Reputation: 30920

this is the equation of a RS flip flop: https://en.wikipedia.org/wiki/Flip-flop_(electronics)

using the example given as a dataframe:

print(df)

   cond_A  cond_B
0   False   False
1   False    True
2   False   False
3   False   False
4    True   False
5   False   False

UPDATE

df['state']=df.any(axis=1).where(df['cond_B'].cumsum().ge(1),0).cumsum()%2
print(df)


   cond_A  cond_B  state
0   False   False      0
1   False    True      1
2   False   False      1
3   False   False      1
4    True   False      0
5   False   False      0

If you have two independent series

(cond_A | cond_B).where(cond_B.cumsum().ge(1),0).cumsum()%2

Upvotes: 1

abhilb
abhilb

Reputation: 5757

You can try

>>> df['c'] = pd.Series((df.a.shift(-1) < df.b) & (df.a >= df.b)).replace({False : 0, True : 1})
>>> df
    a   b  c
0   8  17  0
1   2  86  0
2  93  42  0
3  49   1  0
4  35  62  0
5   3  39  0
6  25  21  0
7  54  24  1
8   3  77  0
9  41  42  0

Upvotes: 0

Related Questions