Мое решение работает также с данными с периодами присутствия, отличными от 1,5 часа, но даты должны быть от одного дня (в зависимости от того, как вы собрали данные образца).
Я прочиталваши данные как поля фиксированной ширины с преобразованием в datetime :
df = pd.read_fwf(pd.compat.StringIO(txt), colspecs=[(0, 15), (18, 33)],
names=['Sign In', 'Sign Out'], parse_dates=[0, 1])
, поэтому с самого начала у меня есть правильные типы данных (нет необходимости в дополнительных вызовах pd.to_datetime ).
Первым подготовительным шагом является создание IntervalIndex :
intervals = pd.IntervalIndex.from_arrays(df['Sign In'], df['Sign Out'], closed='left')
Следующим шагом является создание hrs - список полных часов:
hrs = pd.date_range(df['Sign In'].min(),
df['Sign Out'].max() + pd.Timedelta('1H'), freq='H')
Обратите внимание, что я добавил 1 дополнительный час к значению max , чтобы после каждого из них был "последний" часвышел.Что-то вроде последнего часа с 0 заполнением, как CHAMI .Если вам это не нужно, просто удалите этот дополнительный час.
Но нам нужна Series с индексом и значениями, установленными в эти часы, поэтому я создал также hours :
hours = pd.Series(hrs, index=hrs)
И, имея эти данные, фактическое вычисление может быть выполнено в виде single инструкции:
occupancy = hours.apply(lambda hr: np.count_nonzero(
intervals.map(lambda it: hr in it)))
Результат:
2018-01-01 09:00:00 1
2018-01-01 10:00:00 1
2018-01-01 11:00:00 5
2018-01-01 12:00:00 6
2018-01-01 13:00:00 4
2018-01-01 14:00:00 0
Freq: H, dtype: int64
Стоит сравнить с другими ответами:
- Ответ по CHAMI имеет тип данных float be int ).
- CHAMI Решение показывает занятость в 10:00 как 5 , тогда как в настоящее время фактически только 1 человек присутствовал.Клиенты с № 2 по 6 вошли позже ( после 10:00).
- Результаты за 10:00 и последующие часы в его решении "сдвинуты" на 1 час.
- Неправильно включать в начальные / конечные пробелы имена столбцов (как CHAMI ).
- krewsider на самом деле показывает только агрегацию знакасобытия входа / выхода , но не занятость.
- harvpan занял 1,5 шаг в часах (почему?).Другая деталь состоит в том, что он показывает занятость в 9: 00 как 4 (почему?), И его результат является далеко не полным.
Обратите внимание также на такойразница в том, что CHAMI показал 7 занятость в 11: 00 (на самом деле в 12: 00 ), но я показал 6.Причина в том, что я предположил, что если человек № 5 остался острым в 12: 00 , то в это время он уже отсутствовал .
Если вы хотите лечитьтакой человек, который все еще присутствует, измените атрибут closed IntervalIndex на 'Оба' и для ваших данных результат в 12: 00 будет 7 .