Python 检测逐渐变化的数据集中的重大变化

Python 检测逐渐变化的数据集中的重大变化,python,statistics,data-analysis,Python,Statistics,Data Analysis,我有一个python数据列表,表示每分钟使用的资源量。我想找出它在数据集中显著变化的次数。我所说的重大变化与我到目前为止读到的有点不同 例如,如果我有一个数据集,如 [10,15,17,20,30,40,50,70,80,60,40,20] 我说,当数据比以前的正常值增加一倍或减少一半时,就会发生重大变化 例如,由于列表以10开头,这是我们的正常起点 然后,当数据翻倍到20时,我将其视为一个重大变化,并将法线设置为20 然后,当数据翻倍到40,它被认为是一个重大的变化,正常值现在是40 然后,当

我有一个python数据列表,表示每分钟使用的资源量。我想找出它在数据集中显著变化的次数。我所说的重大变化与我到目前为止读到的有点不同

例如,如果我有一个数据集,如
[10,15,17,20,30,40,50,70,80,60,40,20]

我说,当数据比以前的正常值增加一倍或减少一半时,就会发生重大变化

例如,由于列表以10开头,这是我们的正常起点

然后,当数据翻倍到20时,我将其视为一个重大变化,并将法线设置为20

然后,当数据翻倍到40,它被认为是一个重大的变化,正常值现在是40

然后,当数据翻倍到80,它被认为是一个重大的变化,正常值现在是80

之后,当数据减少一半至40时,它被视为另一个显著变化,正常值变为40

最后,当数据减少一半至20时,这是最后一次重大变化

这里共有5项重大变化


它与任何其他变化检测算法类似吗?如何在python中高效地实现这一点?

这相对简单。您可以通过列表中的单个迭代来实现这一点。当发生“重大”变化时,我们只需更新我们的基础

请注意,我的实现将适用于任何iterable或容器。例如,如果您希望在不必将文件全部加载到内存的情况下通读文件,这将非常有用

def gen_significant_changes(iterable, *, tol = 2):
    iterable = iter(iterable) # this is necessary if it is container rather than generator.
    # note that if the iterable is already a generator iter(iterable) returns itself.
    base = next(iterable)
    for x in iterable:
        if x >= (base * tol) or x <= (base/tol):
            yield x
            base = x

my_list = [10,15,17,20,30,40,50,70,80,60,40,20]

print(list(gen_significant_changes(my_list)))
def gen\u重大变化(iterable,*,tol=2):
iterable=iter(iterable)#如果它是容器而不是发电机,这是必需的。
#请注意,如果iterable已经是生成器,iter(iterable)将返回自身。
基本=下一个(iterable)
对于iterable中的x:

如果x>=(基*tol)或x,这是相对简单的。您可以通过列表中的单个迭代来实现这一点。当发生“重大”变化时,我们只需更新我们的基础

请注意,我的实现将适用于任何iterable或容器。例如,如果您希望在不必将文件全部加载到内存的情况下通读文件,这将非常有用

def gen_significant_changes(iterable, *, tol = 2):
    iterable = iter(iterable) # this is necessary if it is container rather than generator.
    # note that if the iterable is already a generator iter(iterable) returns itself.
    base = next(iterable)
    for x in iterable:
        if x >= (base * tol) or x <= (base/tol):
            yield x
            base = x

my_list = [10,15,17,20,30,40,50,70,80,60,40,20]

print(list(gen_significant_changes(my_list)))
def gen\u重大变化(iterable,*,tol=2):
iterable=iter(iterable)#如果它是容器而不是发电机,这是必需的。
#请注意,如果iterable已经是生成器,iter(iterable)将返回自身。
基本=下一个(iterable)
对于iterable中的x:

如果x>=(base*tol)或x我无法帮助您完成Python部分,但是从数学角度来说,您要问的问题非常简单,可以使用log base 2来解决。当当前值除以常数可以通过将2提高到与前一个值不同的幂次(作为整数)来达到时,会发生显著变化。(由于数组中的第一个值构成比较的基础,因此需要该常量。)

对于
t
处的每个元素,计算:

current  = math.log(Array[t]  /Array[0], 2)
previous = math.log(Array[t-1]/Array[0], 2)
if math.floor(current) <> math.floor(previous) a significant change has occurred
current=math.log(数组[t]/Array[0],2)
previous=math.log(数组[t-1]/Array[0],2)
如果math.floor(当前)math.floor(上一个)发生了重大变化

使用这种方法,您根本不需要跟踪“法线点”,只需要阵列。通过删除额外的状态变量,我们可以按任意顺序处理数组,如果数据集非常大,我们可以将数组的一部分分配给不同的线程。使用当前的方法无法做到这一点。

我无法帮助您完成Python部分,但在数学方面,您所问的问题非常简单,可以使用log base 2解决。当当前值除以常数可以通过将2提高到与前一个值不同的幂次(作为整数)来达到时,会发生显著变化。(由于数组中的第一个值构成比较的基础,因此需要该常量。)

对于
t
处的每个元素,计算:

current  = math.log(Array[t]  /Array[0], 2)
previous = math.log(Array[t-1]/Array[0], 2)
if math.floor(current) <> math.floor(previous) a significant change has occurred
current=math.log(数组[t]/Array[0],2)
previous=math.log(数组[t-1]/Array[0],2)
如果math.floor(当前)math.floor(上一个)发生了重大变化
使用这种方法,您根本不需要跟踪“法线点”,只需要阵列。通过删除额外的状态变量,我们可以按任意顺序处理数组,如果数据集非常大,我们可以将数组的一部分分配给不同的线程。用你目前的方法你无法做到这一点