Проблема с itertools.groupby для временных интервалов в Python - PullRequest
0 голосов
/ 04 октября 2018

У меня есть такой набор данных:

data = ['input2-2018-09-01--22-35-43', 'input1-2018-09-01--22-35-41', 'input1-2018-09-01--22-35-42', 'input1-2018-09-01--20-38-11', 'input1-2018-09-01--22-32-38']

Моя цель - извлечь данные, соответствующие одному и тому же времени, с временным порогом 2 секунды.Мой набор данных намного больше, чем этот, с ~ 300 элементами, поэтому я использую itertools.groupby, чтобы сгруппировать их по временным интервалам и извлечь их с длиной> 1. Мой код (он адаптирован для выполнения):

from itertools import groupby
from datetime import timedelta, datetime


data = ['input2-2018-09-01--22-35-43', 'input1-2018-09-01--22-35-41',
        'input1-2018-09-01--22-35-42', 'input1-2018-09-01--20-38-11',
        'input1-2018-09-01--22-32-38']

time_threshold = 2   # seconds
date_time = '2018-09-01'

def time_comparison(data, time_threshold):
    potential_detections = []

    # Make groups by time_threshold intervals
    def get_key(det):
        d = datetime.strptime(det[det.find('--')-len(date_time):],'%Y-%m-%d--%H-%M-%S')
        k = d + timedelta(seconds=-(d.second % time_threshold))
        return datetime(k.year, k.month, k.day, k.hour, k.minute, k.second)

    group = groupby(sorted(data), key=get_key)
    print(f'-------------{date_time}------------')

    # Iterate and extract coincidences
    for key, items in group:
        time_interval = []
        print('--------------------')
        print(key)
        print('---')
        for item in items:
            print(item)
            time_interval.append(item)
            if len(time_interval) > 1: 
               potential_detections.append(time_interval)

    return potential_detections

time_comparison(data, time_threshold)

Вывод:

-------------2018-09-01------------
--------------------
2018-09-01 20:38:10
---
input1-2018-09-01--20-38-11
--------------------
2018-09-01 22:32:38
---
input1-2018-09-01--22-32-38
--------------------
2018-09-01 22:35:42
---
input1-2018-09-01--22-35-42
input2-2018-09-01--22-35-43
--------------------
2018-09-01 22:35:40
---
input1-2018-09-01--22-35-41

Проблема в том, что, согласно моему порогу в 2 секунды, последние 2 клавиши должны быть объединены, только в одном интервале:

2018-09-01 22:35:41
---
input1-2018-09-01--22-35-42
input2-2018-09-01--22-35-43
input1-2018-09-01--22-35-41

Как я могу решить это?Это правильный способ классификации моих данных?

Большое спасибо.

1 Ответ

0 голосов
/ 04 октября 2018

Вы можете обернуть каждую введенную дату классом для лучшей помощи в сортировке:

import itertools, re, datetime
import functools
class _date:
  times = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
  def __init__(self, _date:str) -> None:
    self.dmy, self.hms = re.findall('(?<=^input\d\-)[\-\d]+(?=\-\-)|(?<=\-\-)[\d\-]+$', _date)
    self._original = _date
  @property
  def to_date(self):
    return datetime.datetime(*map(int, self.dmy.split('-')+self.hms.split('-')))
  @staticmethod
  def lt(a, b):
    r = a.to_date-b.to_date if a.to_date > b.to_date else b.to_date-a.to_date
    if sum(bool(getattr(r, i, 0)) for i in _date.times) > 1 or not getattr(r, 'seconds', None):
       return False
    return r.seconds <= 2
  def __eq__(self, _c):
    return _date.lt(self, _c)
  def __lt__(self, _d):
     return _date.lt(self, _d)
  def __repr__(self):
    return f'<{self.dmy}, {self.hms}>'


data = ['input2-2018-09-01--22-35-43', 'input1-2018-09-01--22-35-41', 'input1-2018-09-01--22-35-42', 'input1-2018-09-01--20-38-11', 'input1-2018-09-01--22-32-38']
new_data = [[re.findall('(?<=^input\d\-)[\d\-]+(?=\-\-)', i)[0], i] for i in data]
final_data = [[a, list(b)] for a, b in itertools.groupby(sorted(new_data, key=lambda x:x[0]), key=lambda x:x[0])]
for a, b in final_data:
  print(f'{"-"*10}{a}{"-"*10}')
  new_data = sorted([_date(i) for _, i in b], reverse=True)
  final_results = [[a, list(b)] for a, b in itertools.groupby(new_data)]
  for _, c in final_results:
    print('*'*20)
    print('\n'.join(i._original for i in c))
    print('*'*20)

Вывод:

----------2018-09-01----------
********************
input2-2018-09-01--22-35-43
input1-2018-09-01--22-35-41
input1-2018-09-01--22-35-42
********************
********************
input1-2018-09-01--20-38-11
********************
********************
input1-2018-09-01--22-32-38
********************
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...