Python - отображать диапазон дат по идентификатору в отдельных строках - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть некоторые данные о сотрудниках, которые показывают список дат, на которые они запросили отпуск

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 голосов
/ 10 декабря 2018

Вы можете перебирать каждую строку

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)
0 голосов
/ 10 декабря 2018

Решение, если emp_id значения уникальны - изменить на melt и resample с ffill:

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()
       )

Или используйте concat с Series с, созданным date_range с itertuples, а затем join:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...