计算 pandas 数据帧中每单位时间的出现率

Computing rate of occurrences per unit of time in a pandas dataframe

我正在寻求计算数据帧中事件发生的速率。

我在 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

其中 onsetduration 以及 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)

问题是它没有拾取频道 A1 在 1.5 和 5.5 秒处发生的事件。所以我最终基本上得到了所有 nans 的行,而理想情况下我在我重新采样的这段时间里得到了 2 的计数。

期望的泛化

理想情况下,我可以指定其他费率字符串(例如 'hr'),它将 return 每小时费率。在这种情况下,它将是:

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
    }

Groupby channels,统计发生次数,除以结束时间。因为每组的出现次数比组大小要少,所以在这种情况下将出现次数定位到 end_time 没有什么坏处,因为没有太大的变化。

df.groupby('channels')['end_time'].agg(lambda x: x.count()/x.mean()).to_dict()

首先,我们可以将您的 table 重新创建为 Pandas DataFrame:

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