连续开关信号之间的行数



我有一个"信号"系列,有1个值(开(、-1个值(关(和零值:

signal = pd.Series([0, 1, 0, 0, -1, 0, 1, 1, 0, -1])

我需要返回连续开和关信号之间的行数,在结果下方:

首次出现=3

第二次出现=2

要考虑存在两个或多个连续的on值时,引用是最后一个。

非常感谢。

问候Tom

您可以利用系列的索引标签:

s = signal[signal!=0]
np.diff(s[s.shift(-1) != s].index)[::2]

输出:

array([3, 2])

解释

首先,去除零:

s = signal[signal!=0]

然后,删除连续重复的(保留最后一个(:

s = s[s.shift(-1) != s]

查看输出以了解发生了什么:

1    1
4   -1
7    1
9   -1
dtype: int64

看到了吗,现在我们有一个,后面是负的,原始索引保留在那里。因此,我们可以计算这些指数的差异(只对正指数进行切片(:

np.diff(s.index)[::2]

基本解决方案

我要做的方法是定义几个状态,比如ON_SIGNAL_SEENRESET,然后逐步完成该系列,将事物视为状态机。因此,当你浏览每个项目时,你会有不同的行为,这取决于当前状态和系列中当前项目的组合。类似(伪代码(:

let counter = 0;
let result = [];
let state = RESET
for n in series:
if state == RESET:
if n == 1:
state = ON_SEEN
counter = 0
elif state == ON_SEEN
if n == -1
counter++
results += [counter]
state = RESET
elif n == 0
counter++
elif n == 1
counter = 0
return result

如果将每个状态定义为一个类,然后调用state = state.next(item),则还有一种更为面向对象的方法,其中state的值可以是状态对象ON_SEENRESET之一,每个状态对象都有不同的next()实现。

Regex解决方案

由于正则表达式状态机,我认为您还可以将数据转换为字符串并查找ab*?c模式。在这里,我在所有数字上加了2,以避免不得不处理-11(再次伪代码(:

result = []
//Change the nums from {0,1,-1} to {0,1,2} for easier matching
series = series.add_element_wise(2)
// Change to a string so we can use regex
series_string = (string) series
//Find matches of 2, then 1's, then 0 (with non-greedy matching)
for m in /21*?0/.match(series_string)
// Save the length of the match
result += [m.length]

最新更新