我有一份员工薪资数据的数据框(样本如下)其中'日期'是指员工的薪水何时生效:
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今年以50,000美元开始,而PersonC已经在公司工作了一段时间,自从2010年5月15日开始以来已经收到了几次增加。
我需要在单个员工的基础上将Date
列转换为Months from Start
,其中Months from Start
将以m
个月为增量(由我指定)。例如,对于PersonB,假设为m=12
,结果为:
Employee Months From Start Salary
PersonB 0 $65000
PersonB 12 $65000
PersonB 24 $75000
这意味着在第0个月(就业开始),PersonB的薪水为65,000美元; 12个月后,他的薪水为65,000美元,24个月后,他的薪水为75,000美元。请注意,下一个增量(36个月) NOT 会出现在PersonB的转换数据框上,因为该持续时间超过了PersonB的工作时间(将来会是这样)。
再次注意,我希望能够将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)
问题是否采用编程方式(我假设使用至少一个:groupby
,resample
或TimeGrouper
)来实现所需的数据帧如上所述?
注意:您可以假设所有员工都处于活动状态(尚未离开公司)。
答案 0 :(得分:2)
您可以将group_by和resample结合使用。要使用重新采样,您需要将日期作为索引。
df.index = pd.to_datetime(df.Date)
df.drop('Date',axis = 1, inplace = True)
然后:
df.groupby('Employee').resample('6m').pad()
在这种情况下,我使用了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
现在您可以创建“自启动以来的月份”列(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
希望它有所帮助!
答案 1 :(得分:1)
您可以使用groupby
merge
和DataFrames
功能
>>> 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
并为其指定任意值
答案 2 :(得分:1)
好的,所以对于答案的第一部分,我会做这样的事情......
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
日期之间的天数,然后除以一个月中的大致天数,然后进行一些整数除法到#34;四舍五入&#34;到你想要的窗口大小。
这会给你这样的东西......
Date Employee Salary months_from_start
0 2016-01-01 PersonA 50000 0
1 2014-03-05 PersonB 65000 0
2 2015-03-01 PersonB 75000 12
3 2016-03-01 PersonB 100000 24
4 2010-05-15 PersonC 75000 0
5 2011-06-03 PersonC 100000 12
6 2012-03-10 PersonC 110000 18
7 2012-09-05 PersonC 130000 24
8 2013-03-01 PersonC 150000 30
9 2014-03-01 PersonC 200000 42
第二部分有点棘手。我会创建一个新的df并连接到第一个......
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
答案 3 :(得分:0)
非常感谢提供的答案。不幸的是,所有答案都有点“关闭”。并没有完全实现目标。我最终在列表推导中嵌套了两个for
循环来实现目标。