I am looking for a way to determine if two isocalendar tuples are consecutive using Python.
The tuples are obtained by using the datetime.isocalendar() as below:
datelist = pd.date_range(datetime.strptime("29-Dec-2022", "%d-%b-%Y").date(), periods=11).tolist()
for i in range (len ( datelist)):
datelist [i] =datelist [i].isocalendar()
datelist
(2022, 52, 5),
(2022, 52, 6),
(2022, 52, 7),
(2023, 1, 1),
(2023, 1, 2),
(2023, 1, 3),
(2023, 1, 4),
(2023, 1, 5),
(2023, 1, 6),
(2023, 1, 7)]
I am looking for a way to check that (2023,1,1)
is the isoweek that follows (2023,52,7)
and so on.
I tried two approaches that did not work.
The first is extracting the week number from the tuple and checking if it's consecutive by using the integer. This logic works in most week but not when there is a change of year, as in the example above.
The second approach I tried is using logical operators on the isocalendar tuple itself, such as:
(2022, 52, 7) relativedelta(weeks=1)
However, this produces errors.
Can you recommend a Pythonic way to achieve this on a Pandas DataFrame?
My final objective after establishing if two tuples represent consecutive isoweek is to use Groupby to group dates only in consecutive weeks.
Many thanks in advance to the community for the help.
CodePudding user response:
The pandas version:
df = pd.DataFrame({'isocal': datelist})
df['check'] = df['isocal'].apply(lambda x: datetime.fromisocalendar(*x)) \
.diff().eq(pd.Timedelta(days=1))
Output:
>>> df
isocal check
0 (2022, 52, 4) False
1 (2022, 52, 5) True
2 (2022, 52, 6) True
3 (2022, 52, 7) True
4 (2023, 1, 1) True
5 (2023, 1, 2) True
6 (2023, 1, 3) True
7 (2023, 1, 4) True
8 (2023, 1, 5) True
9 (2023, 1, 6) True
10 (2023, 1, 7) True
CodePudding user response:
Convert the ISO calendar to date then use relativedelta
to check if the current date following the previous date:
from datetime import date
dt = [date.fromisocalendar(*x) for x in datelist]
out = ['N/A'] [curr relativedelta(days=-1) == prev
for curr, prev in zip(dt[1:], dt)]
Output:
>>> out
['N/A', True, True, True, True, True, True, True, True, True, True]
CodePudding user response:
As I understand, the core of the problem is to check whether one isocalendar date is in the week after another isocalendar date, not day as as other answers here indicate.
As you have described yourself, it is not possible to make any date calculations on your isocalendar dates. This is because they are simply named tuples see docs here. You can however convert them into a datetime object, do the arithmetic (add one week), and then convert them back and see if they are the same week:
def is_consecutive(curr, consecutive_candidate):
curr_dt = date.fromisocalendar(*curr)
consec_dt = date.fromisocalendar(*consecutive_candidate)
return datetime.isocalendar(curr_dt timedelta(weeks=1)).week
== datetime.isocalendar(consec_dt).week
Now use this function directly on your datelist list, e.g.:
is_consecutive(datelist[3], datelist[4])
# True
is_consecutive(datelist[4], datelist[5])
# False
The first one is True since 1.jan 2023 (dt[3]) is Sunday of the last week of 2022 (according to ISO week date) and 2.jan (dt[4]) is Monday of the first week of 2023