Identify groups that have an A-B-A change

Viewed 36

I have to find occurrences in the data that match a change like 'A-B-A'. I have my dataset grouped and sorted in the correct way. The values that need to be compared are the columns VAL1 and VAL2. In this example they are numbers, but they might be string values as well.

Sample Data explanation

All values of VAL1 and VAL2 in group 1 are different and I'm not interested in these A-B-C changes.

All values of VAL1 and VAL2 in group 2 are the same, which is fine too. Changes like A-A-A or even A-A-B-B-B-C are fine and I'm not interested in those either.

In group 3 the first and the third VAL1 and VAL2 are the same. So this is the kind of A-B-A change I'm looking for. Also changes like

  • A-B-C-B
  • A-B-C-D-A

I am interested in. Basically it does not matter where in the group the previous same row is, as long as there is a different row in between I'm interested in this Group

import pandas as pd

df = pd.DataFrame([
     [273,1,'01.01.2016','16.02.2017','23154','1'],
     [273,1,'16.03.2017','31.10.2019','48625','1'],
     [273,1,'01.11.2019','31.12.2099','32007','1'],
     [274,2,'01.01.2016','16.02.2017','23154','1'],
     [274,2,'16.03.2017','31.10.2019','23154','1'],
     [275,3,'01.01.2016','16.02.2017','78945','1'],
     [275,3,'16.03.2017','31.10.2019','48625','2'],
     [275,3,'01.11.2019','31.12.2099','78945','1'],
 ], columns=['ID','GROUP','FROM','UNTIL','VAL1','VAL2'])

What I want

I would like the resulting dataframe to only have the groups which do have a kind of A-B-A change in them.

So in my example data only the rows of group 3 would remain.

My attempt at the problem

My Idea is to first find any duplicates for each group, then check in the group with duplicates if there are any A-B-A changes and last only select the groups that fullfill the criteria.

So I ran the pandas duplicate function like this

df['DUPES'] = df.duplicated(subset=['GROUP', 'VAL1', 'VAL2'], keep=False)

and got following dataframe, but I do not know how to progress from this point on.

ID Group From Until Val1 Val2 Dupes
0 273 1 01.01.2016 16.02.2017 23154 1 False
1 273 1 16.03.2017 31.10.2019 48625 1 False
2 273 1 01.11.2019 31.12.2099 32007 1 False
3 274 2 01.01.2016 16.02.2017 23154 1 True
4 274 2 16.03.2017 31.10.2019 23154 1 True
5 275 3 01.01.2016 16.02.2017 78945 1 True
6 275 3 16.03.2017 31.10.2019 48625 2 False
7 275 3 01.11.2019 31.12.2099 78945 1 True

Next I would need to check if there are are A-B-A changes in a group I'd like to find. So my Idea is to check each member in the group

  • If it is the first item in the group and it is a Dupe it should be ignored
  • If it is NOT the first but a Dupe AND
    • the previous entry in the group has the same Val1 and Val2 it is a valid A-A change
    • the previous entry in the group has NOT the same Val1 and Val2 found an A-B-A change

I know I can use a mask like df['VAL1'].eq(df['VAL1'].shift()) & df['VAL2'].eq(df['VAL2'].shift()) to compare with the previous value, but how would I limit this to the group? Also I'm not checking if the value is ...

Edit: I played around a little more and came up with this mask

df['DUPES2'] = df['DUPES'] & df['GROUP'].eq(df['GROUP'].shift()) & ~(df['VAL1'].eq(df['VAL1'].shift()) & df['VAL2'].eq(df['VAL2'].shift()))

The resulting dataframe looks fine, but I still do not know how to only select the groups

ID Group From Until Val1 Val2 Dupe2 Dupes2
0 273 1 01.01.2016 16.02.2017 23154 1 False False
1 273 1 16.03.2017 31.10.2019 48625 1 False False
2 273 1 01.11.2019 31.12.2099 32007 1 False False
3 274 2 01.01.2016 16.02.2017 23154 1 True False
4 274 2 16.03.2017 31.10.2019 23154 1 True False
5 275 3 01.01.2016 16.02.2017 78945 1 True False
6 275 3 16.03.2017 31.10.2019 48625 2 False False
7 275 3 01.11.2019 31.12.2099 78945 1 True True

Question to the community

Is there any other way how I could utilize pandas functionality to achieve my goal?

Thanks for helping

0 Answers
Related