Python 事件序列的动态滚动计数

Python 事件序列的动态滚动计数,python,pandas,count,sequence,rolling-computation,Python,Pandas,Count,Sequence,Rolling Computation,我有以下虚拟数据帧: import pandas as pd import numpy as np def random_dates(start, end, n, freq, seed=None): if seed is not None: np.random.seed(seed) dr = pd.date_range(start, end, freq=freq) return pd.to_datetime(np.sort(np.random.choi

我有以下虚拟数据帧:

import pandas as pd
import numpy as np

def random_dates(start, end, n, freq, seed=None):
    if seed is not None:
        np.random.seed(seed)

    dr = pd.date_range(start, end, freq=freq)
    return pd.to_datetime(np.sort(np.random.choice(dr, n, replace=False)))

data = {'Timestamp': random_dates('2018-01-01', '2018-01-02', 21, 'H', seed=[3, 1415]), 
        'Group': [1,1,1,1,1,1,1,1,1,1,1,1,
                 2,2,2,2,2,2,2,2,2],
        
        'Event': ['A','A','A','B','A','A','A','B','A','A','A','B',
                'A','A','B','A','A','B','A','A','B']}

df = pd.DataFrame(data, columns = ['Timestamp', 'Group', 'Event'])
print(df)

             Timestamp  Group Event
0  2018-01-01 00:00:00      1    A
1  2018-01-01 01:00:00      1    A
2  2018-01-01 03:00:00      1    A
3  2018-01-01 04:00:00      1    B
4  2018-01-01 05:00:00      1    A
5  2018-01-01 06:00:00      1    A
6  2018-01-01 07:00:00      1    A
7  2018-01-01 08:00:00      1    B
8  2018-01-01 09:00:00      1    A
9  2018-01-01 12:00:00      1    A
10 2018-01-01 13:00:00      1    A
11 2018-01-01 14:00:00      1    B
12 2018-01-01 15:00:00      2    A
13 2018-01-01 17:00:00      2    A
14 2018-01-01 18:00:00      2    B
15 2018-01-01 19:00:00      2    A
16 2018-01-01 20:00:00      2    A
17 2018-01-01 21:00:00      2    B
18 2018-01-01 22:00:00      2    A
19 2018-01-01 23:00:00      2    A
20 2018-01-02 00:00:00      2    B
我想要每个“组”的“事件”列的动态滚动计数。例如可以看出,
df['Group']==1
具有事件序列:

A, A, A, B
事件序列每三分之一发生一次,因此有一个3,1的序列。而
df['Group']==2
是:

A, A, B
其中事件序列每秒发生一次,因此具有2,1的序列。理想情况下,我会:

Group Event Sequence 
1      A      3      
1      B      1      
1      A      3      
1      B      1      
1      A      3      
1      B      1      
2      A      2      
2      B      1      
2      A      2      
2      B      1      
2      A      2      
2      B      1      
这样我就可以画出顺序以便监控。通过“动态”,如图所示,事件的发生正在发生变化,即使是在一个组内!例如,
df['Group']==1
也可以看到3、1、3、1、2、1

计算每个事件序列的经过时间也很好。这可以计算为每个组的每个序列的最后一个和第一个事件时间戳之间的差值,我们将有:

Group Event Sequence ElapsedTime
1      A      3      4
1      B      1      1
1      A      3      3
1      B      1      1
1      A      3      5
1      B      1      1
2      A      2      3
2      B      1      1
2      A      2      2
2      B      1      1
2      A      2      2
2      B      1      None
此处,组1中“事件”A的第一个序列的第一行的ElapsedTime计算为:

df[df['Group']==1]['Timestamp'].iloc[2] - df[df['Group']==1]['Timestamp'].iloc[0]
df[df['Group']==1]['Timestamp'].iloc[3] - df[df['Group']==1]['Timestamp'].iloc[2]
第1组中“事件”B第一序列的第二行计算如下:

df[df['Group']==1]['Timestamp'].iloc[2] - df[df['Group']==1]['Timestamp'].iloc[0]
df[df['Group']==1]['Timestamp'].iloc[3] - df[df['Group']==1]['Timestamp'].iloc[2]
我在pandas中尝试了滚动计数、重采样、groupby.cumcount()方法等,但没有一个返回我感兴趣的结果。我确信这些方法以groupby方式的复杂组合应该可以完成这项工作(至少在第一个场景中),但我已经花了足够的时间尝试和搜索,到目前为止没有成功。这超出了我目前对熊猫的了解


再次感谢您的时间和经验。

好的。我没有放弃!事实证明,我还需要1-2个小时才能找到解决方案(主要是受@DSM的启发),我学到了很多东西,对于那些可能遇到这种数据转换的人,包括经过的时间:

df['Lag'] = df['Timestamp'].shift(-1) 
df['Seq'] = df["Event"].groupby((df.Event != df.Event.shift()).cumsum()).transform('size')
df['SeqID'] = (df.Event != df.Event.shift()).cumsum()

df_grp = df.groupby(['Group','SeqID']).first().reset_index()
df_grp['Elapsed(min)'] =  (df.groupby(['Group','SeqID'])['Lag'].last() - df.groupby(['Group','SeqID'])['Timestamp'].first()).reset_index()[0]/ np.timedelta64(1, 'm')

df_grp = df_grp.drop(['Timestamp','Lag'],axis=1)
print(df_grp)


    Group  SeqID Event  Seq  Elapsed(min)
0       1      1     A    3         240.0
1       1      2     B    1          60.0
2       1      3     A    3         180.0
3       1      4     B    1          60.0
4       1      5     A    3         300.0
5       1      6     B    1          60.0
6       2      7     A    2         180.0
7       2      8     B    1          60.0
8       2      9     A    2         120.0
9       2     10     B    1          60.0
10      2     11     A    2         120.0
11      2     12     B    1           NaN

祝你快乐

数据
中,第三个元素应该是
事件
,而不是
名称
.transform('size')
的作用是什么?就像聚合函数一样,使用参数'size'计算事件的数量,请参见此处: