【问题标题】:Python - Group by time periods with tolerancePython - 按具有容差的时间段分组
【发布时间】:2021-04-24 04:26:40
【问题描述】:

此数据集中存在三列:ID(唯一员工标识)、WorkComplete(指示所有工作何时完成)和 DateDiff(从开始日期算起的天数)。我希望根据某些时间段对 DaysDiff 列进行分组,并增加一层容忍或宽大处理。对于我的模拟数据,我将时间段间隔 30 天。

Group 0: 0-30 DateDiff (with a 30 day extra window if 'Y' is not found)
Group 1: 31-60 DateDiff (with a 30 day extra window if 'Y' is not found)
Group 2: 61-90 DateDiff (with a 30 day extra window if 'Y' is not found)

我能够创建非常基本的代码并分配分组,但我遇到了额外的 30 天窗口问题。例如,如果员工在上述时间段内完成了他们的工作 (Y),那么他们会收到属性分组。对于下面的 ID 111,您可以看到此人在前 30 天内没有完成他们的工作,所以我给他们额外的 30 天来完成他们的工作。如果他们完成了他们的工作,那么我们看到的第一个实例是“Y”,它被分组到之前的分组中。

df = pd.DataFrame({'ID':[111, 111, 111, 111, 111, 111, 112, 112, 112],
                   'WorkComplete':['N', 'N', 'Y', 'N', 'N', 'N', 'N', 'Y', 'Y'],
                   'DaysDiff': [0, 29, 45, 46, 47, 88, 1, 12, 89]})

输入

ID   WorkComplete      DaysDiff 
111  N                 0
111  N                 29
111  Y                 45
111  N                 46
111  N                 47
111  N                 88
123  N                 1 
123  Y                 12
123  Y                 89        

输出

ID   WorkComplete      DaysDiff   Group
111  N                 0          0
111  N                 29         0
111  Y                 45         0   <---- note here the grouping is 0 to provide extra time
111  N                 46         1   <---- back to normal
111  N                 47         1   
111  N                 88         2
123  N                 1          0
123  Y                 12         0
123  Y                 89         2
minQ1 = 0
highQ1 = 30
minQ2 = 31
highQ2 = 60
minQ2 = 61
highQ2 = 90

def Group_df(df):
    if (minQ1 <= df['DateDiff'] <= highQ1): return '0'
    elif (minQ1 <= df['DateDiff'] <= highQ1): return '1'
    elif (minQ2 <= df['DateDiff'] <= highQ2): return '2'

df['Group'] = df.apply(Group_df, axis = 1)

如果这个人没有完成工作,我遇到的麻烦是允许额外的 30 天。我的上述尝试是部分尝试解决问题。

【问题讨论】:

    标签: python python-3.x pandas datetime pandas-groupby


    【解决方案1】:
    1. 您可以使用np.select 作为主要条件。
    2. 然后,针对您提到的具体情况使用masks 是所有Y每组第一个索引位置。然后我暂时将assigns 作为一个新列,以便我可以针对df.index(索引)检查行以返回满足条件的行。第二个条件是如果组号是前面代码行中的1

    df['Group'] = np.select([df['DaysDiff'].between(0,30), 
                             df['DaysDiff'].between(31,60), 
                             df['DaysDiff'].between(61,90)],
                             [0,1,2])
    s = df[df['WorkComplete'] == 'Y'].groupby('ID')['DaysDiff'].transform('idxmin')
    df['Group'] = df['Group'].mask((df.assign(s=s)['s'].eq(df.index)) & (df['Group'].eq(1)), 0)
    df
    Out[1]: 
        ID WorkComplete  DaysDiff  Group
    0  111            N         0      0
    1  111            N        29      0
    2  111            Y        45      0
    3  111            N        46      1
    4  111            N        47      1
    5  111            N        88      2
    6  123            N         1      0
    7  123            Y        12      0
    8  123            Y        89      2
    

    【讨论】:

      猜你喜欢
      • 2017-06-15
      • 2020-08-28
      • 1970-01-01
      • 2019-01-23
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多