Разница во времени между первой и последней строкой в ​​группе в пандах

Вход

Date                  event   
2023-04-11 13:42:16   play   
2023-04-11 14:02:26   play 
2023-04-11 14:36:09   play 
2023-04-11 14:37:46   start
2023-04-11 14:41:34   start
2023-04-11 14:46:27   start
2023-04-11 14:47:03   start

Ожидается это в фрейме данных pandas. Сгруппировать по порядку событий по дате и разнице между первой и последней разницей времени.

выход

date          event   diff
2023-04-11    play    00:53:52 
2023-04-11    start   00:09:17
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
53
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Давайте сделаем groupby и agg с np.ptp т.е. (макс. - мин.)

df['Date'] = pd.to_datetime(df['Date'])
df.groupby(['event', df['Date'].dt.date])['Date'].agg(np.ptp).reset_index(name='diff')

Результат

   event        Date            diff
0   play  2023-04-11 0 days 00:53:53
1  start  2023-04-11 0 days 00:09:17

Используйте собственный groupby.agg:

df['Date'] = pd.to_datetime(df['Date'])

out = (
 df.groupby([df['Date'].dt.normalize(), 'event'])
   .agg(diff=('Date', lambda g: g.iloc[-1]-g.iloc[0]))
   .reset_index()
)

Или повторно используйте группировщик:

g = df.groupby([df['Date'].dt.normalize(), 'event'])['Date']

out = g.last().sub(g.first()).reset_index(name='diff')

Выход:

        Date  event            diff
0 2023-04-11   play 0 days 00:53:53
1 2023-04-11  start 0 days 00:09:17

Несортированный ввод

Если данные изначально не отсортированы, используйте min/max в качестве агрегации:

out = (
 df.groupby([df['Date'].dt.normalize(), 'event'])
   .agg(diff=('Date', lambda g: g.max()-g.min()))
   .reset_index()
)

Или:

g = df.groupby([df['Date'].dt.normalize(), 'event'])['Date']
out = g.max().sub(g.min()).reset_index(name='diff')

Это семантически идентично использованию np.ptp, но по какой-то причине (и, к сожалению), намного эффективнее. Здесь время на 700 тыс. строк:

# max - min 
99.7 ms ± 2.33 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# np.ptp
355 ms ± 43.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Это предполагает, что значения упорядочены от самого раннего к последнему, верно?

filpa 11.04.2023 17:26

@filpa да (похоже, здесь так и есть). Если нет, либо сначала sort_values, либо используйте min/max вместо iloc. Если данные уже отсортированы, это может быть более эффективно;)

mozway 11.04.2023 17:30

@filpa Я провел несколько тестов, и производительность между min/max и first/last на самом деле похожа, однако оба они намного быстрее, чем np.ptp (я хотел бы знать, почему, я представляю детали его реализации).

mozway 11.04.2023 17:42

@ rose1110 были ли проблемы с решением?

mozway 19.04.2023 20:32
df1.assign(date=df1.Date.dt.date).groupby('event',as_index=False)\
    .agg(date=("date",'first'),diff=("Date",lambda ss:str(ss.iat[-1]-ss.iat[0])[6:]))

Результат

   event        Date            diff
0   play  2023-04-11 0 days 00:53:53
1  start  2023-04-11 0 days 00:09:17

Другие вопросы по теме