【问题标题】:Pandas dataframe Groupby and retrieve date rangePandas 数据框 Groupby 和检索日期范围
【发布时间】:2019-03-31 03:10:32
【问题描述】:

这是我正在处理的数据框。定义了两个支付期: 每个月的前 15 天和后 15 天。

         date  employee_id hours_worked   id job_group  report_id
0  2016-11-14            2         7.50  385         B         43
1  2016-11-15            2         4.00  386         B         43
2  2016-11-30            2         4.00  387         B         43
3  2016-11-01            3        11.50  388         A         43
4  2016-11-15            3         6.00  389         A         43
5  2016-11-16            3         3.00  390         A         43
6  2016-11-30            3         6.00  391         A         43

我需要同时按employee_id 和job_group 分组 我必须达到该分组行的日期范围。

例如,对于employee_id 1,分组结果如下所示:

预期输出:

         date  employee_id hours_worked  job_group  report_id
1  2016-11-15            2         11.50        B         43
2  2016-11-30            2         4.00         B         43
4  2016-11-15            3         17.50        A         43
5  2016-11-16            3         9.00         A         43

这可以使用 pandas 数据框 groupby 吗?

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    SMGrouper 一起使用,最后添加SemiMonthEnd

    df['date'] = pd.to_datetime(df['date'])
    
    d = {'hours_worked':'sum','report_id':'first'}
    df = (df.groupby(['employee_id','job_group',pd.Grouper(freq='SM',key='date', closed='right')])
           .agg(d)
           .reset_index())
    
    df['date'] = df['date'] + pd.offsets.SemiMonthEnd(1)
    print (df)
       employee_id job_group       date  hours_worked  report_id
    0            2         B 2016-11-15          11.5         43
    1            2         B 2016-11-30           4.0         43
    2            3         A 2016-11-15          17.5         43
    3            3         A 2016-11-30           9.0         43
    

    【讨论】:

    • 好的,试过了,但不知何故它不适用于我提供的数据集。
    • @Kishan - 你能创建minimal, complete, and verifiable example 吗?还是更多具有预期输出的数据行?
    • 第一行数据是 2016-11-14,它应该在 2016-11-15 括号内,但它进入了 2016-10-31 括号
    【解决方案2】:

    一个。首先,(对于每个employee_id)在hours_worked 列上使用multiple Grouper.sum()。二、使用DateOffset实现双周date栏目。在这两个步骤之后,我根据 2 个括号(日期范围)在分组 DF 中分配了 date - 如果 day of month (from the date column) date 中的 day 设置为 15,否则我将day 设置为30。这个day 然后用于组装一个新的date。我根据12计算月末日。

    b. (对于每个employee_id)获取.last() recordjob_groupreport_id

    c。合并一个。和 b。在employee_id 键上

    # a.
    hours = (df.groupby([
                pd.Grouper(key='employee_id'),
                pd.Grouper(key='date', freq='SM')
                        ])['hours_worked']
                .sum()
                .reset_index())
    hours['date'] = pd.to_datetime(hours['date'])
    hours['date'] = hours['date'] + pd.DateOffset(days=14)
    
    # Assign day based on bracket (date range) 0-15 or bracket (date range) >15
    from pandas.tseries.offsets import MonthEnd
    hours['bracket'] = hours['date'] + MonthEnd(0)
    hours['bracket'] = pd.to_datetime(hours['bracket']).dt.day
    hours.loc[hours['date'].dt.day <= 15, 'bracket'] = 15
    hours['date'] = pd.to_datetime(dict(year=hours['date'].dt.year,
                                        month=hours['date'].dt.month,
                                        day=hours['bracket']))
    hours.drop('bracket', axis=1, inplace=True)
    
    # b.
    others = (df.groupby('employee_id')['job_group','report_id']
                .last()
                .reset_index())
    
    # c.
    merged = hours.merge(others, how='inner', on='employee_id')
    

    employee_id==1employeeid==3 的原始数据

    df.sort_values(by=['employee_id','date'], inplace=True)
    print(df[df.employee_id.isin([1,3])])
    
        index       date  employee_id  hours_worked   id job_group  report_id
    0       0 2016-11-14            1           7.5  481         A         43
    10     10 2016-11-21            1           6.0  491         A         43
    11     11 2016-11-22            1           5.0  492         A         43
    15     15 2016-12-14            1           7.5  496         A         43
    25     25 2016-12-21            1           6.0  506         A         43
    26     26 2016-12-22            1           5.0  507         A         43
    6       6 2016-11-02            3           6.0  487         A         43
    4       4 2016-11-08            3           6.0  485         A         43
    3       3 2016-11-09            3          11.5  484         A         43
    5       5 2016-11-11            3           3.0  486         A         43
    20     20 2016-11-12            3           3.0  501         A         43
    21     21 2016-12-02            3           6.0  502         A         43
    19     19 2016-12-08            3           6.0  500         A         43
    18     18 2016-12-09            3          11.5  499         A         43
    

    输出

    print(merged)
    
        employee_id       date  hours_worked job_group  report_id
    0             1 2016-11-15           7.5         A         43
    1             1 2016-11-30          11.0         A         43
    2             1 2016-12-15           7.5         A         43
    3             1 2016-12-31          11.0         A         43
    4             2 2016-11-15          31.0         B         43
    5             2 2016-12-15          31.0         B         43
    6             3 2016-11-15          29.5         A         43
    7             3 2016-12-15          23.5         A         43
    8             4 2015-03-15           5.0         B         43
    9             4 2016-02-29           5.0         B         43
    10            4 2016-11-15           5.0         B         43
    11            4 2016-11-30          15.0         B         43
    12            4 2016-12-15           5.0         B         43
    13            4 2016-12-31          15.0         B         43
    

    【讨论】:

    • 这个答案是根据 OP 的 cmets 部分提供的新数据和解释更新的 - 请参阅 here - 新数据的直接来源是 here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2021-05-09
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 2023-01-17
    • 2016-11-04
    相关资源
    最近更新 更多