删除统计异常值的更好方法比这更好



这段代码有效。但我不禁觉得这是一个黑客,尤其是"偏移"部分。我必须把它放在那里,否则每次我执行 del 操作时,删除中的所有索引值都会移动一个。

    # remove outliers > devs # of std deviations
    devs = 1
    deletes = []
    for num, duration in enumerate(durations):
        if (duration > (mean_duration + (devs * std_dev_one_test))) or 
            (duration < (mean_duration - (devs * std_dev_one_test))):
            deletes.append(num)
    offset = 0
    for delete in deletes:
        del durations[delete - offset]
        del dates[delete - offset]
        offset += 1

关于如何让它变得更好的想法?

在迭代列表时构建一个守护者列表:

def isKeeper( duration ):
    if (duration > (mean_duration + (devs * std_dev_one_test))) or 
            (duration < (mean_duration - (devs * std_dev_one_test))):
        return False
    return True
durations = [duration for duration in durations if isKeeper(duration)]

也许是这样的:

import numpy as np        
myList = [1,2,3,4,5,6,7,3,4,5,3,5,99] 
mean_duration  = np.mean(myList)
std_dev_one_test = np.std(myList)     
def drop_outliers(x):
    if abs(x - mean_duration) <= std_dev_one_test:
        return x
myList = filter(drop_outliers, myList)

结果:

>>> myList
[1, 2, 3, 4, 5, 6, 7, 3, 4, 5, 3, 5]

问题是您正在从列表中删除项目并导致索引移动并且您正在用偏移进行补偿吗?

如果是这种情况,那么只需从后面到前面删除,这样当您删除项目时,它不会影响列表的其余部分。

因此,从最后一项开始迭代到列表的前面。

这些SO问题可能会感兴趣 删除列表(python)和Python的许多元素:在迭代列表时删除列表元素

另一个很好的SO讨论可以在这里找到:迭代时从列表中删除项目(感谢@PaulMcGuire通过评论提出的建议)

如果你的数据集很小,你可以反转你的逻辑,保留值而不是删除它们:

# keep value outliers < devs # of std deviations
devs = 1
keeps = []
for duration in durations:
    if (duration <= (mean_duration + (devs * std_dev_one_test))) and 
        (duration >= (mean_duration - (devs * std_dev_one_test))):
        keeps.append(duration)

最新更新