从列表中检测异常值

3
我希望能够检测并存储列表中的异常值,以下是我的操作:
代码:
def outliers(y,thresh=3.5):
    
    m = np.median(y)
    abs_dev = np.abs(y - m)
    left_mad = np.median(abs_dev[y <= m])
    right_mad = np.median(abs_dev[y >= m])
    y_mad = left_mad * np.ones(len(y))
    y_mad[y > m] = right_mad
    modified_z_score = 0.6745 * abs_dev / y_mad
    modified_z_score[y == m] = 0
    return modified_z_score > thresh

bids = [5000,5500,4500,1000,15000,5200,4900]

z = outliers(bids)
bidd = np.array(bids)
out_liers = bidd[z]

这将产生以下结果:
out_liers = array([ 1000, 15000])

有没有更好的方法,不是返回数组而是返回列表呢? 还请有人能解释一下为什么我们使用了 thresh=3.5 modified_z_score = 0.6745 * abs_dev / y_mad

1
如果你需要一个列表而不是numpy数组,numpy数组提供了一个方便的tolist函数:out_liers.tolist()。你其他的问题最好由代码的原作者回答。 - entropy
2个回答

3

这个有效:

def outliers_modified_z_score(ys, threshold=3.5):
    ys_arr = np.array(ys)
    median_y = np.median(ys_arr)
    median_absolute_deviation_y = np.median(np.abs(ys_arr - median_y))
    modified_z_scores = 0.6745 * (ys_arr - median_y) / median_absolute_deviation_y
    return (ys_arr[np.abs(modified_z_scores) > threshold]).tolist()

非常感谢!另外,您能解释一下3.5和0.6745的值吗? - Rahul Sharma
1
0.6745是因为对于正态分布变量,E[MAD] = 0.6745 * sigma。尝试:x = np.random.normal(size=100000000) 然后 print(np.median(np.abs(x - np.median(x))).mean() / x.std())3.5也是由Iglewicz和Hoaglin(异常值检测的创建者)经验性地发现的。参见:https://hwbdocuments.env.nm.gov/Los%20Alamos%20National%20Labs/TA%2054/11587.pdf - J. Kwon

1
那是因为您正在使用numpy函数。默认使用的类型是numpy.ndarray,这可以加快计算速度。如果您只需要一个列表作为输出参数,请使用tolist()方法。
z = outliers(bids)
bidd = np.array(bids)
out_liers = bidd[z].tolist()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接