检测pandas数据框中两列信号的重叠事件。

问题描述 投票:0回答:1

我有一个数据框,有两列A和B,A和B的值可以是0.0或1.0(二进制状态)。

信号大部分时间都是0.0,偶尔有1.00。 我想检测每个事件,其中A和B都是1.00,并且是重叠的(内部连接)。

下面是一个示例代码。

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
%matplotlib inline
np.random.seed(101)

data = np.zeros((1200,2),dtype=float)

df = pd.DataFrame(data=data,
                  index=pd.date_range('2020-05-19', 
                  freq='50ms', periods=1200),
                  columns=['A','B'])
#event1
df.loc[pd.to_datetime('2020-05-19 00:00:01.000'):pd.to_datetime('2020-05-19 00:00:02.500'),'A'] =1.00
df.loc[pd.to_datetime('2020-05-19 00:00:01.500'):pd.to_datetime('2020-05-19 00:00:03.000'),'B'] =1.00
#event2
df.loc[pd.to_datetime('2020-05-19 00:00:12.000'):pd.to_datetime('2020-05-19 00:00:15.000'),'A'] =1.00
df.loc[pd.to_datetime('2020-05-19 00:00:13.000'):pd.to_datetime('2020-05-19 00:00:14.500'),'B'] =1.00
#event3
df.loc[pd.to_datetime('2020-05-19 00:00:40.000'):pd.to_datetime('2020-05-19 00:00:43.000'),'A'] =1.00
df.loc[pd.to_datetime('2020-05-19 00:00:42.000'):pd.to_datetime('2020-05-19 00:00:46.000'),'B'] =1.00

A和B的线段图,以显示重叠的情况。 请注意,我将A移动了0.01以使所有的线都可见。

def plot_Class_AB():
    fig, ax = plt.subplots(nrows=1,ncols=1,figsize=(15,4))
    ax.set_title("Checking overlaps of A and B")

    ax.plot(df['A'].dropna()+0.01,label="A",color='red')
    ax.plot(df['B'].dropna(),label="B",color='blue')
    ax.set_ylabel("Class")
    ax.legend()

Line plot of A and B signals

我可以得到第一个事件的开始时间和最后一个事件的结束时间,如下所示。

events_startTime = df[(df['A'] == 1.00)  & (df['B'] == 1.00)].head(1).index
events_endTime   = df[(df['A'] == 1.00)  & (df['B'] == 1.00)].tail(1).index
print('events_startTime:',events_startTime)
print('events_endTime:  ',events_endTime)

然而,我对单个事件的重叠时间感兴趣。 我期望的输出是类似于这样的。

event1_startTime = 2020-05-19 00:00:01.500
event1_endTime:  = 2020-05-19 00:00:02.500

event2_startTime = 2020-05-19 00:00:13.000
event2_endTime:  = 2020-05-19 00:00:14.500

event3_startTime = 2020-05-19 00:00:42.000
event3_endTime:  = 2020-05-19 00:00:43.000

你能不能建议一下如何解决这个问题?

python pandas dataframe
1个回答
1
投票

将两个信号相乘,找到乘积非零的指数呢?

import numpy as np

a = df['A'].dropna().values
b = df['B'].dropna().values

events_idxs = np.where(a*b > 0.5)[0]

(我放了一个0.5的阈值,因为看起来你的信号在事件外不完全是0)


0
投票

我使用了JacoSolari的建议,它返回一个A == B ==1.00的所有指数的列表。 对于上面的例子,它返回以下数组。

array([ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
        43,  44,  45,  46,  47,  48,  49,  50, 260, 261, 262, 263, 264,
       265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
       278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
       840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852,
       853, 854, 855, 856, 857, 858, 859, 860], dtype=int64)

最后我添加了下面的函数 从上面的数组中提取出所有事件的开始和停止指数列表 下面的代码。

def find_start_stop_indexes(df):

    a = df['A'].dropna().values
    b = df['B'].dropna().values

    events_idxs = np.where(a*b > 0.5)[0]

    if len(events_idxs) > 0:

        # initiate a list to store first,last index of each event
        first_last = [events_idxs[0]]
        i = 1
        while i < len(events_idxs):
            if (events_idxs[i] - events_idxs[i-1]) < 2:   
                i = i+1
                if i == len(events_idxs):
                    first_last.append(events_idxs[i-1])
            else:
                first_last.append(events_idxs[i-1])
                first_last.append(events_idxs[i])
                i = i +1
                if i == len(events_idxs):
                    first_last.append(events_idxs[i-1])

        return(first_last)
    else:
        return([])

上面例子的函数输出是。

[30, 50, 260, 290, 840, 860]

不知道是否有更简单的解决方案,但它的工作原理是:

© www.soinside.com 2019 - 2024. All rights reserved.