Reputation: 1354
I am attempting to create a conditional running sum in pandas based on two conditions.
import pandas as pd
ID = [1,1,1,2,2,3,4]
after = ['A','B','B','A','A','B','A']
before = ['A','B','B','A','A','B','A']
df = pd.DataFrame([ID, before,after]).T
df.columns = ['ID','before','after']
The data looks like:
ID before after
0 1 A A
1 1 B B
2 1 B B
3 2 A A
4 2 A A
5 3 B B
6 4 A A
I then want to look at how long an ID has had the value of before as B, my attempt:
df['time_on_b'] = (df.groupby('before')['ID'].cumcount()+1).where(df['before']=='B',0)
This gives me:
ID before after time_on_b
0 1 A A 0
1 1 B B 1
2 1 B B 2
3 2 A A 0
4 2 A A 0
5 3 B B 3
6 4 A A 0
The ideal output is as followed:
ID before after time_on_b
0 1 A A 0
1 1 B B 1
2 1 B B 2
3 2 A A 0
4 2 A A 0
5 3 B B 1
6 4 A A 0
As you can see as the ID changes I want time_on_b to reset so it gives me the value of 1 and not 3.
Upvotes: 3
Views: 1785
Reputation: 772
You could also use transform
like
df.groupby('ID').before.transform(lambda x: x.eq('B').cumsum())
0 0
1 1
2 2
3 0
4 0
5 1
6 0
Name: before, dtype: int32
df.assign(time_on_b=df.groupby('ID').before.transform(lambda x: x.eq('B').cumsum()))
ID before after time_on_b
0 1 A A 0
1 1 B B 1
2 1 B B 2
3 2 A A 0
4 2 A A 0
5 3 B B 1
6 4 A A 0
Upvotes: 3
Reputation: 215047
Seems you need to group by ID
, then use cumsum
to count the occurrences of B
:
cond = df.before == 'B'
df['time_on_b'] = cond.groupby(df.ID).cumsum().where(cond, 0).astype(int)
df
# ID before after time_on_b
#0 1 A A 0
#1 1 B B 1
#2 1 B B 2
#3 2 A A 0
#4 2 A A 0
#5 3 B B 1
#6 4 A A 0
Upvotes: 7