【问题标题】:Algos - Delete Extremes From A List of Integers in Python?算法 - 从 Python 中的整数列表中删除极值?
【发布时间】:2015-04-03 09:32:43
【问题描述】:

我想从 Python 中的整数列表中消除极端情况。我会说我的问题是设计问题之一。到目前为止,这是我做的:

listToTest = [120,130,140,160,200]

def function(l):
    length = len(l)
    for x in xrange(0,length - 1):
        if l[x] < (l[x+1] - l[x]) * 4:
            l.remove(l[x+1])
    return l

print function(listToTest)

所以这个输出应该是:没有 200 的 120,130,140,​​160,因为这距离其他的太远了。

这行得通,因为 200 是最后一个,或者只有一个极端。但是,这样的列表会出现问题:

listToTest = [120,200,130,140,160,200]

或者

listToTest = [120,130,140,160,200,140,130,120,200]

因此,最后一个列表的输出应该是:120,130,140,​​160,140,​​130,120。 200 应该没有了,因为它比“通常”大得多,它围绕 ~130-140 旋转。 为了说明这一点,这是一张图片: 显然,我的方法行不通。一些想法: - 我需要以某种方式在 x 和 x+1 之间进行比较,看看接下来的两对是否比最后一对有更大的差异,如果是,那么差异较大的那对应该消除一个元素(最大的一)然后,递归地再次执行此操作。我认为我也应该有一个“可接受的差异”,所以它知道什么时候差异是可以接受的并且不会破坏递归性,所以我最终只有 2 个值。

我试过写它,但到目前为止没有运气。

【问题讨论】:

    标签: python list loops recursion


    【解决方案1】:

    您的问题陈述不清楚。如果您只是想删除最大值和最小值,那么这很简单

    O(N) with  2 extra memory- which is O(1) 
    

    操作。这是通过保留当前的最小值/最大值并依次与列表中的每个条目进行比较来实现的。

    如果你想要最小/最大 K 个项目,它仍然是

     O(N + KlogK)  with O(k) extra memory
    

    操作。这是通过两个大小为 K 的优先级队列来实现的:一个用于最小值,一个用于最大值。

    或者您是否打算从您的算法中获得不同的输出/结果?

    UPDATE OP 更新了问题:他们似乎想要一个移动(/windowed)平均值并删除异常值。

    以下是一个在线算法——即它可以处理流数据http://en.wikipedia.org/wiki/Online_algorithm

    我们可以保留移动平均线:假设您保留 K 个条目作为平均值。

    然后创建一个大小为 K 的链表和一个指向头尾的指针。现在:处理前 K 个条目中的项目需要单独考虑。在前 K 保留 项之后,算法可以进行如下操作: 根据运行的 k 平均值检查输入列表中的下一项。如果该值超过可接受的比率阈值,则将其列表索引放入单独的“删除队列”列表中。否则:更新运行窗口总和如下:

    • (a) 从链表中删除头部条目并从运行总和中减去其值
    • (b) 将最新的列表条目添加为链表的尾部,并将其值添加到运行总和 (c) 将运行平均值重新计算为运行总和/K

    现在:如何处理前 K 个条目? - 即在我们有一个正确初始化的运行总和之前?

    您需要在这里做出一些硬编码的决定。一种可能性:

    • 遍历所有前 K+2D (D
    • 保留 d 最大值/最小值
    • 从该列表中删除 d (

    【讨论】:

    • 好的,看来您正在寻找一个窗口函数来创建移动平均线:如果给定的新值超过该平均值......什么......某个相对分数? ..然后它被删除。这能抓住你的意图吗?
    • 听起来不错!是的,我认为这就是总结!
    • 我看到了你的逻辑,据我了解,它可以工作,虽然@trans 提供了一个解决方案,但我真的很想了解它背后的工作原理。将继续与他合作,谢谢!
    • 如果您可以选择先将整个数据集读入内存,@trans 的解决方案可以正常工作。我的解决方案是“在线”解决方案。你可以查一下这是什么意思:en.wikipedia.org/wiki/Online_algorithm
    • 我没想到。那么问题是我的算法从我那里获取数据,或者,列表是由一些计数生成的。 :) 我不是在这里寻找可用性/便携性。
    【解决方案2】:

    您可以在此处使用统计数据,消除超出平均值 n 个标准差的值:

    import numpy as np
    test = [120,130,140,160,200,140,130,120,200]
    n = 1
    output = [x for x in test if abs(x - np.mean(test)) < np.std(test) * n]
    # output is [120, 130, 140, 160, 140, 130, 120]
    

    【讨论】:

    • 感谢您的贡献 - 它有效!不过,你能提供一些关于这方面的文件吗?我真的很想自己写,了解它是如何工作的,这是我的最终目标。
    • 上面的输出是一个列表推导,它只在平均值的 1 个标准差范围内保留一个值,去掉高于或低于 1 个标准差的值。如果 n 设置为 2,那么它将去除高于或低于平均值 2 个标准差的值。 abs(x - np.mean(test)) 计算一个值与平均值的距离。 np.std(test) 假设正态分布计算standard deviation
    • 如果您有一个可以在执行计算之前完整阅读的小型数据集,这比我的答案更好(更简单)。
    • 谢谢,我明白了!现在阅读更多内容。
    • 虽然这不是一个移动算法,但根据您的用例,它可能或多或少是准确的。
    猜你喜欢
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2012-07-15
    相关资源
    最近更新 更多