pd.offsets.WeekOfMonth() behavior in Pandas

90 views Asked by At

With pd.offsets.WeekOfMonth() here:

  • 2020-08-10 (i.e. Monday) offsets to 2020-08-12 as expected i.e. Wednesday of 2nd week (i.e. week=1)

Trying to understand why doesn't:

  • 2020-08-01 offset to 2020-08-05 instead of 2020-08-12.
  • 2020-08-21 offset to 2020-08-26 instead of 2020-09-09.

[Python 3.9.13; pandas: 2.0.1]

Code:

import pandas as pd     
data = pd.Series(
     [pd.Timestamp('2020-08-01 01:01:01.001001001'), # Saturday
     pd.Timestamp('2020-08-10 01:01:01.001001001'),  # Monday
     pd.Timestamp('2020-08-21 01:01:01.001001001')]) # Friday
print(data)
print()

Offset:

w = data + pd.offsets.WeekOfMonth(week=1, weekday=2)
print(w)

Output:

0   2020-08-01 01:01:01.001001001 # Saturday
1   2020-08-10 01:01:01.001001001 # Monday
2   2020-08-21 01:01:01.001001001 # Friday
dtype: datetime64[ns]

0   2020-08-12 01:01:01.001001001 # Wednesday
1   2020-08-12 01:01:01.001001001 # Wednesday
2   2020-09-09 01:01:01.001001001 # Wednesday
dtype: datetime64[ns]
2

There are 2 answers

1
mozway On BEST ANSWER

Because you use a positive Offset, this will give you the next "second Wednesday of the month".

If you're before one "second Wednesday of a month", this will remain in the same month, otherwise go to the next month's "second Wednesday".

pd.Timestamp('2020-08-11') + pd.offsets.WeekOfMonth(week=1, weekday=2)
# Timestamp('2020-08-12 00:00:00')

pd.Timestamp('2020-08-12') + pd.offsets.WeekOfMonth(week=1, weekday=2)
# Timestamp('2020-09-09 00:00:00')

Likewise, using a negative offset:

pd.Timestamp('2020-08-12') - pd.offsets.WeekOfMonth(week=1, weekday=2)
# Timestamp('2020-07-08 00:00:00')

pd.Timestamp('2020-08-13') - pd.offsets.WeekOfMonth(week=1, weekday=2)
# Timestamp('2020-08-12 00:00:00')
0
Ahmer Tabassum On

The code data + pd.offsets.WeekOfMonth(week=1, weekday=2) is used to add an offset to a given date. This offset allows us to shift dates and times forwards or backward in a flexible manner.

The parameters used in pd.offsets.WeekOfMonth(week=1, weekday=2) have specific meanings:

  • week=1 represents the 2nd week of a month, where the weeks are numbered starting from 0 for the first week.
  • weekday=2 represents the third day of the week, which corresponds to Monday (since weekdays are numbered starting from 0). Here's what the code does step by step:

When we apply the offset to a given date, it calculates the date of the third weekday of the second week of the same month as the provided date.

For a positive offset:

If the provided date (2020-08-01) comes before the calculated date (2020-08-12) using the week and weekday, it returns the calculated date. For example, if the input date is 2020-08-01, the calculated date is 2020-08-12. While if the provided date (2020-08-21) comes after the calculated date (2020-09-09) using the week and weekday, it returns the date of the same weekday in the second week of the next month. For example, if the input date is 2020-08-21, the calculated date is 2020-08-12, but since the input date is after this calculated date, it moves to the next month and calculates the date again. The result is 2020-09-09.

For a negative offset

It will work oppositely in this case. Let's say the provided date (2020-08-01) comes before the calculated date (2020-08-12) then, it will return the second Wednesday of the previous month.