#python #pandas #counting
#python #pandas #подсчет
Вопрос:
Я пытаюсь вычислить скорость появления событий в фрейме данных.
У меня есть фрейм данных в pandas, который отслеживает начало и продолжительность определенного события. Итак, изначально это будет выглядеть примерно так:
onset duration label channels end_time
0 1.5 0.1 HFO A1 10
1 2.0 1.0 HFO A2 10
2 3.0 1.0 HFO A3 10
3 5.5 0.1 HFO A1 10
где onset
и duration
и end_time
в секундах. channels
обозначьте уникальный набор групп, которые я хочу перебрать.
Желаемый результат
Я хотел бы получить что-то вроде этого:
rate_dict = {
'A1': 0.2, # rate of 0.2 per second (i.e. 2 occurrences over 10 second time frame)
'A2': 0.1, # rate of 0.1 per second
'A3': 0.1
}
Моя попытка до сих пор
Во-первых, я получаю группу на основе channels
:
for idx, group in df.groupby(['channels']):
Затем я преобразую данные в индекс даты и времени
onset duration label channels end_time
timestamp
2021-02-10 19:25:19.391130 00:00 1.5 0.1 HFO A1 10
2021-02-10 19:25:23.391130 00:00 5.5 0.1 HFO A1 10
Затем я рассмотрел возможность повторной индексации по времени начала (0 секунд) и окончания (в данном случае 10 секунд):
# rate is say 's' for creating a dummy row for every second
dt_idx = pd.date_range(ref_timestamp, end_timestamp, freq=rate)
group = group.reindex(dt_idx, fill_value=np.nan)
Проблема в том, что он не улавливает события, которые происходят через 1,5 и 5,5 секунды для канала A1. Таким образом, я в конечном итоге получаю по существу строки всех nan, тогда как в идеале я получаю количество 2 за этот период, который я пересчитал.
Желаемое обобщение
В идеале я могу указать другие строки скорости (например, «hr»), и это вернет скорость за час. В этом случае это будет:
rate_dict = {
'A1': 2.0, # rate of 2 per hr (i.e. 2 occurrences over a 1 hour time frame)
'A2': 1.0, # rate of 1 per hr
'A3': 1.0
}
Ответ №1:
Во-первых, мы можем воссоздать вашу таблицу как фрейм данных Pandas:
import pandas as pd
d = {'onset': [1.5 ,2.0 ,3.0 ,5.5],
'duration': [0.1, 1.0, 1.0, 0.1],
'label': ['HFO', 'HFO', 'HFO', 'HFO'],
'channels': ['A1', 'A2', 'A3', 'A1'],
'end_time': [10.0, 10.0, 10.0, 10.0]}
df = pd.DataFrame(d)
Чтобы решить ваш вопрос напрямую, в терминах вхождений в секунду, мы можем подсчитать вхождения и разделить на среднее end_time
:
df.groupby('channels').end_time.agg(lambda x: x.count()/x.mean()).to_dict()
Чтобы обобщить это, давайте создадим функцию to_freq
, которая принимает в качестве входных данных как ряд x
, так и желаемую частоту в виде строки rate
:
def to_freq(x, rate='s'):
d = {'s':1, 'm': 60, 'h': 60*60, 'd': 60*60*24}
f = x.count()/x.mean()
return f/d[rate]
Теперь наш исходный код становится:
df.groupby('channels').end_time.agg(lambda x: to_freq(x)).to_dict()
И мы можем найти количество вхождений в час следующим образом:
df.groupby('channels').end_time.agg(lambda x: to_freq(x, rate='h')).to_dict()
Ответ №2:
Сгруппируйте по каналам, подсчитайте появление и разделите на среднее время окончания. Поскольку вхождения в группу больше, чем размер группы, в этом случае нет никакого вреда в локализации вхождения в end_time, поскольку вариаций не так много.
df.groupby('channels')['end_time'].agg(lambda x: x.count()/x.mean()).to_dict()