Скорость вычисления вхождений в единицу времени в фрейме данных pandas

#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()