【问题标题】:Get maximum for each group based on time condition根据时间条件获取每个组的最大值
【发布时间】:2021-09-18 20:31:36
【问题描述】:

我有这个数据框df

   id        date     time  record
0   1  2021-07-08  3:00:00       8
1   1  2021-07-08  5:30:00       7
2   1  2021-07-08  9:00:00      10
3   1  2021-01-08  6:30:00       5
4   1  2021-01-08  9:30:00       7
5   2  2021-07-08  3:00:00       7
6   2  2021-07-08  9:00:00      14
7   2  2021-07-08  5:30:00      10
8   2  2021-01-08  3:00:00      11
9   2  2021-01-08  3:00:00      13

我需要创建一个新列 max 等于由 iddate 分组的最大值。但也只有当time 早于 7:00:00 时,我才需要获得最大值。即 id=1date=2021-07-08 max 列应该等于 8,而不是 10,因为当 time 是 9:00:00 时我们得到了 10。

这是数据框 df 以更易于访问的方式

import io
import pandas as pd

data1_txt = """
id,date,time,record
1,2021-07-08,3:00:00,8
1,2021-07-08,5:30:00,7
1,2021-07-08,9:00:00,10
1,2021-01-08,6:30:00,5
1,2021-01-08,9:30:00,7
2,2021-07-08,3:00:00,7
2,2021-07-08,9:00:00,14
2,2021-07-08,5:30:00,10
2,2021-01-08,3:00:00,11
2,2021-01-08,3:00:00,13
"""

df = pd.read_csv(io.StringIO(data1_txt))

理想的结果是

   id        date     time  record  max
0   1  2021-07-08  3:00:00       8    8
1   1  2021-07-08  5:30:00       7    8
2   1  2021-07-08  9:00:00      10    8
3   1  2021-01-08  6:30:00       5    5
4   1  2021-01-08  9:30:00       7    5
5   2  2021-07-08  3:00:00       7   10
6   2  2021-07-08  9:00:00      14   10
7   2  2021-07-08  5:30:00      10   10
8   2  2021-01-08  3:00:00      11   13
9   2  2021-01-08  3:00:00      13   13

【问题讨论】:

    标签: python pandas dataframe datetime


    【解决方案1】:

    让我们分步进行

    • 从时间列中提取小时部分
    • 将小时组件与7 进行比较以创建布尔掩码
    • 屏蔽record 列中小时大于7 的值
    • Groupiddatetransform 屏蔽的列使用max 计算每组的最大值
    m = pd.to_timedelta(df['time']).dt.components['hours'].ge(7)
    df['max'] = df['record'].mask(m).groupby([df['id'], df['date']]).transform('max')
    

       id        date     time  record   max
    0   1  2021-07-08  3:00:00       8   8.0
    1   1  2021-07-08  5:30:00       7   8.0
    2   1  2021-07-08  9:00:00      10   8.0
    3   1  2021-01-08  6:30:00       5   5.0
    4   1  2021-01-08  9:30:00       7   5.0
    5   2  2021-07-08  3:00:00       7  10.0
    6   2  2021-07-08  9:00:00      14  10.0
    7   2  2021-07-08  5:30:00      10  10.0
    8   2  2021-01-08  3:00:00      11  13.0
    9   2  2021-01-08  3:00:00      13  13.0
    

    【讨论】:

    • 最后一个问题,如果我想把时间限制从7:00:00改为7:15:00怎么办。 IE。我也需要分钟组件
    • @BogdanTitomir 在这种情况下,我们可以直接将 timedelta 对象与时间字符串进行比较,例如你可以做m = pd.to_timedelta(df['time']) >= '07:15:00'
    【解决方案2】:

    让我们确保时间是数据时间类型:

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

    7:00前过滤时间,分组并应用变换:

    s = df.loc[(df['time'] < '7:00')].groupby(['id', 'date'])['record'].transform('max').rename('max')
    

    合并结果并向前填充:

    df2 = pd.concat([df, s], axis=1)
    df2['max'] = df2['max'].ffill().astype(int)
    

    输出:

       id       date                time  record  max
    0   1 2021-07-08 2021-07-08 03:00:00       8    8
    1   1 2021-07-08 2021-07-08 05:30:00       7    8
    2   1 2021-07-08 2021-07-08 09:00:00      10    8
    3   1 2021-01-08 2021-07-08 06:30:00       5    5
    4   1 2021-01-08 2021-07-08 09:30:00       7    5
    5   2 2021-07-08 2021-07-08 03:00:00       7   10
    6   2 2021-07-08 2021-07-08 09:00:00      14   10
    7   2 2021-07-08 2021-07-08 05:30:00      10   10
    8   2 2021-01-08 2021-07-08 03:00:00      11   13
    9   2 2021-01-08 2021-07-08 03:00:00      13   13
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-28
      • 2020-08-12
      • 1970-01-01
      • 2021-06-05
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多