【问题标题】:Pair of employees that worked together for the longest period of time - Python/Pandas一起工作时间最长的一对员工——Python/Pandas
【发布时间】:2019-06-07 14:27:00
【问题描述】:

我最近不得不编写一个代码,它返回在一个共同项目上合作最多的员工对。这是我想出的代码:

注意 1:Null 被程序读取为“今天”

注2:数据来自一个.txt文件,格式如下:

EmpID,ProjectID,DateFrom,DateTo
1,101,2014-11-01,2015-05-01
1,103,2013-11-01,2016-05-01
2,101,2013-12-06,2014-10-06
2,103,2014-06-05,2015-05-14
3,100,2016-03-01,2018-07-03
3,102,2015-06-04,2017-09-04
3,103,2015-06-04,2017-09-04
4,102,2013-11-13,2014-03-13
4,103,2016-02-14,2017-03-15
4,104,2014-10-01,2015-12-01
5,100,2013-03-07,2015-11-07
5,101,2015-07-09,2019-01-19
5,102,2014-03-15,NULL
6,101,2014-03-15,2014-03-16

我目前遇到的问题是我必须调整/更改代码以返回彼此合作时间最长的一对员工(不是在单个项目上,而是在所有项目上合并)。我在调整我当前的代码时遇到了麻烦,它运行得非常好,我想知道我是否应该从头开始(但这会花费我很多时间,我不这样做)目前没有)。我很难获得一起参与项目的员工组合。

如果有人能给我任何提示,我将不胜感激!谢谢!

编辑1:cmets中的一个人提醒我提一下重叠天数应该算作例子:

整个 6 月,A 人和 B 人在两个项目上工作。这意味着它应计为 30 天的总共同工作(对于两个项目),而不是将两个项目时间加在一起,即为 60 天。

【问题讨论】:

  • 是否应该计算或忽略不同项目的重叠天数? IE。如果第 1 人和第 2 人在整个 6 月都在项目 A 和 B 上工作,那么他们有 30 天还是 60 天一起工作?
  • @ALollz 感谢您的提醒,我会将其添加到帖子中。对于您的示例,这意味着 30 天(因为他们只在整个 6 月份一起工作)。
  • 这个问题与您的other one 有何不同?如果您参考上下文,它会有所帮助。
  • 另外,我们大概谈论了多少项目和员工?这使某些事情或多或少可行
  • 另一个极大地帮助我解决了我之前的任务(一个共同项目中最长的工作对)。现在任务不同了,我必须调整我当前的代码,这还不够(或者至少我还没有弄清楚)。 @ALollz 查看帖子中的示例 .txt 文件。这大概就是我所需要的。

标签: python pandas csv datatables combinations


【解决方案1】:

这是我能想到的更直接的方法之一。

  1. 将时间跨度扩展到每个日期的一行。
  2. 合并同一项目的所有 Days(以获取所有一起工作的人的组合)
  3. 删除在同一天一起工作但不同项目的重复行。
  4. 只需找出每个工人配对中有多少行。

代码:

import pandas as pd
import numpy as np

def expand_period_daily(df, start, stop):
    # Allows it to work for one day spans. 
    df.loc[df[stop].notnull(), stop] = (df.loc[df[stop].notnull(), stop] 
                                        + pd.Timedelta(hours=1))

    real_span = df[[start, stop]].notnull().all(1)

    # Resample timespans to daily fields. 
    df['temp_id'] = range(len(df))
    dailydf = (df.loc[real_span, ['temp_id', start, stop]].set_index('temp_id').stack()
                 .reset_index(level=-1, drop=True).rename('period').to_frame())
    dailydf = (dailydf.groupby('temp_id').apply(lambda x: x.set_index('period')
                      .resample('d').asfreq()).reset_index())

    # Merge back other information
    dailydf = (dailydf.merge(df, on=['temp_id'])
                      .drop(columns=['temp_id', start, stop]))

    return dailydf

# Make dates, fill missings.
df[['DateFrom', 'DateTo']] = df[['DateFrom', 'DateTo']].apply(pd.to_datetime, errors='coerce')
df[['DateFrom', 'DateTo']] = df[['DateFrom', 'DateTo']].fillna(pd.to_datetime('today').normalize())

dailydf = expand_period_daily(df.copy(), start='DateFrom', stop='DateTo')

# Merge, remove rows of employee with him/herself.
m = (dailydf.merge(dailydf, on=['period', 'ProjectID'])
            .loc[lambda x: x.EmpID_x != x.EmpID_y])

# Ensure A-B and B-A are grouped the same
m[['EmpID_x', 'EmpID_y']] = np.sort(m[['EmpID_x', 'EmpID_y']].to_numpy(), axis=1)

# Remove duplicated projects on same date between employee pairs
m = m.drop_duplicates(['period', 'EmpID_x', 'EmpID_y'])

m.groupby(['EmpID_x', 'EmpID_y']).size().to_frame('Days_Together')

输出:

                 Days_Together
EmpID_x EmpID_y               
1       2                  344
        3                  333
        4                   78
2       6                    2
3       4                  396
        5                  824

测试用例

为了更清楚地说明它如何处理重叠以及组合不同的项目,以下是以下测试用例:

   EmpID  ProjectID   DateFrom     DateTo
0      1        101 2014-11-01 2014-11-15
1      1        103 2014-11-01 2014-11-15
2      1        105 2015-11-02 2015-11-03
3      2        101 2014-11-01 2014-11-15
4      2        103 2014-11-01 2014-11-15
5      2        105 2015-10-02 2015-11-05
6      3        101 2014-11-01 2014-11-15

员工 1 和 2 在 2014 年 11 月的 2 个项目上完全重叠了 15 天。然后,他们在 2015 年的另一个项目上一起工作了 2 天。1、2 和 3 一起在一个项目上工作了 15 天。

运行我们得到的这个测试用例:

                 Days_Together
EmpID_x EmpID_y               
1       2                   17
        3                   15
2       3                   15

【讨论】:

  • 非常感谢您提出的解决方案!我喜欢所有可能的配对(并删除重复项 - 刚刚学会了 pandas 的这一强大功能!)在表中的结构,我想我只需要一个小的 panda 函数来显示 Days_Together 列中的最大值作为输出(其中很容易做到),它会完美地工作。我只有一个小问题,Days_Together 认为多个项目是对的——例如,1 和 2 在不同的时间段同时在项目 A 和项目 B 上工作,但他们的总工作时间合并在这个特定的单元格中?再次感谢您
  • @GerganZhekov Days_Together 是两个人一起工作的独特天数,并且不会重复计算他们在不同项目上合作的同一天,而是将所有可能的项目的天数合并。我用一个测试用例更新了解决方案,该测试用例应该阐明如何处理。
  • 你好!我认为 drop_duplicates 行中可能存在错误,因为我尝试了多次并且数据框不会删除额外的行(数以千计)。我尝试将信息放在一个子集中,然后'keep = False',但它仍然不起作用。
  • @GerganZhekov 这很奇怪。在测试用例中,它显然删除了重复项(因为 1 和 2 在同一天在 2 个项目上一起工作)所以如果它没有删除它们,你将得到 32 天,而不是 17 天。
猜你喜欢
  • 2013-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多