Pure python或itertools按日期之间的天数对日期列表进行分组



排序日期列表:

[
datetime.date(2006, 8, 15),
datetime.date(2006, 9, 12),
datetime.date(2007, 8, 10),
datetime.date(2021, 4, 6),
datetime.date(2021, 4, 16),
datetime.date(2021, 4, 19)
...
]

我想有包含日期的组,所有日期之间最多30天(组的第一个元素和最后一个元素之间的距离将为<= 30天)

例如,使用前面的列表,我将得到:

  • group_1 =[日期时间。日期(2006,8,15),日期时间。日期(2006,9,12)](日期之间<= 30天)
  • group_2 = [datetime. time]Date (2021, 4, 6), datetime。Date (2021, 4, 16), datetime。date(2021, 4, 19)]& lt; 30岁=
  • group_3 = [datetime. time]date(2007,8,10)](没有其他相关日期<= 30天)

我尝试使用跨工具组,但关键函数不允许2个日期比较,如"lambda x,y:(x-y)。days <= 30…"我不知道我是否可以使用groupby来解决这个问题,或者我需要其他的itertools功能。我知道我可以为它建立一个python算法,但我认为存在一个简单的选项来解决这个问题,但我没有找到它:(

谢谢!

itertools.groupby表示对彼此不依赖的项进行分组。在您的情况下,通过插入一个新组(当当前日期比当前组的第一个日期晚30天以上时),简单地遍历日期列表以构建组列表既容易又清晰:

dates = [
datetime.date(2006, 8, 15),
datetime.date(2006, 9, 12),
datetime.date(2007, 8, 10),
datetime.date(2021, 4, 6),
datetime.date(2021, 4, 16),
datetime.date(2021, 4, 19),
datetime.date(2021, 5, 7)
]
threshold = datetime.timedelta(30)
groups = []
for date in dates:
if not groups or date - group[0] > threshold:
group = []
groups.append(group)
group.append(date)

groups将变成:

[[datetime.date(2006, 8, 15), datetime.date(2006, 9, 12)],
[datetime.date(2007, 8, 10)],
[datetime.date(2021, 4, 6), datetime.date(2021, 4, 16), datetime.date(2021, 4, 19)],
[datetime.date(2021, 5, 7)]]

这是一个pandas解决方案,将日期与下一个日期进行比较,并检查两者之间是否有30天。然后用cumsum分配一个组号:

import pandas as pd
import datetime
data = [ datetime.date(2006, 8, 15), datetime.date(2006, 9, 12), datetime.date(2007, 8, 10), datetime.date(2021, 4, 6), datetime.date(2021, 4, 16), datetime.date(2021, 4, 19)]
df = pd.DataFrame(data, columns=['date'])
df['groups'] = (df['date'].diff() > pd.Timedelta(30, unit='D')).cumsum()

输出:

0

在这种情况下,使用普通的旧式for循环的迭代解决方案非常简单。

我不认为使用itertools来解决这个问题是简单或有效的,因为在这种情况下,分组取决于数据的上下文,这可能会产生O(N^2)的解决方案,而迭代方法是O(N)。

dts = [
datetime.date(2006, 8, 15),
datetime.date(2006, 9, 12),
datetime.date(2007, 8, 10),
datetime.date(2021, 4, 6),
datetime.date(2021, 4, 16),
datetime.date(2021, 4, 19)
]
def groupDateTimes(dts):
i = 0
ans = []
group = []
delta30days = datetime.timedelta(days=30)
while i < len(dts):
cur = dts[i]
if not group:
group.append(cur)
elif cur - group[0] <= delta30days:
group.append(cur)
else:
ans.append(group)
group = [cur]
i += 1
if group:
ans.append(group)
return ans
print(groupDateTimes(dts)) // [[datetime.date(2006, 8, 15), datetime.date(2006, 9, 12)], [datetime.date(2007, 8, 10)], [datetime.date(2021, 4, 6), datetime.date(2021, 4, 16), datetime.date(2021, 4, 19)]]

最新更新