Python-按ID在单独的行中显示日期范围

时间:2018-12-10 05:47:54

标签: python-3.x pandas

我有一些员工数据,显示了他们请假的日期列表

emp_id,emp_name,from_date,to_date
101,kevin,2018-12-01,2018-12-05
104,scott,2018-12-02,2018-12-02

我正在尝试转换上述格式,以使上述示例中的每个日期都显示为单独的行,如下所示:

emp_id,emp_name,date
101,kevin,2018-12-01
101,kevin,2018-12-02
101,kevin,2018-12-03
101,kevin,2018-12-04
101,kevin,2018-12-05
104,scott,2018-12-02

任何人都可以建议我如何在熊猫身上做到这一点。谢谢。

2 个答案:

答案 0 :(得分:1)

如果emp_id值是唯一的解决方案-用meltresampleffill重塑:

df1 = (df.melt(['emp_id','emp_name'], value_name='date')
        .set_index('date')
        .drop('variable', axis=1)
        .groupby(['emp_id', 'emp_name'])
        .resample('d')[[]]
        .ffill()
        .reset_index()
       )

print (df1)
   emp_id emp_name       date
0     101    kevin 2018-12-01
1     101    kevin 2018-12-02
2     101    kevin 2018-12-03
3     101    kevin 2018-12-04
4     101    kevin 2018-12-05
5     104    scott 2018-12-02

另一种解决方案-更通用,只有必要的默认RangeIndex

#default RangeIndex
#df = df.reset_index(drop=True)

df1 = (df.reset_index()
        .melt(['emp_id','emp_name','index'], value_name='date')
        .set_index('date')
        .drop('variable', axis=1)
        .groupby(['index'])
        .resample('d')[['emp_id','emp_name']]
        .ffill()
        .reset_index(level=0, drop=True)
        .reset_index()
       )

或将concatdate_rangeitertuples创建的join创建的Series一起使用:

df1 = (pd.concat([pd.Series(r.Index,
                           pd.date_range(r.from_date,r.to_date)) 
                  for r in df.itertuples()])
        .reset_index())
df1.columns = ['date','idx']
df1 = df1.set_index('idx').join(df[['emp_id','emp_name']]).reset_index(drop=True)
print (df1)

        date  emp_id emp_name
0 2018-12-01     101    kevin
1 2018-12-02     101    kevin
2 2018-12-03     101    kevin
3 2018-12-04     101    kevin
4 2018-12-05     101    kevin
5 2018-12-02     104    scott

答案 1 :(得分:0)

您可以遍历每一行

df_dates =  pd.concat([pd.DataFrame({'Date': pd.date_range(row.from_date, row.to_date, freq='D'),
                   'Emp_id': row.emp_id,
                   'Emp_Name': row.emp_name}, columns=['Date', 'Emp_id', 'Emp_Name']) 
               for i, row in df.iterrows()], ignore_index=True)

    print(df_dates)