下面的代码找到离平均值最远的点,将其删除,然后再次检查平均值。如果移除该点导致平均值小于给定的容差(通过对旧平均值的百分比变化),则移动被拒绝并返回旧列表。否则,新列表将保留,并且过程继续。
t = [{'a': 22, 'b': 59, 'k': 1},
{'a': 21, 'b': 34, 'k': 2},
{'a': 991, 'b': 29, 'k': 3},
{'a': 45, 'b': 11, 'k': 4},
{'a': 211, 'b': 77, 'k': 5},
{'a': 100, 'b': 1024, 'k': 6}]
K = [te['k'] for te in t]
A = [te['a'] for te in t]
B = [te['b'] for te in t]
data = zip(K,A,B)
def mean(A):
return sum(A)/float(len(A))
def max_deviation(A):
mu = mean(A)
dev = [(a, abs(a-mu)) for a in A]
dev.sort(key=lambda k: k[1], reverse=True)
return dev[0][0]
def remove_outliers(A, tol=.3):
mu = mean(A)
A_prime = list(a for a in A if a != max_deviation(A))
mu_prime = mean(A_prime)
if abs(mu_prime - mu)/float(mu) > tol:
return remove_outliers(A_prime, tol)
else:
return A
t_prime = [dict(k=k, a=a, b=b) for k, a, b in data
if a in remove_outliers(A) and b in remove_outliers(B)]
>>> print t_prime
[{'a': 22, 'b': 59, 'k': 1},
{'a': 21, 'b': 34, 'k': 2},
{'a': 45, 'b': 11, 'k': 4}]
编辑:因为它是去除一个值,而不是创建N-1的值的这可能比例更好。这将修改原始的A
矢量。如果你不想这样做,那么第一个选项将是你的最佳选择,或者先发送一份副本。
def remove_outliers(A, tol=.3):
mu = mean(A)
out = max_deviation(A)
A.remove(out)
mu_prime = mean(A)
if abs(mu_prime - mu)/float(mu) > tol:
return remove_outliers(A, tol)
else:
A.append(out)
return A
您必须指定“有意义”是什么。一般来说,所有的数字都是有意义的,除非证明相反 – mgkrebbs
也许你可以定义“方式太大或太小”...... – roippi
一个有意义的值可以是我认为大部分值都以它为中心的东西。一种识别方法是采用列表的平均值,但问题是这是一个2d列表,其中a和b彼此不相关并且是独立变量。并且,在我猜测的同一帧中可以采用太大或太小的方式:就像所有的滤波值不应该偏离那个有意义的值。我猜在这种情况下,它将是一个(n,m )矢量? – user2480542