【问题标题】:How do I identify cycles in time series data with overlapping periods?如何识别具有重叠周期的时间序列数据中的周期?
【发布时间】:2021-04-21 02:44:23
【问题描述】:

给定具有 4 个任务类别(A、B、C、D)的时间序列数据及其对应的时间戳,我的任务是识别 [(A,B,C,D)_1, (A, B,C,D)_2, ...]

这将是简单的(例如,哈希映射或链表),具有干净、不重叠的事件,但我的数据包含序列(按时间排序),例如 [A、B、A、B、C、D、C , D]。这是一个例子:

EVENT TIME
Task A 11/1/16 3:57
Task B 11/1/16 4:19
Task A 11/1/16 7:43
Task B 11/1/16 7:43
Task C 11/1/16 7:51
Task D 11/1/16 7:51
Task C 11/1/16 8:11
Task D 11/1/16 8:13
Task A 11/3/16 3:49
Task B 11/3/16 4:11
Task B 11/3/16 7:34
Task A 11/3/16 7:34
Task C 11/3/16 7:43
Task D 11/3/16 7:43
Task C 11/3/16 8:03
Task D 11/3/16 8:05
Task A 11/5/16 3:41
Task B 11/5/16 4:03
Task A 11/5/16 7:26
Task B 11/5/16 7:26
Task D 11/5/16 7:35
Task C 11/5/16 7:35
Task C 11/5/16 7:54
Task D 11/5/16 7:56

在这种情况下,正确的答案是一旦任务 A(循环的开始)已经开始,就删除“内部”/重叠的 ABCD。这会产生 3 个周期:

Task A Task B Task C Task D
11/1/16 3:57 11/1/16 4:19 11/1/16 8:11 11/1/16 8:13
11/3/16 3:49 11/3/16 4:11 11/3/16 8:03 11/3/16 8:05
11/5/16 3:41 11/5/16 4:03 11/5/16 7:54 11/5/16 7:56

忽略(目前)边缘情况,例如不完整的事件序列,是否有一种有效的算法可以在合并重叠的内部周期时识别周期?

【问题讨论】:

  • 在您展示的示例中,我只使用 4 个计数器的数组。在扫描输入时,增加与每个任务对应的计数器。当所有计数器都具有相同的非零值时,您就发现了一组重叠循环的结束。

标签: python algorithm graph time-series sequence


【解决方案1】:

只是@user3386109 提到的方法并跟踪事件时间戳。

将输入移动到名为 events.txt 的文件中。

file = open("events.txt", "r")
result = []
partial_result = {}
max_count =0;
tasks_count = [0,0,0,0]
for event in file:
    event = event.strip('\n')
    split_events = event.split()
    max_count = max(tasks_count)
    if len(split_events)==4: #Task data
        task_name = split_events[1]
        time =  split_events[2]+" "+split_events[3]
        idx = ord(task_name)-65
        curr_count = tasks_count[idx]
        if (curr_count==max_count or curr_count+1 == max_count) and task_name not in partial_result:
            partial_result[task_name] = time
        tasks_count[idx] +=1

    if len(partial_result)==4:
        result.append(partial_result)
        partial_result ={}
        tasks_count = [0,0,0,0]

print(result)

最终输出

[{'A': '11/1/16 3:57', 'B': '11/1/16 4:19', 'C': '11/1/16 8:11', 'D': '11/1/16 8:13'}, {'A': '11/3/16 3:49', 'B': '11/3/16 4:11', 'C': '11/3/16 8:03', 'D': '11/3/16 8:05'}, {'A': '11/5/16 3:41', 'B': '11/5/16 4:03', 'C': '11/5/16 7:54', 'D': '11/5/16 7:56'}]

【讨论】:

    【解决方案2】:

    你可以使用collections.defaultdict:

    import collections, datetime, re
    r, d = [], collections.defaultdict(list)
    data = [['Task A', '11/1/16 3:57'], ['Task B', '11/1/16 4:19'], ['Task A', '11/1/16 7:43'], ['Task B', '11/1/16 7:43'], ['Task C', '11/1/16 7:51'], ['Task D', '11/1/16 7:51'], ['Task C', '11/1/16 8:11'], ['Task D', '11/1/16 8:13'], ['Task A', '11/3/16 3:49'], ['Task B', '11/3/16 4:11'], ['Task B', '11/3/16 7:34'], ['Task A', '11/3/16 7:34'], ['Task C', '11/3/16 7:43'], ['Task D', '11/3/16 7:43'], ['Task C', '11/3/16 8:03'], ['Task D', '11/3/16 8:05'], ['Task A', '11/5/16 3:41'], ['Task B', '11/5/16 4:03'], ['Task A', '11/5/16 7:26'], ['Task B', '11/5/16 7:26'], ['Task D', '11/5/16 7:35'], ['Task C', '11/5/16 7:35'], ['Task C', '11/5/16 7:54'], ['Task D', '11/5/16 7:56']]
    for a, b in data: 
       v = list(map(int, re.findall('\d+', b)))
       _date = datetime.datetime(v[2], v[0], v[1], v[-2], v[-1], 0)
       if (k:=a.split()[-1]) == 'A' and all(j in d for j in ['A', 'B', 'C', 'D']):
           r.append(d)
           d = collections.defaultdict(list)
           d[k].append(_date)
       else:
           d[k].append(_date)
    
    r.append(d)
    
    f, f1 = {'A':min, 'B':min, 'C':max, 'D':max}, lambda x:f'{x.month}/{x.day}/{x.year} {x.hour}:{str(x.minute).zfill(2)}'
    result = [{a:f1(f[a](b)) for a, b in i.items()} for i in r]
    

    输出:

    [{'A': '11/1/16 3:57', 'B': '11/1/16 4:19', 'C': '11/1/16 8:11', 'D': '11/1/16 8:13'}, 
     {'A': '11/3/16 3:49', 'B': '11/3/16 4:11', 'C': '11/3/16 8:03', 'D': '11/3/16 8:05'}, 
     {'A': '11/5/16 3:41', 'B': '11/5/16 4:03', 'C': '11/5/16 7:54', 'D': '11/5/16 7:56'}]
    

    【讨论】:

    • 谢谢! @Ajax1234 的 defaultdict 方法似乎对缺失值和不完整循环更具弹性。尝试了 @Maruthi Adithya 和 @user3386109 的反方法,但不得不添加许多 if-else 语句来处理这种极端情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 2014-10-11
    • 2013-10-29
    • 2016-11-08
    相关资源
    最近更新 更多