Панды группируются по временным интервалам

У меня есть два фрейма данных. DF1 содержит следующее:

Пользователь | Интервал времени

Пользователь01 | [01.01.2014 08:12:00, 01.01.2014 08:13:43]

Пользователь02 | [03.01.2014 07:21:44, 04.01.2014 01:07:01]

DF 2 содержит события:

Пользователь | Время | Ценность

Пользователь01 | 03.01.2014 04:11:00 | 9

Пользователь01 | 01.01.2014 08:10:00 | 12

Пользователь02 | 03.01.2014 09:11:00 | 3

Пользователь02 | 02.01.2014 011:10:00 | 21

Я хочу добавить 3 столбца в DF1, содержащие среднее значение, стандартное отклонение и максимальное значение для каждого пользователя в течение интервала времени на основе событий в DF2.

Таким образом, окончательный результат должен выглядеть так:

Пользователь | Временной интервал | Среднее | Макс | СтДев

Пользователь01 | [01.01.2014 08:12:00, 01.01.2014 08:13:43] | NaN | NaN | Нэн

Пользователь02 | [03.01.2014 07:21:44, 04.01.2014 01:07:01] | 3 | 3 | 0

Каков эффективный способ сделать это, если мои таблицы большие? Есть ли какая-то функция groupby для временных интервалов, основанных на другом кадре данных?

Код:

import pandas as pd

DF1 = pd.DataFrame({'User' : pd.Series(["User01", "User02"], index=['1', '2']), 'Time start' : pd.Series(["01/01/2014 08:12:00", "01/03/2014 07:21:44"], index=['1', '2']),'Time end' : pd.Series(["01/01/2014 08:13:43", "01/04/2014 01:07:01"], index=['1', '2'])})

DF2 = pd.DataFrame({'User' : pd.Series(["User01","User01","User02", "User02"], index=['1', '2','3','4']), 'Time' : pd.Series(["01/03/2014 04:11:00", "01/01/2014 08:10:00","01/03/2014 09:11:00","01/02/2014 011:10:00"], index=['1', '2','3', '4']),'Value' : pd.Series([9,12,3,21], index=['1', '2','3','4'])})

DF3 = pd.DataFrame({'User' : pd.Series(["User01", "User02"], index=['1', '2']), 'Time start' : pd.Series(["01/01/2014 08:12:00", "01/03/2014 07:21:44"], index=['1', '2']),'Time end' : pd.Series(["01/01/2014 08:13:43", "01/04/2014 01:07:01"], index=['1', '2']),'Mean' : pd.Series(["Nan", 3], index=['1', '2']),'Max' : pd.Series(["Nan", 3], index=['1', '2']),'StDev' : pd.Series(["Nan", 0], index=['1', '2'])})

person Alexis Eggermont    schedule 23.09.2014    source источник
comment
Полезно иметь примеры, которые можно копировать. Также опубликуйте, как должно выглядеть ожидаемое решение с приведенными вами примерами. Это можно сделать, разделив столбец Time interval на два, нижний и верхний, а затем используя что-то вроде between_time во втором кадре данных.   -  person TomAugspurger    schedule 23.09.2014
comment
Спасибо. Можете ли вы указать, что вы подразумеваете под копируемым примером?   -  person Alexis Eggermont    schedule 23.09.2014
comment
Вы говорите, как выглядят ваши кадры данных, но не предоставляете код для их создания. Это означает, что любой, кто попытается помочь вам, сначала должен будет написать код для создания этих фреймов данных. Гораздо проще скопировать и вставить свой код, чтобы достичь той же точки, в которой вы сейчас находитесь, чем тратить время на воссоздание ваших структур данных. Попробуйте выполнить df.to_dict() на своих объектах, а затем отправьте код, например DF1 = pandas.DataFrame({'User': ...}) и т. д., вместо того, чтобы просто описывать то, что у вас есть, словами.   -  person chthonicdaemon    schedule 23.09.2014
comment
Сначала вы должны очистить свои кадры, хорошее начало - извлечь начало и конец ваших временных интервалов в виде столбцов даты и времени. Неясно, уникальны ли пользователи (вас интересует только их поведение в течение одного временного интервала? Если да, это упрощает задачу.)   -  person Andy Hayden    schedule 23.09.2014
comment
Понятно. Добавлен код для создания DF. Разделенное время начала и окончания тоже. Глядя на between_time сейчас.   -  person Alexis Eggermont    schedule 23.09.2014
comment
Похоже, between_time работает только для времени, а не для даты и времени. Есть ли еще один трюк, который позволяет мне сохранять только строки между датами?   -  person Alexis Eggermont    schedule 23.09.2014
comment
Этот вопрос задавался несколько раз. Вот пример, который я связан с, который имеет несколько ответов.   -  person LondonRob    schedule 25.06.2015


Ответы (1)


Сначала объедините DF1 и DF2.

df = DF2.merge(DF1,on="User")

и создайте индикатор («сохранить»), если время попадает между началом времени и окончанием времени

import numpy as np
df.loc[:,"keep"] = (np.logical_and(df.loc[:,"Time start"]<=df.loc[:,"Time"],df.loc[:,"Time"]<=df.loc[:,"Time end"]))*1

Выход:

    Time                User  Value Time end            Time start       keep
 2014-01-03 04:11:00    User01  9   2014-01-01 08:13:43 2014-01-01 08:12:00 0
 2014-01-01 08:10:00    User01  12  2014-01-01 08:13:43 2014-01-01 08:12:00 0
 2014-01-03 09:11:00    User02  3   2014-01-04 01:07:01 2014-01-03 07:21:44 1
 2014-01-02 11:10:00    User02  21  2014-01-04 01:07:01 2014-01-03 07:21:44 0

Теперь сохраняйте только те строки, где keep=1

df = df.loc[df.keep==1,:]

Теперь выполните агрегирование по df с помощью groupby

df4 = df.groupby("User")["Value"].agg(['max','mean','std']).reset_index()

выход:

    User    max mean    std
    User02  3   3   NaN

объединить df4 с DF1

DF1.merge(df4.reset_index(), on="User",how="left")

выход:

 Time end           Time start          User    max mean std
2014-01-01 08:13:43 2014-01-01 08:12:00 User01  NaN NaN NaN
2014-01-04 01:07:01 2014-01-03 07:21:44 User02  3.0 3.0 NaN
person Sahil Dahiya    schedule 22.12.2017
comment
Человек, который проголосовал за мой ответ, пожалуйста, дайте мне знать, почему? так что я могу помочь вам с этим. - person Sahil Dahiya; 23.12.2017