In Pandas dataframe, using boolean output, how to detect crossovers of two different columns (lines)?
--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Lost Civilization
--
Chapters
00:00 In Pandas Dataframe, Using Boolean Output, How To Detect Crossovers Of Two Different Columns (Lines)
02:03 Accepted Answer Score 0
02:51 Thank you
--
Full question
https://stackoverflow.com/questions/6714...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #pandas #dataframe
#avk47
    Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Lost Civilization
--
Chapters
00:00 In Pandas Dataframe, Using Boolean Output, How To Detect Crossovers Of Two Different Columns (Lines)
02:03 Accepted Answer Score 0
02:51 Thank you
--
Full question
https://stackoverflow.com/questions/6714...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #pandas #dataframe
#avk47
ACCEPTED ANSWER
Score 0
The issue is the use of and. For a boolean comparison of array-like objects you want to use & (see this question). Moreover, you need to make sure to use parenthesis to separate the logical & from the tests with < and >. Finally, the function cond1 updates the dataframe df in place, so there is no need to use return at the end of the function.
In summary:
 def cond1(df):
     df.loc[:, ('cond1a')] = (df.LineA < df.LineB) & (df.LineA.shift(1) > df.LineB.shift(1))
     df.loc[:, ('cond1b')] = (df.LineA.shift(1) < df.LineB.shift(1)) & (df.LineA.shift(2) > df.LineB.shift(2))
     df.loc[:, ('cond1')] = df[['cond1a', 'cond1b']].all(axis=1)
Edit: Regarding your first question, it might be easier to do first a comparison between lineA and lineB to get a boolean index and then check when this index flips from True to False. This will give you all crossover points so far:
cond = df.lineA < df.lineB  # checks for all times whether lineB is above lineA
cond != cond.shift(1)  # returns True for all times, where lineB dips below lineA