Search code examples
pandasdatetimeisoweek-number

How to get back to a datetime object from an isoweek integer in a pandas series?


I am stuck with this problem. Although I found some similar questions, I could not manage to apply the solutions to my case.

I have a small series in which I have a start and an end date of a experimental deployment. My goal is to get the starting day of the week (monday 00h 00min) in which the deployment was started and the same for the last week.

This is my series:

Input

print(df_startend)

Output

Camera_Deployment_Start   2015-09-28 11:00:00
Camera_Deployment_End     2017-12-25 16:40:00
dtype: datetime64[ns]

I thought I could first get the week number and then go back to a datetime object, which would represent the very start of the week. So I did this:

df_startend=df_startend.apply(lambda x: x.isocalendar())

Input

print(df_startend)

Output

Camera_Deployment_Start    (2015, 40, 1)
Camera_Deployment_End      (2017, 52, 1)
dtype: object
None

It is worth saying that I can ignore the object in the 3rd position of the (tuple[2]). In this example both are coincidentally 1-the first day of the week- but that may not be the case with other data samples.

And from here on I cannot manage. My ultimate goal is to generate all the start days of all the weeks in between. Probably using something like:

ws=pd.date_range(start=,end=,freq='W')

Your attention is very appreciated, thank you very much!


Solution

  • If only 2 element Series firstsubtract days extracted by dayofweek and then use floor for remove times and then date_range with W-Mon offset:

    print (df_startend)
    Camera_Deployment_Start   2015-09-28 11:00:00
    Camera_Deployment_End     2015-12-25 16:40:00
    dtype: datetime64[ns]
    
    
    s = (df_startend - pd.to_timedelta(df_startend.dt.dayofweek, unit='d')).dt.floor('d')
    
    ws=pd.date_range(start=s['Camera_Deployment_Start'],
                     end=s['Camera_Deployment_End'],
                     freq='W-Mon')
    print (ws)
    DatetimeIndex(['2015-09-28', '2015-10-05', '2015-10-12', '2015-10-19',
                   '2015-10-26', '2015-11-02', '2015-11-09', '2015-11-16',
                   '2015-11-23', '2015-11-30', '2015-12-07', '2015-12-14',
                   '2015-12-21'],
                  dtype='datetime64[ns]', freq='W-MON')
    

    Detail:

    print (s)
    Camera_Deployment_Start   2015-09-28
    Camera_Deployment_End     2015-12-21
    dtype: datetime64[ns]
    

    Solution with isocalendar:

    s = df_startend.apply(lambda x: '-'.join(str(y) for y in x.isocalendar()[:2]))
    s = pd.to_datetime(s + '-1', format='%Y-%W-%w') - pd.Timedelta(7, 'd')
    
    print (s)
    Camera_Deployment_Start   2015-09-28
    Camera_Deployment_End     2015-12-21
    dtype: datetime64[ns]