Time difference in days based on specific condition in pandas

╄→尐↘猪︶ㄣ 提交于 2020-03-25 19:16:27

问题


I have a data frame as shown below

ID   CONSTRUCTION_DATE   START_DATE   END_DATE      CANCELLED_DATE
1    2016-02-06          2016-02-26   2017-02-26    NaT
1    2016-02-06          2017-03-27   2018-02-26    2017-05-22 
1    2016-02-06          2017-08-27   2019-02-26    2017-10-21
1    2016-02-06          2018-07-27   2021-02-26    NaT
2    2016-05-06          2017-03-27   2018-02-26    NaT 
2    2016-05-06          2018-08-27   2019-02-26    NaT

Above data has to be order based on ID and START_DATE.

From the above data frame I would like to prepare below dataframe

ID   D_from_C_to_first_S_D    T_D_V_aft_c  T_D_V_w_cancel   N_of_cancel    Lst_END_DATE_to_today
1    20                       376          29               2              After_today
1    325                      NaN          182              0              358     

Where

CANCELLED_DATE = NaT means contract not cancelled

D_from_C_to_first_S_D = Days from CONSTRUCTION_DATE to first START_DATE.

T_D_V_aft_c = Total days vacant after cancellation ( for ID = 1, two cancelled date, 97+279 = 376)

T_D_V_w_cancel = Total days vacant without cancellation (just find the sum of difference of previous END_DATE with next START_DATE.

Lst_END_DATE_to_today = Days from last end date to today.


回答1:


First was created new columns for possible easy verify solution:

today = pd.to_datetime('now').floor('d')
m = df['CANCELLED_DATE'].isna()
df['D_from_C_to_first_S_D'] = df['START_DATE'].sub(df['CONSTRUCTION_DATE']).dt.days
df['T_D_V_aft_c'] = df.groupby('ID')['START_DATE'].shift(-1).sub(df['CANCELLED_DATE']).dt.days
df['T_D_V_w_cancel'] = df.groupby('ID')['START_DATE'].shift(-1).sub(df.loc[m, 'END_DATE']).dt.days
df['N_of_cancel'] = np.where(m, 0, 1)
s = df['END_DATE'].rsub(today).dt.days
df['Lst_END_DATE_to_today'] = s.mask(s.lt(0), 'After_today')

print (df)
   ID CONSTRUCTION_DATE  START_DATE    END_DATE CANCELLED_DATE
0   1        2016-02-06  2016-02-26  2017-02-26            NaT
1   1        2016-02-06  2017-03-27  2018-02-26     2017-05-22
2   1        2016-02-06  2017-08-27  2019-02-26     2017-10-21
3   1        2016-02-06  2018-07-27  2021-02-26            NaT
4   2        2016-05-06  2017-03-27  2018-02-26            NaT
5   2        2016-05-06  2018-08-27  2019-02-26            NaT
   ID CONSTRUCTION_DATE START_DATE   END_DATE CANCELLED_DATE  \
0   1        2016-02-06 2016-02-26 2017-02-26            NaT   
1   1        2016-02-06 2017-03-27 2018-02-26     2017-05-22   
2   1        2016-02-06 2017-08-27 2019-02-26     2017-10-21   
3   1        2016-02-06 2018-07-27 2021-02-26            NaT   
4   2        2016-05-06 2017-03-27 2018-02-26            NaT   
5   2        2016-05-06 2018-08-27 2019-02-26            NaT   

   D_from_C_to_first_S_D  T_D_V_aft_c  T_D_V_w_cancel  N_of_cancel  \
0                     20          NaN            29.0            0   
1                    415         97.0             NaN            1   
2                    568        279.0             NaN            1   
3                    902          NaN             NaN            0   
4                    325          NaN           182.0            0   
5                    843          NaN             NaN            0   

  Lst_END_DATE_to_today  
0                  1089  
1                   724  
2                   359  
3           After_today  
4                   724  
5                   359  

And then aggregate by GroupBy.agg by first, last and sum in custom function for NaNs instead 0:

f = lambda x: x.sum(min_count=1)
df1 = df.groupby('ID').agg(D_from_C_to_first_S_D=('D_from_C_to_first_S_D','first'),
                           T_D_V_aft_c=('T_D_V_aft_c',f),
                           T_D_V_w_cancel=('T_D_V_w_cancel',f),
                           N_of_cancel=('N_of_cancel',f),
                           Lst_END_DATE_to_today=('Lst_END_DATE_to_today','last'),
                           ).reset_index()

print (df1)
   ID  D_from_C_to_first_S_D  T_D_V_aft_c  T_D_V_w_cancel  N_of_cancel  \
0   1                     20        376.0            29.0            2   
1   2                    325          NaN           182.0            0   

  Lst_END_DATE_to_today  
0           After_today  
1                   359  


来源:https://stackoverflow.com/questions/60305889/time-difference-in-days-based-on-specific-condition-in-pandas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!