Pandas - 将相近事件分组
我的问题可以通过一个例子来说明,假设 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