Python 时间序列中的状态变化检测

Python 时间序列中的状态变化检测,python,Python,我想检测一个时间序列的制度变化或异常。 所谓政权更迭,我的意思是线性趋势被改变/打破,见下图 import numpy as np import matplotlib.pyplot as plt x = range(50) y = [1.28, 1.28, 1.26, 1.32, 1.34, 1.33, 1.38, 1.39, 1.37, 1.42, 1.42, 1.41, 1.39, 1.41, 1.45, 1.45, 1.46, 1.5, 1.49, 1.53, 1.53, 1.54,

我想检测一个时间序列的制度变化或异常。 所谓政权更迭,我的意思是线性趋势被改变/打破,见下图

import numpy as np
import matplotlib.pyplot as plt

x = range(50)
y = [1.28, 1.28, 1.26, 1.32, 1.34, 1.33, 1.38, 1.39, 1.37, 1.42, 
1.42, 1.41, 1.39, 1.41, 1.45, 1.45, 1.46, 1.5, 1.49, 1.53, 1.53, 
1.54, 1.61, 1.59, 1.62, 1.66, 1.63, 1.66, 1.66, 1.7, 1.76, 1.84, 
1.88, 1.97, 1.94, 1.98, 2.01, 2.02, 0.73, 0.72, 0.76, 0.87, 0.97, 
1.01, 0.98, 1.16, 1.22, 1.3, 1.27, 1.33]

plt.scatter(x, y)
plt.show()
我已经搜索了一段时间,但找不到一种方法来检测这个时间序列中的重大变化

检测差异对我来说是不够的,因为我需要能够检测到粗略的线性趋势发生了变化。数据从一个观测值到下一个观测值的差值可能很大,但趋势线性趋势仍然正确

为了解释我为什么放弃diff方法:

在45-46左右的x轴上的观察显示该值有跳跃,但实际上呈线性趋势,因此对我来说不是政权变化。这正是我放弃diff方法的原因,我正在寻找一种趋势方法。
我一直在考虑循环观察、拟合线性回归、预测下一个点、计算误差等。但如果存在,我更愿意使用为此制作的库。

让我绘制数据的橙色和二阶绿色差异:

就我所见,这两种方法对跳跃的检测似乎都很有区别,在这种情况下,一个简单的阈值将用作分类器

考虑到你如何描述任务,二阶差应该特别指示跳跃:对于线性变化,对于非跳跃部分,它必然在零左右

复制绘图的完整代码:

import numpy as np                                                                                                                                                                                                                           
import matplotlib.pyplot as plt                                                                                                                                                                                                              


x = range(50)                                                                                                                                                                                                                                
y = [1.28, 1.28, 1.26, 1.32, 1.34, 1.33, 1.38, 1.39, 1.37, 1.42,                                                                                                                                                                             
1.42, 1.41, 1.39, 1.41, 1.45, 1.45, 1.46, 1.5, 1.49, 1.53, 1.53,                                                                                                                                                                             
1.54, 1.61, 1.59, 1.62, 1.66, 1.63, 1.66, 1.66, 1.7, 1.76, 1.84,                                                                                                                                                                             
1.88, 1.97, 1.94, 1.98, 2.01, 2.02, 0.73, 0.72, 0.76, 0.87, 0.97,                                                                                                                                                                            
1.01, 0.98, 1.16, 1.22, 1.3, 1.27, 1.33]                                                                                                                                                                                                     


def get_deltas(series):                                                                                                                                                                                                                      
    return [series[i+1] - series[i] for i in range(len(series)-1)]                                                                                                                                                                           


y_delta = get_deltas(y)                                                                                                                                                                                                                      
y_delta_delta = get_deltas(y_delta)                                                                                                                                                                                                          

plt.scatter(x, y)                                                                                                                                                                                                                            
plt.scatter(x[:-1], y_delta)                                                                                                                                                                                                                 
plt.scatter(x[:-2], y_delta_delta)                                                                                                                                                                                                           
plt.show()                                                                                                                                                                                                                                   

定义政权更迭。你想对这个检测的结果做什么?你有没有用np查看和查看标记副本中的第一个答案。diff@tucson那么请给出一个例子,其中纯差绝对值是不够的。@dedObed实际上,在45-46周围的x轴上的观察显示该值有一个跳跃,这将引发相当大的差异,但实际上是线性趋势,因此对我来说不是政权更迭。这正是我放弃diff方法的原因,我正在寻找一种趋势方法。