根据groupby和值比较创建新变量

时间:2018-12-20 13:41:24

标签: python pandas for-loop pandas-groupby

对于此帖子的名称不正确,我深表歉意。该任务包括几个部分,我不知道该如何精确地制定。我有一个这样的数据框

df = pd.DataFrame({'id': (1,1,1,2,2), 'begin': ('01.01.2018','01.02.2018', '01.03.2018', '01.01.2018', '01.02.2018'),
    'end': ('01.02.2018','01.03.2018', '01.04.2018', '01.02.2018', '01.03.2018')})
df['begin']= pd.to_datetime(df['begin'])
df['end']= pd.to_datetime(df['end'])
df
      begin        end     id
0   2018-01-01  2018-01-02  1
1   2018-01-02  2018-01-03  1
2   2018-01-03  2018-01-04  1
3   2018-01-01  2018-01-02  2
4   2018-01-02  2018-01-03  2

其中begin是项目开始时间,end是项目结束时间,id是员工。我想创建一个新变量

      begin       end      id  new
0   2018-01-01  2018-01-02  1   3
1   2018-01-02  2018-01-03  1   2
2   2018-01-03  2018-01-04  1   1
3   2018-01-01  2018-01-02  2   2
4   2018-01-02  2018-01-03  2   1

new表示特定雇员在该日期尚未完成的项目数。到目前为止,项目开始时间为2018年1月1日,第0行中的值为3,该员工在该日期有三个当前项目。

我如何解决此问题 首先,我需要获取每位员工的项目结束/开始日期的列表

gr_end = df.groupby(['id'])['end'].apply(list)
gr_begin = df.groupby(['id'])['begin'].apply(list)

现在最困难。我必须将每个员工的项目开始日期与每个项目的结束日期进行比较。我必须计算开始日期小于结束日期的所有情况

l = []
for i in gr_begin.index:
    for x in gr_begin[i]:
        cv = [j == 1 for j in gr_end[i] if j > x].count(False)
        l.append(cv)
df['new'] = l

首先,请您检查是否正确编写了循环。最重要的是,我相信可以做到,但要简短得多,也要方便得多。我将不胜感激。

1 个答案:

答案 0 :(得分:1)

您也可以使用merge

merged = df.merge(df.drop(columns='end'), on='id', suffixes=('', '_y'))
live_projects = merged[merged.begin<=merged.begin_y]
result = live_projects.groupby(['id','begin','end']).count().reset_index()
result.rename(columns={'begin_y':'new'}, inplace=True)