считать количество событий между двумя последовательными моментами python - PullRequest
1 голос
/ 05 апреля 2020

У меня есть некоторая информация о дате и времени:

DateTime                          
2018/01/01 01:00:00             
2018/01/01 02:30:00
2018/01/01 03:10:00
2018/01/01 04:00:00
2018/01/01 05:25:00

У меня также есть некоторые другие времена возникновения события:

occurrence
2018/01/01 01:01:00             
2018/01/01 01:02:00
2018/01/01 02:31:00
2018/01/01 04:05:00

Я хотел бы посчитать количество случаев возникновения события между любыми два последовательных временных интервала для получения чего-то ниже:

Occurrence      Start Time               End Time
2               2018/01/01 01:00:00      2018/01/01 02:30:00
1               2018/01/01 02:30:00      2018/01/01 03:10:00
0               2018/01/01 03:10:00      2018/01/01 04:00:00
1               2018/01/01 04:00:00      2018/01/01 05:25:00

Я думаю об использовании чего-то вроде

sum(1 if meets_condition(x) else 0 for x in my_list)

, но я не знаю, как это реализовать. Может кто-нибудь, пожалуйста, помогите с этим.

Ответы [ 3 ]

2 голосов
/ 05 апреля 2020

вы можете использовать:

from datetime import datetime
from collections import Counter

t = """2018/01/01 01:00:00         
2018/01/01 02:30:00
2018/01/01 03:10:00
2018/01/01 04:00:00
2018/01/01 05:25:00"""

occurrence = """2018/01/01 01:01:00             
2018/01/01 01:02:00
2018/01/01 02:31:00
2018/01/01 04:05:00"""


fmt ='%Y/%m/%d %H:%M:%S'
dates = [datetime.strptime(d.strip(), fmt) for d in t.split('\n')]
intervals = [(d1, d2) for d1, d2 in zip(dates, dates[1:])] # already sorted
occ = [datetime.strptime(d.strip(), fmt) for d in occurrence.split('\n')]

count = Counter()
for o in occ:
    for d1, d2 in intervals:
        if o < d2:
            count[(d1, d2)] += 1
            break


print('Occurrence      Start Time               End Time')
for d1, d2 in intervals:
    print(str(count[(d1, d2)]).ljust(15), d1.strftime(fmt).ljust(24), d2.strftime(fmt))

вывод:

Occurrence      Start Time               End Time
2               2018/01/01 01:00:00      2018/01/01 02:30:00
1               2018/01/01 02:30:00      2018/01/01 03:10:00
0               2018/01/01 03:10:00      2018/01/01 04:00:00
1               2018/01/01 04:00:00      2018/01/01 05:25:00
0 голосов
/ 05 апреля 2020

Вы были правы с этой суммой / для комбо, но мы должны сделать некоторые дополнительные маги c с python классом datetime. Здесь мы просто анализируем строку в объекте datetime, затем используем операторы сравнения, чтобы проверить, попадает ли она в диапазон.

from datetime import datetime as dt

dates = ["2018/01/01 01:00:00", "2018/01/01 02:30:00", "2018/01/01 04:00:00"]
events = ["2018/01/01 01:01:00", "2018/01/01 01:02:00", "2018/01/01 02:31:00"]

dates = [dt.fromisoformat(date.replace("/", "-")) for date in dates]
events = [dt.fromisoformat(event.replace("/", "-")) for event in events] 
buckets = [(x,y) for x,y in zip(dates, dates[1:])]

result = dict()

for start, end in buckets:  
  result[str(start) + " to " + str(end)] = sum([1 if start >= date < end else 0 for date in dates])

print(result)
# {'2018-01-01 01:00:00 to 2018-01-01 02:30:00': 1, '2018-01-01 02:30:00 to 2018-01-01 04:00:00': 2}
0 голосов
/ 05 апреля 2020

Попробуйте это:

# pip install dateutil-python
from collections import Counter
import dateutil.parser

bases = [
    "2018/01/01 01:00:00",
    "2018/01/01 02:30:00",
    "2018/01/01 03:10:00",
    "2018/01/01 04:00:00",
    "2018/01/01 05:25:00"
]

occurances = [
    "2018/01/01 01:01:00",
    "2018/01/01 01:02:00",
    "2018/01/01 02:31:00",
    "2018/01/01 04:05:00"
]

class DateInterval:
    def __init__(self, start, end):
        self.start = dateutil.parser.parse(start)
        self.end = dateutil.parser.parse(end)
    def __contains__(self, other) -> bool:
        return self.start <= dateutil.parser.parse(other) <= self.end
    def __repr__(self):
        return f'<Interval:{self.start} ~ {self.end}>'

my_intervals = Counter({DateInterval(i, bases[n+1]): 0 for n, i in enumerate(bases) if n < len(bases)-1})

for occ in occurances:
    for intr in my_intervals:
        my_intervals[intr] += int(occ in intr)

print(my_intervals)
...