I have a df as follows which shows when a person started a shift, ended a shift, the amount of hours and the date worked.
Business_Date Number PayTimeStart PayTimeEnd Hours
0 2019-05-24 1 2019-05-24 11:00:00 2019-05-24 12:15:00 1.250
1 2019-05-24 2 2019-05-24 12:30:00 2019-05-24 13:30:00 1.00
Now what I'm trying to do is break this into an hourly format, so I know how many hours were used between 11:00 - 12:00
so, in my head, for the above, I want to put the 1 hour between 11 - 12 into the bin for 11:00 and the remainder 0.25 into the next bin of 12
so I would end up with something like
Business Date Time Hour
0 2019-05-24 11:00 1
1 2019-05-24 12:00 0.75
2 2019-05-24 13:00 0.5
One idea is working with minutes - first use list comprehension with flattening for Series
and then grouping by hours
with hour
s for count by GroupBy.size
and last divide by 60
for final hours:
s = pd.Series([z for x, y in zip(df['Pay Time Start'], df['Pay Time End'] - pd.Timedelta(60, unit='s')) for z in pd.date_range(x, y, freq='Min')])df = (s.groupby([s.dt.date.rename('Business Date'), s.dt.hour.rename('Time')]).size().div(60).reset_index(name='Hour'))
print (df)Business Date Time Hour
0 2019-05-24 11 1.00
1 2019-05-24 12 0.75
2 2019-05-24 13 0.50
If you need to group by a location or ID
df1 = pd.DataFrame([(z, w) for x, y, w in zip(df['Pay Time Start'], df['Pay Time End'] - pd.Timedelta(60, unit='s'), df['Location']) for z in pd.date_range(x, y, freq='Min')], columns=['Date','Location']) df = (df1.groupby([df1['Date'].dt.date.rename('Business Date'), df1['Date'].dt.hour.rename('Time'), df1['Location']]) .size() .div(60) .reset_index(name='Hour'))