Фрейм данных Pandas вычисляет разницу во времени для каждой группы и разницу во времени между двумя разными группами

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Я создал такой фрейм данных:

 import pandas as pd
d = {'Time': ['01.07.2019, 06:21:33', '01.07.2019, 06:32:01', '01.07.2019, 06:57:33', '01.07.2019, 07:24:33','01.07.2019, 08:26:25', '01.07.2019, 09:12:44']
     ,'Action': ['Opened', 'Closed', 'Opened', 'Closed', 'Opened', 'Closed']
     ,'Name': ['Bayer', 'Bayer', 'ITM', 'ITM', 'Geco' , 'Geco'],
               'Group': ['1', '1', '2','2','3','3']}
df = pd.DataFrame(data=d)

output:

    Time                    Action  Name    Group
0   01.07.2019, 06:21:33    Opened  Bayer   1
1   01.07.2019, 06:32:01    Closed  Bayer   1
2   01.07.2019, 06:57:33    Opened  ITM     2
3   01.07.2019, 07:24:33    Closed  ITM     2
4   01.07.2019, 08:26:25    Opened  Geco    3
5   01.07.2019, 09:12:44    Closed  Geco    3
 

итак, теперь я пытаюсь вычислить разницу во времени для каждой группы и разницу во времени между этими группами в минутах. Так, например, разница во времени в группе Bayer должна составлять 10 минут и 28 секунд, а разница во времени между Bayer и ITM должна составлять 25 минут и 32 секунды. После этого разница во времени между одной и той же группой должна отображаться в столбце в той же строке, где начинается группа, а разница во времени между двумя разными группами должна отображаться в другом столбце в той же строке, где заканчивается группа.

таким образом, желаемый результат будет:

     Time                    Action  Name    Group Time Difference(names) Time Difference(groups)
0   01.07.2019, 06:21:33    Opened  Bayer   1          10:28
1   01.07.2019, 06:32:01    Closed  Bayer   1                                   25:32
2   01.07.2019, 06:57:33    Opened  ITM     2          27:00         
3   01.07.2019, 07:24:33    Closed  ITM     2                                   1:01:52
4   01.07.2019, 08:26:25    Opened  Geco    3          46:19
5   01.07.2019, 09:12:44    Closed  Geco    3
 

как я мог это сделать?

Ответ №1:

Начните с создания даты и времени из строки, затем некоторых групп и различий:

 df["Time"] = pd.to_datetime(df["Time"])
df["d1"] = df.groupby("Name")["Time"].diff().shift(-1).fillna("")
df["d2"] = (
    df.groupby((df["Action"] == "Closed").cumsum())["Time"]
    .diff()
    .shift(-1)
    .fillna("")
)

 

производит

 |    | Time                | Action   | Name   |   Group | d1              | d2              |
|---:|:--------------------|:---------|:-------|--------:|:----------------|:----------------|
|  0 | 2019-01-07 06:21:33 | Opened   | Bayer  |       1 | 0 days 00:10:28 |                 |
|  1 | 2019-01-07 06:32:01 | Closed   | Bayer  |       1 |                 | 0 days 00:25:32 |
|  2 | 2019-01-07 06:57:33 | Opened   | ITM    |       2 | 0 days 00:46:19 |                 |
|  3 | 2019-01-07 07:24:33 | Closed   | ITM    |       2 |                 | 0 days 01:01:52 |
|  4 | 2019-01-07 08:26:25 | Opened   | Geco   |       3 | 0 days 00:27:00 |                 |
|  5 | 2019-01-07 09:12:44 | Closed   | Geco   |       3 |                 |                 |
 

чтобы немного объяснить d2 вычисление, это (df['Action'] == 'Closed').cumsum() увеличивается на 1 для каждой новой 'Closed' строки. Здесь я печатаю его рядом Action для наглядности, используя это

 df['d2_cond'] = (df['Action'] == 'Closed').cumsum()
df[['Action', 'd2_cond']]
 

С принтами

 
Action  d2_cond
0   Opened  0
1   Closed  1
2   Opened  1
3   Closed  2
4   Opened  2
5   Closed  3
 

таким образом, мы можем groupby в этом списке объединить каждую Closed с соответствующей следующей Opened

Комментарии:

1. отличный ответ. можете ли вы разработать создание d2, было бы полезно немного объяснений.

2. @piterbarg так что все работает нормально!! отлично! Еще один вопрос: если время в следующей строке, например, на следующий день, можно ли рассчитать с самого начала? так что не то, что есть, как 1 день и 20 минут

3. @Arthi Рад, что это помогло. Однако я не уверен, что понимаю ваш последующий вопрос. с начала чего?

4. @piterbarg так, например: если у нас в фрейме данных одно и то же имя, но дата другая: ( 01.07.2019 14:55:57, Открыт, ITM, 1), (02.07.2019 06:55:12, Закрыто, ITM) это рассчитало бы весь день, так как же я мог это сделатьесли в следующей строке появится следующий день, он должен остановиться в 14:55:57 и вычислить с 0 на следующий день?

5. вы можете вычислить смещение для каждой временной метки с полуночи этого дня примерно так df['d3'] = df['Time'].apply(lambda d: d - d.floor('d')) .