Python 计算特定标签在滑动窗口中的出现次数
我有下面的数据框Python 计算特定标签在滑动窗口中的出现次数,python,pandas,dataframe,data-manipulation,Python,Pandas,Dataframe,Data Manipulation,我有下面的数据框 t_msec ID 0 1.1 0200 1 1.4 020a 2 8.9 01f4 3 11.1 0200 4 13.2 02e2 ... ... ... 85454 189915.3 02e4 85455 189915.6 02e6 85456 189921.8 0200 85457 189922.3 01f4
t_msec ID
0 1.1 0200
1 1.4 020a
2 8.9 01f4
3 11.1 0200
4 13.2 02e2
... ... ...
85454 189915.3 02e4
85455 189915.6 02e6
85456 189921.8 0200
85457 189922.3 01f4
85458 189924.0 020a
我想运行一个滑动窗口,该窗口提前1秒统计特定标签的出现次数
only_id_df = df[df.ID == id]
counts = Counter()
for index, row in only_id_df.iterrows():
mask = (only_id_df.t_msec< row.t_msec + 1000) & (only_id_df.t_msec> row.t_msec)
counts.update([len(only_id_df[mask])])
only_id_df=df[df.id==id]
计数=计数器()
对于索引,仅为_id_df.iterrows()中的行:
掩码=(仅限id测向t_msecrow.t_msec)
计数。更新([len(仅\u id\u df[mask]))
然而,这是非常缓慢的,我知道必须有一种方法来执行它,而不必手动迭代每一行和过滤(我知道这是低效的)
实现这一目标的正确途径是什么?如何加快计算速度?在测试中,我使用了以下数据帧:
t_msec ID
0 60 0200
1 70 020a
2 445 01f4
3 555 0200
4 660 02e2
5 1005 0200
6 1510 02e2
7 2105 0200
8 2260 02e2
因此,如果我们在距初始行1s内查找例如ID='0200'
(t_msec==60)向前,则在
t_msec==[605551005]
要计算整个结果,我们必须执行一些技巧:
- 将索引计算为df.t_msec.max()-df.t_msec[ms]
- 按相反的顺序处理
- 再次颠倒结果的顺序
- 我们想看看ID列(一个字符串)
- 但滚动计算只能在数值列上执行
lbl = int('0200', 16) # Label to look for (hex -> dec)
# ID converted to dec
df['ID_dec'] = df.ID.apply(lambda x: int(x, 16))
# Set index
df = df.set_index(pd.to_datetime(df.t_msec.max() - df.t_msec, unit='ms'))
因此,df现在包含:
t_msec ID ID_dec
t_msec
1970-01-01 00:00:02.200 60 0200 512
1970-01-01 00:00:02.190 70 020a 522
1970-01-01 00:00:01.815 445 01f4 500
1970-01-01 00:00:01.705 555 0200 512
1970-01-01 00:00:01.600 660 02e2 738
1970-01-01 00:00:01.255 1005 0200 512
1970-01-01 00:00:00.750 1510 02e2 738
1970-01-01 00:00:00.155 2105 0200 512
1970-01-01 00:00:00.000 2260 02e2 738
第二个(主要)步骤是计算Nr列:
注意[:-1]反转源列和结果本身
现在df包含:
t_msec ID ID_dec Nr
t_msec
1970-01-01 00:00:02.200 60 0200 512 3
1970-01-01 00:00:02.190 70 020a 522 2
1970-01-01 00:00:01.815 445 01f4 500 2
1970-01-01 00:00:01.705 555 0200 512 2
1970-01-01 00:00:01.600 660 02e2 738 1
1970-01-01 00:00:01.255 1005 0200 512 1
1970-01-01 00:00:00.750 1510 02e2 738 1
1970-01-01 00:00:00.155 2105 0200 512 1
1970-01-01 00:00:00.000 2260 02e2 738 0
最后一步是删除临时列并恢复
原始索引:
df = df.drop(columns='ID_dec').reset_index(drop=True)
最终结果是:
t_msec ID Nr
0 60 0200 3
1 70 020a 2
2 445 01f4 2
3 555 0200 2
4 660 02e2 1
5 1005 0200 1
6 1510 02e2 1
7 2105 0200 1
8 2260 02e2 0
执行时间应该大大缩短。写一条关于您和我的代码的执行时间(+行号)的注释。对于我的测试,我使用了以下数据帧:
t_msec ID
0 60 0200
1 70 020a
2 445 01f4
3 555 0200
4 660 02e2
5 1005 0200
6 1510 02e2
7 2105 0200
8 2260 02e2
因此,如果我们在距初始行1s内查找例如ID='0200'
(t_msec==60)向前,则在
t_msec==[605551005]
要计算整个结果,我们必须执行一些技巧:
- 将索引计算为df.t_msec.max()-df.t_msec[ms]
- 按相反的顺序处理
- 再次颠倒结果的顺序
- 我们想看看ID列(一个字符串)
- 但滚动计算只能在数值列上执行
lbl = int('0200', 16) # Label to look for (hex -> dec)
# ID converted to dec
df['ID_dec'] = df.ID.apply(lambda x: int(x, 16))
# Set index
df = df.set_index(pd.to_datetime(df.t_msec.max() - df.t_msec, unit='ms'))
因此,df现在包含:
t_msec ID ID_dec
t_msec
1970-01-01 00:00:02.200 60 0200 512
1970-01-01 00:00:02.190 70 020a 522
1970-01-01 00:00:01.815 445 01f4 500
1970-01-01 00:00:01.705 555 0200 512
1970-01-01 00:00:01.600 660 02e2 738
1970-01-01 00:00:01.255 1005 0200 512
1970-01-01 00:00:00.750 1510 02e2 738
1970-01-01 00:00:00.155 2105 0200 512
1970-01-01 00:00:00.000 2260 02e2 738
第二个(主要)步骤是计算Nr列:
注意[:-1]反转源列和结果本身
现在df包含:
t_msec ID ID_dec Nr
t_msec
1970-01-01 00:00:02.200 60 0200 512 3
1970-01-01 00:00:02.190 70 020a 522 2
1970-01-01 00:00:01.815 445 01f4 500 2
1970-01-01 00:00:01.705 555 0200 512 2
1970-01-01 00:00:01.600 660 02e2 738 1
1970-01-01 00:00:01.255 1005 0200 512 1
1970-01-01 00:00:00.750 1510 02e2 738 1
1970-01-01 00:00:00.155 2105 0200 512 1
1970-01-01 00:00:00.000 2260 02e2 738 0
最后一步是删除临时列并恢复
原始索引:
df = df.drop(columns='ID_dec').reset_index(drop=True)
最终结果是:
t_msec ID Nr
0 60 0200 3
1 70 020a 2
2 445 01f4 2
3 555 0200 2
4 660 02e2 1
5 1005 0200 1
6 1510 02e2 1
7 2105 0200 1
8 2260 02e2 0
执行时间应该大大缩短。写一条关于你和我的代码执行时间的注释(+行号)