Pandas - 将相近事件分组

2 投票
1 回答
1184 浏览
提问于 2025-04-18 18:38

我的问题可以通过一个例子来说明,假设 t 是时间索引,x 是数据,我们有以下输入:

t = [1,2,3, 7,9,11, 17,18,20]
x = [1,2,3, 4,5,6,   7,8,9]
s = ['P', 'P', 'N',  'N', 'N', 'N', 'P', 'P', 'P']
window = 2

想要的输出是:

t1 = [1, 3, 7, 17]
x1 = [3, -3, -15, 24]

也就是说,我想把 x 的数据分成几个组。具体来说,如果两个连续的数据点的时间差小于等于一个设定的窗口时间,并且它们的 s 值相同,就把它们放在一起,并把同一组里的所有值加起来。此外,那些 s 值为 N 的组,要把它们的总和变成负数。最后,取每个组里第一个数据点的时间作为这个组的时间。

例子解释:这些组是 (1,2), (3), (4,5,6), (7,8,9)。(3) 必须单独成组,因为虽然它和前一个数据点很接近,但它的 s 值不同。(4,5,6) 都是负数(s 值是 N),所以这个组的总值是 -(4+5+6) = -15。

1 个回答

4

这是一个开始。假设你有一个数据表,里面存放着你的数值,现在我们要在这个表里添加三列新数据,这些新数据是把原来的数据向后移动了一次。同时,还要添加一个带符号的x值。

df = pd.DataFrame({'t':t, 'x':x, 's':s})
df[['s_1', 't_1', 'x_1']] = df.shift(-1)
df['x_signed'] = np.where(df['s'] == 'N', -1 * df['x'], df['x'])

接下来,添加一列布尔值(也就是真或假),用来表示一个新组的开始,这个判断是基于你之前提到的两个条件。

df['cluster'] = (df['s'] != df['s_1']) | (df['t_1'] - df['t'] > window)

然后,把这些数据转换成组号,方法是把数据向后移动一次,填上第一个值(组号为0),再把这些值转换成整数,最后进行累加。

df['cluster'] = df['cluster'].shift(1).fillna(False).astype(int).cumsum()

从这里开始,使用分组功能就很简单了,可以得到你想要的结果。

In [72]: df.groupby('cluster').agg({'t':'first', 'x_signed':'sum'})
Out[72]: 
          t  x_signed
cluster              
0         1         3
1         3        -3
2         7       -15
3        17        24

撰写回答