"Resample" a timestamp according to its frequency

I have a pandas Timestamp with a datetime and frequency associated. However, the datetime seems to be independent of the frequency. For instance,

>>> t = pd.Timestamp('2018-6-6', freq='W-FRI')
>>> t
Timestamp('2018-06-06 00:00:00')

June 6, 2018 is not a Friday. How can I get June 1, 2018 (the previous Friday) from this Timestamp? (If the Timestamp were June 1, 2018 then it should return June 1, 2018.) The following works but seems too verbose.

>>> friday = (pd.date_range(t + pd.Timedelta('1D'), 
                            periods=1, 
                            freq='W-FRI')
              - 1)[0]
>>> friday
Timestamp('2018-06-01 00:00:00', freq='W-FRI')

OR we could use an if-statement to not move the date if it is friday (4) already. Thanks to @Ben.T we can compare it to the defined freq-weekday and thus make it a bit more generic.

import pandas as pd

t = pd.Timestamp('2018-6-7', freq='W-FRI')
friday = t if t.weekday() == t.freq.weekday else t-1

print(friday)

Returns:

2018-06-01 00:00:00

Another possibility is to use the methods weekday of t and the fact that the freq.weekday is accessible from t:

t - pd.Timedelta(days = (t.weekday() - t.freq.weekday)%7 )

>>> friday = [d for d in pd.date_range(end='2018-6-6', periods=7, freq='D') 
      if d.dayofweek == 4]
>>> print(friday)

[Timestamp('2018-06-01 00:00:00', freq='D')]

After some digging around, it seems that rollback is the perfect method for this. (If we'd wanted the next Friday instead of the previous Friday we could use rollforward.) There are two ways to create the offset object with a frequency of W-FRI:

# Method 1
>>> from pandas.tseries.offsets import Week
>>> w_fri = Week(weekday=4) # Mon == 0, Tue == 1, ..., Sun = 6
>>> w_fri
<Week: weekday=4>

# Method 2
>>> from pandas.tseries.frequencies import to_offset
>>> w_fri = to_offset('W-FRI')
>>> w_fri
<Week: weekday=4>

Then to do the rollback,

>>> w_fri.rollback(pd.Timestamp('2019-1-17'))  # A Thursday
Timestamp('2019-01-11 00:00:00')
>>> w_fri.rollback(pd.Timestamp('2019-1-18'))  # A Friday
Timestamp('2019-01-18 00:00:00')

More info here

Comments
  • This moves a friday to the previous friday rather than leave it unchanged
  • Better, sure, but I don't like needing to specify the frequency twice. If I change 'W-FRI' to 'W-MON' then I also need to change 4 to 0.
  • @BallpointBen then you can use t.freq.weekday to not have to specified the day again: friday = t if t.weekday() == t.freq.weekday else t-1