2

有一个订购日期列表:

[
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 = [datetime.date(2006, 8, 15), datetime.date(2006, 9, 12)](日期之间 <= 30 天)
  • group_2 = [datetime.date(2021, 4, 6), datetime.date(2021, 4, 16), datetime.date(2021, 4, 19)] <=30
  • group_3 = [datetime.date(2007, 8, 10)](没有其他相关日期 <= 30 天)

我尝试使用 iter-tools groupby 但关键功能不允许像“lambda x,y: (xy).days <= 30 ....”这样的 2 个日期比较我不知道我是否可以使用 groupby解决这个问题或者我需要其他的 itertools 功能。我知道我可以为它构建一个 python 算法,但我认为这将存在一个简单的选项来解决这个问题,但我没有找到它:(

谢谢!

4

3 回答 3

1

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)]]
于 2021-10-26T07:27:04.513 回答
1

这是一个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 2006-08-15 0
1 2006-09-12 0
2 2007-08-10 1
3 2021-04-06 2
4 2021-04-16 2
5 2021-04-19 2

或者,如果您只想将列表列表作为输出:df.groupby((df['date'].diff() > pd.Timedelta(30, unit='D')).cumsum()).agg(list)['date'].to_list()

于 2021-10-26T07:11:20.987 回答
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)]]
于 2021-10-26T07:00:16.967 回答