Count Consecutive Days Worked by Name and Date

Viewed 52

Fairly new to this so hopefully my query makes sense!

I have a dataset which covers numerous drivers and dates they have worked, example below:

Driver Date
Steve 11/02/2022
Steve 14/02/2022
Steve 15/02/2022
Steve 16/02/2022
Steve 17/02/2022
Steve 18/02/2022
Steve 20/02/2022
Graham 11/02/2022
Graham 12/02/2022
Graham 14/02/2022
Graham 15/02/2022
Graham 16/02/2022
Graham 18/02/2022
Graham 19/02/2022
Graham 20/02/2022

I am trying to calculate the consecutive days each has worked, to come out as below:

Driver Date Days
Steve 11/02/2022 1
Steve 14/02/2022 1
Steve 15/02/2022 2
Steve 16/02/2022 3
Steve 17/02/2022 4
Steve 18/02/2022 5
Steve 20/02/2022 1
Graham 11/02/2022 1
Graham 12/02/2022 2
Graham 14/02/2022 1
Graham 15/02/2022 2
Graham 16/02/2022 3
Graham 18/02/2022 1
Graham 19/02/2022 2
Graham 20/02/2022 3

So far i have managed to find the code below (by Grzegorz Skibinski on here) which seems to work in general. However i am getting some negative values, which seem to be calculated where it resets to 0 more than once. As i say i am fairly new to this and am not totally familiar with what the code is doing. I am just wondering if anything obvious stands out, or if this is not suitable for what i need.

    df3["Date"]=pd.to_datetime(df3["Date"])
    df3=df3.sort_values(["Driver", "Date"])
    
    df["Days"]=df.groupby("Driver")["Date"].diff()
    mask=df["Days"].isna()
    df["Days"]=df["Days"].eq(pd.to_timedelta("1 days"))
    df["Days"]=np.where(~df["Days"]&~mask, -df.groupby("Driver")["Days"].cumsum(), df["Days"])
    df["Days"]=df.groupby("Driver")["Days"].cumsum().add(1).astype(int)

Many thanks

1 Answers

Assuming that the dates are sorted, you can use:

# ensure datetime type
df['Date'] = pd.to_datetime(df['Date'])

# get non-consecutive days
s = df.groupby('Driver')['Date'].diff().ne('1d')

# groupby consecutive days and  cumulate the counts
df['Days'] = (~s).groupby([df['Driver'], s.cumsum()]).cumsum()+1

output:

    Driver       Date  Days
0    Steve 2022-02-11     1
1    Steve 2022-02-14     1
2    Steve 2022-02-15     2
3    Steve 2022-02-16     3
4    Steve 2022-02-17     4
5    Steve 2022-02-18     5
6    Steve 2022-02-20     1
7   Graham 2022-02-11     1
8   Graham 2022-02-12     2
9   Graham 2022-02-14     1
10  Graham 2022-02-15     2
11  Graham 2022-02-16     3
12  Graham 2022-02-18     1
13  Graham 2022-02-19     2
14  Graham 2022-02-20     3
Related