按月份将日期数组拆分为多个列表

3
我可以完成你的翻译需求。以下是您需要翻译的内容:

我有以下数组(也可以是列表):

uniqueDates = np.array([datetime.date(2017, 4, 11), datetime.date(2017, 4, 12),
                        datetime.date(2017, 4, 20), datetime.date(2017, 4, 25),
                        datetime.date(2017, 5, 3), datetime.date(2017, 5, 4),
                        datetime.date(2017, 5, 10), datetime.date(2017, 5, 11),
                        datetime.date(2017, 6, 1), datetime.date(2017, 6, 13),
                        datetime.date(2017, 6, 15), datetime.date(2017, 7, 10),
                        datetime.date(2017, 7, 13), datetime.date(2017, 7, 17)])

我想将这个数组分成四个列表,每个列表包含独特月份的日期(四月、五月、六月和七月)。 所以,预期结果类似于以下内容:
monthsList = [[datetime.date(2017, 4, 11),
               datetime.date(2017, 4, 12),
               datetime.date(2017, 4, 20),
               datetime.date(2017, 4, 25)],
              [datetime.date(2017, 5, 3),
               datetime.date(2017, 5, 4),
               datetime.date(2017, 5, 10),
               datetime.date(2017, 5, 11)],
              [datetime.date(2017, 6, 1),
               datetime.date(2017, 6, 13),
               datetime.date(2017, 6, 15)],
              [datetime.date(2017, 7, 10),
               datetime.date(2017, 7, 13),
               datetime.date(2017, 7, 17)]]

我想知道是否有一个函数可以自动完成这个任务?还是必须循环遍历元素并逐个检查它们? 我正在寻找一种高效的方法来完成这个任务。我在StackOverflow上搜索了几个问题,但没有找到我要找的内容。


如果它们的大小不同,那么你肯定需要通过循环来处理它们。 - Nidal Barada
@NidalBarada 不行。每个月的天数可能不同,而且我可能有不同的月份。在某些情况下,我可能会有二月、五月、六月、八月等月份。 - O. Mohsen
3个回答

2
只要将月份分组(计算量更少),这个方法就可以运行:
Dates=[]

for i in range(len(uniqueDates)):
    if(Dates==[]):
        Dates.append([uniqueDates[i]])
    elif(uniqueDates[i].month==Dates[-1][0].month):
        Dates[-1].append(uniqueDates[i])
    else:
        Dates.append([uniqueDates[i]])

否则请使用:
Dates=[]

for i in range(len(uniqueDates)):
    if(Dates==[]):
        Dates.append([uniqueDates[i]])
    else:
        for y in range(len(Dates)):
            if(Dates[y][0].month == uniqueDates[i].month):
                Dates[y].append(uniqueDates[i])
                break
            if(y==len(Dates)-1):
                Dates.append([uniqueDates[i]])

输出结果均为:

[
    [datetime.date(2017, 4, 11), datetime.date(2017, 4, 12), datetime.date(2017, 4, 20), datetime.date(2017, 4, 25)],
    [datetime.date(2017, 5, 3), datetime.date(2017, 5, 4), datetime.date(2017, 5, 10), datetime.date(2017, 5, 11)],
    [datetime.date(2017, 6, 1), datetime.date(2017, 6, 13), datetime.date(2017, 6, 15)],
    [datetime.date(2017, 7, 10), datetime.date(2017, 7, 13), datetime.date(2017, 7, 17)]
]

根据 @Tom83B 提供的 pandas 答案,对第一和第二个函数的结果进行时间测量:

Repeated: 100,000x
    First Function:   0.10295674900044105  seconds
    Second Function:  1.5613631390006049   seconds
    Pandas Function:  146.28389169599905   seconds

2

您可以使用pandas:

import pandas as pd

...

s = pd.Series(uniqueDates)
list(s.groupby(s.map(lambda x: x.month)))

编辑:正如Nidal Barada所指出的那样,他的循环方法显著更快。在Jupyter中使用%%timeit魔术命令:

pandas:562微秒±3.87微秒每次循环(平均值±7次运行的标准差,每次1000个循环)

Nidal Barada的答案:8.14微秒±39.9纳秒每次循环(平均值±7次运行的标准差,每次100000个循环)


0
你可以使用itertools中的groupby:
from itertools import groupby

grouped = [[*g] for _,g in groupby(uniqueDates,key=lambda d:(d.year,d.month))]

print(*(", ".join(map(str,g)) for g in grouped),sep="\n")

2017-04-11, 2017-04-12, 2017-04-20, 2017-04-25
2017-05-03, 2017-05-04, 2017-05-10, 2017-05-11
2017-06-01, 2017-06-13, 2017-06-15
2017-07-10, 2017-07-13, 2017-07-17

即使您的输入只是普通的Python列表,这也可以工作。除非必要,否则不应使用numpy


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接