7

我有一个以 mS 精确间隔发生的事件列表,跨越几天。我想将所有发生在“每 n 分钟”时隙中的事件聚集在一起(可以是 20 个事件,也可以是没有事件)。每个活动我都有一个datetime.datetime项目,所以我可以轻松获得datetime.datetime.minute

我的事件列表按时间顺序排列,最早在前,最晚在后。该列表在我正在处理的时间段内是完整的。

我可以更改列表的想法是:-

[[a],[b],[c],[d],[e],[f],[g],[h],[i]...]

其中 a、b、c 发生在 0 到 29 分钟之间,d、e、f、g 发生在 30 到 59 分钟之间,0 到 29 之间(下一小时)之间没有任何内容,h、i 在 30 到 59 之间……

进入新列表:-

[[[a],[b],[c]],[[d],[e],[f],[g]],[],[[h],[i]]...]

我不确定如何构建一个遍历两个时隙的迭代器,直到时间序列列表结束。xrange一旦完成,我能想到的任何事情都使用停止,所以我想知道是否有一种方法可以使用“while”来进行切片?

我还将使用较小的时间段,可能是 5 分钟,我使用 30 分钟作为演示的较短示例。

(作为上下文,我正在对新西兰最近的地震进行基于地理绘制的时间视图。并希望在一个步骤中显示在一小段时间内发生的所有地震,以加快回放速度)

4

6 回答 6

10
# create sample data
from datetime import datetime, timedelta
d = datetime.now()
data = [d + timedelta(minutes=i) for i in xrange(100)]

# prepare and group the data
from itertools import groupby

def get_key(d):
    # group by 30 minutes
    k = d + timedelta(minutes=-(d.minute % 30)) 
    return datetime(k.year, k.month, k.day, k.hour, k.minute, 0)

g = groupby(sorted(data), key=get_key)

# print data
for key, items in g:
    print key
    for item in items:
        print '-', item

这是这个答案的python翻译,它通过将日期时间四舍五入到下一个边界并将其用于分组来工作。


如果您确实需要可能的空组,则可以使用以下方法或类似方法添加它们:

def add_missing_empty_frames(g):
    last_key = None
    for key, items in g:
        if last_key:
            while (key-last_key).seconds > 30*60:
                empty_key = last_key + timedelta(minutes=30)
                yield (empty_key, [])
                last_key = empty_key
        yield (key, items)
        last_key = key

for key, items in add_missing_empty_frames(g):
    ...
于 2013-07-25T07:44:10.810 回答
2

考虑以下

def time_in_range(t,t_min,delta_t):
    if t<=t_min+delta_t and t>=t_min:
         return True
    else:
         return False
def group_list(input_list,ref_time,time_dx,result=[]):
    result.append([])
    for i,item in enumerate(input_list):
        if time_in_range(item,ref_time,time_dx):
            result[-1].append(item)
        else:
            return group_list(input_list[i:],ref_time+time_dx,time_dx,result=result)
def test():
    input_list = [1,2,3,4,5,8,10,20,30]
    print group_list(input_list,0,5)
test()
# Ouput:
# [[1, 2, 3, 4, 5], [8, 10], [], [20], [], [30]]

您需要在其中编写自己的time_in_range函数。

于 2013-07-25T07:57:48.053 回答
1

如果你有整个列表,你可以循环它并将每个事件直接粘贴在正确的时间段中:

grouped = [[] for _ in xrange(whatever)]
for event in events:
    grouped[timeslot_of(event)].append(event)

如果您需要将事件的可迭代对象转换为分组的可迭代对象,事情会变得有些混乱。itertools.groupby几乎可以工作,但它会跳过没有事件的时间间隔。

于 2013-07-25T07:31:45.543 回答
1

假设事件在一个名为 的按时间顺序排列的列表中可用events,具有一个datetime名为 的属性timestamp

interval = 10    # min
period = 2*24*60 # two days in minutes
timeslots = [[] for slot in range(period/interval)]
for e in events:
    index = int((e.timestamp-events[0].timestamp).total_seconds()/60) / interval
    timeslots[index].append(e)

这使用第一个事件作为时间轴上的 t=0。如果这不是您想要的,只需用对代表您的 t=0events[0].timestamp的实例的引用替换。datetime

于 2013-07-25T07:37:48.430 回答
0

我想知道是否有一种使用“while”进行切片的方法?

我有这个定义可能会对你有所帮助。它没有库依赖项,并根据要求使用 while 循环:

如果您有 2 个列表;unix 时间戳和值,每个都具有相同的长度,其中:

timestamps[0] 分别是 values[0] 的时间戳。

timestamps = [unix, unix, unix, ....etc.]
values = [0.1, 0.2, 0.5, 1.1, ....etc.]

假设您有 30 天的数据,从 2011 年 11 月开始,并且您希望它每小时分组一次:

BEGIN = 1320105600

hourly_values = []
z = 0
while z < 720:   # 24 hours * 30 days = 720
    hourly_values.append([])  # append an new empty list for each hour
    for i in range(len(timestamps)):
        if timestamps[i] >= (BEGIN + 3600*z):  # 3600 sec = 1 hour
            if timestamps[i] < (BEGIN + 3600*(z+1)):
                hourly_values[z].append(values[i])
    z+=1
return hourly_values

这将返回每个小时的列表列表,在没有数据的小时内包含空列表。

于 2015-03-15T03:44:08.473 回答
0

您可以使用插槽模块。我有一个类似的问题,我最终写了一个通用的解决方案 - https://github.com/saurabh-hirani/slotter

asciinema 演示 - https://asciinema.org/a/8mm8f0qqurk4rqt90drkpvp1b?autoplay=1

于 2016-10-10T09:28:58.090 回答