Python 如何检测时间序列中的翻转?

Python 如何检测时间序列中的翻转?,python,time-series,Python,Time Series,对于在不同操作模式下运行的系统,我希望减少模式之间的翻转。为此,需要检测翻转并进行校正 假设我们有一个模式频繁切换的序列: before = [0,0,0,(1,0),1,1,1,2,2,(1,2),1,1,1,(0,1),0] # parenthesis indicate flipping 我只想在(变化点)进行某种交换,以获得: 如何实现这一点?我通过开发一个用于翻转检测的小型卷积滤波器解决了这个问题。 到目前为止,它可以检测到单个翻转(开-关-开或关-开-关) 构建差分信号允许支持不

对于在不同操作模式下运行的系统,我希望减少模式之间的翻转。为此,需要检测翻转并进行校正

假设我们有一个模式频繁切换的序列:

before = [0,0,0,(1,0),1,1,1,2,2,(1,2),1,1,1,(0,1),0]   # parenthesis indicate flipping
我只想在(变化点)进行某种交换,以获得:


如何实现这一点?

我通过开发一个用于翻转检测的小型卷积滤波器解决了这个问题。 到目前为止,它可以检测到单个翻转(开-关-开或关-开-关)

构建差分信号允许支持不同的单交换,即使在两种以上的操作模式之间也是如此

import numpy as np
import matplotlib.pyplot as plt

before = np.array([0,0,1,0,0,1,0,1,1,1,2,2,1,2,1,1,1,0,1,0,0])
goal = np.array(  [0,0,0,0,0,0,1,1,1,1,2,2,2,1,1,1,1,1,0,0,0])
after  = before.copy()
fltr = np.array([1,2,5,10])        # convolution filter

for i in range(0,len(before)-4):
    dif = np.diff(after)
    conv = (fltr*dif[i:i+4]).sum() # conv-filter applied on diff()
    if abs(conv) == 3:       # 00100 = 00000 or 11011 = 11111
        after[i+2] = after[i+1]  
    if abs(conv) == 7:
        b = after[i+2]       # 00101 = 00011 or 11010 = 11100
        after[i+2] = after[i+3]
        after[i+3] = b

plt.plot(before, linestyle='--',label='before')
plt.plot(goal,   linestyle='-.',label='goal')
plt.plot(after,  linestyle=':', label='after')

plt.legend()
plt.show

注意:此解决方案可能不完整,无法涵盖所有可能的场景。请推荐更高级/替代解决方案。

有一种“更简单”的方法来查找范围1的翻转,但不适用于连续重复翻转

before = np.array([0,0,1,0,0,1,0,1,1,1,2,2,1,2,1,1,1,0,1,0,0])
goal = np.array(  [0,0,0,0,0,0,1,1,1,1,2,2,2,1,1,1,1,1,0,0,0])

diff = np.diff(before)          # find 'jumps' with range 1
diff[:-1][(diff == 0)[1:]] = 0  # correct 'right' side of 'jumps'
after = before - np.r_[0,diff]  # correct flipping

plt.plot(before, linestyle='--',label='before')
plt.plot(goal,   linestyle='-.',label='goal')
plt.plot(after,  linestyle=':', label='after')
plt.legend();
输出

使用更大的步幅和负“跳跃”

before = np.array([0,0,-1,0,0,1,0,1,1,1,4,4,1,4,1,1,1,0,1,0,0])
goal = np.array(  [0,0, 0,0,0,0,1,1,1,1,4,4,4,1,1,1,1,1,0,0,0])

diff = np.diff(before)          # find flipping with range 1
diff[:-1][(diff == 0)[1:]] = 0  # correct 'right' side of signal
after = before - np.r_[0,diff]  # correct flipping

plt.plot(before, linestyle='--',label='before')
plt.plot(goal,   linestyle='-.',label='goal')
plt.plot(after,  linestyle=':', label='after')
plt.legend();
输出


解的极限
  • 连续反复翻转

你的问题很有趣。我认为你自己的努力应该是问题的一部分。起初我认为这个问题已经得到了恰当的回答。像
0,1,2
0,1,1,2
这样的模式变化是否可能?甚至
0,2
?事实上,答案反映了我自己的解决方案,因为到目前为止我还没有得到外部支持。我最初的问题在三天后就结束了。@Wups到目前为止,它只考虑了单个步骤。使用卷积方法,通过添加额外的if语句,可以轻松添加两个步骤。重要的是确保没有引入歧义。这就是为什么我的过滤器值被选择为
[1,2,5,10]
。您能解释一下为什么要使用过滤器吗?您可以将每个样本与下一个(和上一个)样本进行比较以查看翻转情况?使用卷积过滤器的优点是,它不仅考虑当前和上一个样本。当卷积集成超过5个样本(4个差异)时,它将2个样本展望未来和过去。如果你用If语句实现它,它会变得非常混乱。这是一个非常好的观点。当系统不断翻转时,不能将其分配到一个或另一个状态。但是您仍然可以使用卷积来检测它[0,1,0,1,0]将卷积为-6,“[1,0,1,0,1]将根据我下面的答案给出6。”
before = np.array([0,0,-1,0,0,1,0,1,1,1,4,4,1,4,1,1,1,0,1,0,0])
goal = np.array(  [0,0, 0,0,0,0,1,1,1,1,4,4,4,1,1,1,1,1,0,0,0])

diff = np.diff(before)          # find flipping with range 1
diff[:-1][(diff == 0)[1:]] = 0  # correct 'right' side of signal
after = before - np.r_[0,diff]  # correct flipping

plt.plot(before, linestyle='--',label='before')
plt.plot(goal,   linestyle='-.',label='goal')
plt.plot(after,  linestyle=':', label='after')
plt.legend();
    before = [0,1,0,1,0,1,1,1,1]
    goal   = [0,0,0,0,1,1,1,1,1]