Pandas groupby+重新抽样/时间分组,用于从s

2024-05-10 13:53:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个员工工资数据的数据框架(示例如下),其中“日期”是指员工工资生效的时间:

Employee    Date        Salary
PersonA     1/1/2016    $50000 
PersonB     3/5/2014    $65000 
PersonB     3/1/2015    $75000 
PersonB     3/1/2016    $100000 
PersonC     5/15/2010   $75000 
PersonC     6/3/2011    $100000 
PersonC     3/10/2012   $110000 
PersonC     9/5/2012    $130000 
PersonC     3/1/2013    $150000 
PersonC     3/1/2014    $200000 

在这个例子中,PersonA今年起薪50000美元,PersonC已经在公司工作了一段时间,自从2010年5月15日开始工作以来,已经收到了几次加薪。在

我需要将Date列转换为Months from Start,其中Months from Start将以m个月为增量(由我指定)。例如,对于PersonB,假设m=12,结果将是:

^{pr2}$

这意味着在第0个月(就业开始)时,PersonB的工资是65000美元;12个月后他的工资是65000美元,24个月后他的工资是75000美元。在未来的一个月内,将不会有超过36个月的就业增长(请注意,在未来的一个月内不会出现)。在

再次注意,我希望能够将m调整为任何月份的增量。如果我想要6个月的增量(m=6),结果是:

Employee    Months From Start   Salary
PersonB     0                   $65000 
PersonB     6                   $65000 
PersonB     12                  $65000 
PersonB     18                  $75000 
PersonB     24                  $100000 
PersonB     30                  $100000 

最后一步,我还想在转换后的数据帧中包含该员工截至今日的工资。再次使用PersonB,并假设m=6,这意味着结果将是:

Employee    Months From Start   Salary
PersonB     0                   $65000 
PersonB     6                   $65000 
PersonB     12                  $65000 
PersonB     18                  $75000 
PersonB     24                  $100000 
PersonB     30                  $100000 
PersonB     32.92               $100000 <--added (today is 32.92 months from start)

问题:是否有一种编程方式(我假设使用至少一种:groupbyresample或{})来实现上述所需的数据帧?在

注意:你可以假设所有员工都在工作(没有离开公司)。在


Tags: 数据fromdate员工employee公司start增量
3条回答

好吧,在回答的第一部分,我会这样做。。。在

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'Employee': ['PersonA', 'PersonB', 'PersonB', 'PersonB', 'PersonC', 'PersonC', 'PersonC', 'PersonC', 'PersonC', 'PersonC'], 
    'Date': ['1/1/2016', '3/5/2014', '3/1/2015', '3/1/2016', '5/15/2010', '6/3/2011', '3/10/2012', '9/5/2012', '3/1/2013', '3/1/2014'], 
    'Salary': [50000 , 65000 , 75000 , 100000 , 75000 , 100000 , 110000 , 130000 , 150000 , 200000]
})

df.Date = pd.to_datetime(df.Date)

m = 6
emp_groups = df.groupby('Employee')
df['months_from_start'] = df.Date - emp_groups.Date.transform(min)
df.months_from_start = df.months_from_start.dt.days / 30 // m * m

m可以是任何你想要的。我在计算min日期之间的天数,然后除以一个月内的大致天数,然后进行一点整数除法,将窗口大小“四舍五入”。在

这会给你这样的东西。。。在

^{pr2}$

第二部分有点棘手。我会创建一个新的df和concat到第一个。。。在

last_date_df = emp_groups.last()
last_date_df.months_from_start = (last_date_df.Date - emp_groups.first().Date).dt.days / 30
last_date_df.reset_index(inplace=True)

pd.concat([df, last_date_df], axis=0)

让你。。。在

        Date Employee  Salary  months_from_start
0 2016-01-01  PersonA   50000           0.000000
1 2014-03-05  PersonB   65000           0.000000
2 2015-03-01  PersonB   75000          12.000000
3 2016-03-01  PersonB  100000          24.000000
4 2010-05-15  PersonC   75000           0.000000
5 2011-06-03  PersonC  100000          12.000000
6 2012-03-10  PersonC  110000          18.000000
7 2012-09-05  PersonC  130000          24.000000
8 2013-03-01  PersonC  150000          30.000000
9 2014-03-01  PersonC  200000          42.000000
0 2016-01-01  PersonA   50000           0.000000
1 2016-03-01  PersonB  100000          24.233333
2 2014-03-01  PersonC  200000          46.200000

您可以结合groupby和resample来执行此操作。要使用重采样,需要将日期作为索引。在

df.index = pd.to_datetime(df.Date)
df.drop('Date',axis = 1, inplace = True)

然后:

^{pr2}$

在这个例子中,我用了6个月的周期。请注意,它将在每个月的最后一天,我希望这不会是一个问题。 然后你将得到:

    Employee   Date      Salary
0   PersonA 2016-01-31   $50000
1   PersonB 2014-03-31   $65000
2   PersonB 2014-09-30   $65000
3   PersonB 2015-03-31   $75000
4   PersonB 2015-09-30   $75000
5   PersonB 2016-03-31  $100000
6   PersonC 2010-05-31   $75000
7   PersonC 2010-11-30   $75000
8   PersonC 2011-05-31   $75000
9   PersonC 2011-11-30  $100000
10  PersonC 2012-05-31  $110000
11  PersonC 2012-11-30  $130000
12  PersonC 2013-05-31  $150000
13  PersonC 2013-11-30  $150000
14  PersonC 2014-05-31  $200000

现在可以创建“months since started”列(cumcount函数检查每行在其组中出现的顺序)。记住用每个周期的月数乘以它(在本例中为6):

df['Months since started'] = df.groupby('Employee').cumcount()*6

     Employee   Date      Salary     Months since started
0   PersonA 2016-01-31   $50000                  0
1   PersonB 2014-03-31   $65000                  0
2   PersonB 2014-09-30   $65000                  6
3   PersonB 2015-03-31   $75000                 12
4   PersonB 2015-09-30   $75000                 18
5   PersonB 2016-03-31  $100000                 24
6   PersonC 2010-05-31   $75000                  0
7   PersonC 2010-11-30   $75000                  6
8   PersonC 2011-05-31   $75000                 12
9   PersonC 2011-11-30  $100000                 18
10  PersonC 2012-05-31  $110000                 24
11  PersonC 2012-11-30  $130000                 30
12  PersonC 2013-05-31  $150000                 36
13  PersonC 2013-11-30  $150000                 42
14  PersonC 2014-05-31  $200000                 48

希望有帮助!在

您可以使用groupbymerge的功能

>>> import pandas as pd
>>> df = pd.DataFrame([['PersonC','5/15/2010',75000],['PersonC','7/3/2011',100000],['PersonB','3/5/2014',65000],['PersonB','3/1/2015',75000],['PersonB','3/1/2016',100000]],columns=['Employee','Date','Salary'])
>>> df['Date']= pd.to_datetime(df['Date'])
>>> df
  Employee       Date  Salary
0  PersonC 2010-05-15   75000
1  PersonC 2011-07-03  100000
2  PersonB 2014-03-05   65000
3  PersonB 2015-03-01   75000
4  PersonB 2016-03-01  100000
>>> satrt_date = df.groupby('Employee')['Date'].min().to_frame().rename(columns={'Date':'Start Date'})
>>> satrt_date['Employee'] = satrt_date.index 
>>> df = df.merge(satrt_date,how='left', on= 'Employee')
>>> df['Months From Start'] = df['Date']-df['Start Date']
>>> df['Months From Start'] = df['Months From Start'].apply(lambda x: x.days)
>>> df['Months From Start']= df['Months From Start'].apply(lambda x: (x/30) - (x/30)%6)
>>> df
  Employee       Date  Salary Start Date  Months From Start
0  PersonC 2010-05-15   75000 2010-05-15                  0
1  PersonC 2011-07-03  100000 2010-05-15                 12
2  PersonB 2014-03-05   65000 2014-03-05                  0
3  PersonB 2015-03-01   75000 2014-03-05                 12
4  PersonB 2016-03-01  100000 2014-03-05                 24

在这里,您可以将6替换为一个名为m的变量,并为其分配任意值

相关问题 更多 >