다음과 같은 작업을 수행하는 numpy 내장이 있습니까? 즉, 목록을 가져 와서 에서 점의 일부 가정 분포를 기반으로 제거 된 외부 요소 가있는 목록 d
을 반환합니다 .filtered_d
d
import numpy as np
def reject_outliers(data):
m = 2
u = np.mean(data)
s = np.std(data)
filtered = [e for e in data if (u - 2 * s < e < u + 2 * s)]
return filtered
>>> d = [2,4,5,1,6,5,40]
>>> filtered_d = reject_outliers(d)
>>> print filtered_d
[2,4,5,1,6,5]
함수가 다양한 분포 (포아송, 가우시안 등)와 해당 분포 내에서 다양한 이상치 임계 값 ( m
여기에서 사용한 것과 같은)을 허용 할 수 있기 때문에 ‘같은 것’이라고 말합니다 .
답변
이 방법은 당신의 방법과 거의 동일하며 더 numpyst입니다 (또한 numpy 배열에서만 작동합니다).
def reject_outliers(data, m=2):
return data[abs(data - np.mean(data)) < m * np.std(data)]
답변
특이 치를 다룰 때 중요한 것은 추정치를 가능한 한 강력하게 사용해야한다는 것입니다. 분포의 평균은 특이 치에 의해 편향되지만 예를 들어 중앙값은 훨씬 적습니다.
eumiro의 대답을 바탕으로 :
def reject_outliers(data, m = 2.):
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d/mdev if mdev else 0.
return data[s<m]
여기서는 평균을 더 강력한 중앙값으로, 표준 편차를 중앙값까지의 중앙값 절대 거리로 대체했습니다. 그런 다음 (다시) 중앙값으로 거리를 조정하여 m
합리적인 상대적인 척도를 유지했습니다.
에 대한 참고 data[s<m]
작업에 대한 구문, data
NumPy와 배열해야합니다.
답변
Benjamin Bannier의 답변은 중앙값으로부터의 거리 중앙값이 0 일 때 통과를 산출하므로 아래 예제와 같이이 수정 된 버전이 경우에 더 유용하다는 것을 알았습니다.
def reject_outliers_2(data, m=2.):
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d / (mdev if mdev else 1.)
return data[s < m]
예:
data_points = np.array([10, 10, 10, 17, 10, 10])
print(reject_outliers(data_points))
print(reject_outliers_2(data_points))
제공 :
[[10, 10, 10, 17, 10, 10]] # 17 is not filtered
[10, 10, 10, 10, 10] # 17 is filtered (it's distance, 7, is greater than m)
답변
Benjamin에서 빌드 하고을 사용 pandas.Series
하고 MAD를 IQR로 대체 :
def reject_outliers(sr, iq_range=0.5):
pcnt = (1 - iq_range) / 2
qlow, median, qhigh = sr.dropna().quantile([pcnt, 0.50, 1-pcnt])
iqr = qhigh - qlow
return sr[ (sr - median).abs() <= iqr]
예를 들어를 설정 iq_range=0.6
하면 사 분위수 범위의 백분위 수는 다음이 0.20 <--> 0.80
되므로 더 많은 특이 치가 포함됩니다.
답변
대안은 표준 편차를 강력하게 추정하는 것입니다 (가우스 통계 가정). 온라인 계산기를 보면 90 % 백분위 수는 1.2815σ에 해당하고 95 %는 1.645σ입니다 ( http://vassarstats.net/tabs.html?#z ).
간단한 예로서 :
import numpy as np
# Create some random numbers
x = np.random.normal(5, 2, 1000)
# Calculate the statistics
print("Mean= ", np.mean(x))
print("Median= ", np.median(x))
print("Max/Min=", x.max(), " ", x.min())
print("StdDev=", np.std(x))
print("90th Percentile", np.percentile(x, 90))
# Add a few large points
x[10] += 1000
x[20] += 2000
x[30] += 1500
# Recalculate the statistics
print()
print("Mean= ", np.mean(x))
print("Median= ", np.median(x))
print("Max/Min=", x.max(), " ", x.min())
print("StdDev=", np.std(x))
print("90th Percentile", np.percentile(x, 90))
# Measure the percentile intervals and then estimate Standard Deviation of the distribution, both from median to the 90th percentile and from the 10th to 90th percentile
p90 = np.percentile(x, 90)
p10 = np.percentile(x, 10)
p50 = np.median(x)
# p50 to p90 is 1.2815 sigma
rSig = (p90-p50)/1.2815
print("Robust Sigma=", rSig)
rSig = (p90-p10)/(2*1.2815)
print("Robust Sigma=", rSig)
내가 얻는 출력은 다음과 같습니다.
Mean= 4.99760520022
Median= 4.95395274981
Max/Min= 11.1226494654 -2.15388472011
Sigma= 1.976629928
90th Percentile 7.52065379649
Mean= 9.64760520022
Median= 4.95667658782
Max/Min= 2205.43861943 -2.15388472011
Sigma= 88.6263902244
90th Percentile 7.60646688694
Robust Sigma= 2.06772555531
Robust Sigma= 1.99878292462
예상 값 2에 가깝습니다.
5 표준 편차 위 / 아래 점을 제거하려는 경우 (1000 점으로 1 값> 3 표준 편차 예상) :
y = x[abs(x - p50) < rSig*5]
# Print the statistics again
print("Mean= ", np.mean(y))
print("Median= ", np.median(y))
print("Max/Min=", y.max(), " ", y.min())
print("StdDev=", np.std(y))
다음을 제공합니다.
Mean= 4.99755359935
Median= 4.95213030447
Max/Min= 11.1226494654 -2.15388472011
StdDev= 1.97692712883
어떤 접근 방식이 더 효율적이고 강력한 지 모르겠습니다.
답변
이 답변에는 “z 점수”에 기반한 솔루션과 “IQR”에 기반한 솔루션의 두 가지 방법을 제공하고 싶습니다.
이 답변에 제공된 코드는 단일 dim numpy
배열과 다중numpy
배열 .
먼저 일부 모듈을 가져 오겠습니다.
import collections
import numpy as np
import scipy.stats as stat
from scipy.stats import iqr
z 점수 기반 방법
이 방법은 숫자가 세 표준 편차를 벗어나는지 테스트합니다. 이 규칙에 따라 값이 이상 값이면 메서드는 true를 반환하고 그렇지 않으면 false를 반환합니다.
def sd_outlier(x, axis = None, bar = 3, side = 'both'):
assert side in ['gt', 'lt', 'both'], 'Side should be `gt`, `lt` or `both`.'
d_z = stat.zscore(x, axis = axis)
if side == 'gt':
return d_z > bar
elif side == 'lt':
return d_z < -bar
elif side == 'both':
return np.abs(d_z) > bar
IQR 기반 방법
이 방법은 값이 SPSS의 플롯 방법과 유사한 q1 - 1.5 * iqr
보다 작 거나 큰지 테스트합니다 q3 + 1.5 * iqr
.
def q1(x, axis = None):
return np.percentile(x, 25, axis = axis)
def q3(x, axis = None):
return np.percentile(x, 75, axis = axis)
def iqr_outlier(x, axis = None, bar = 1.5, side = 'both'):
assert side in ['gt', 'lt', 'both'], 'Side should be `gt`, `lt` or `both`.'
d_iqr = iqr(x, axis = axis)
d_q1 = q1(x, axis = axis)
d_q3 = q3(x, axis = axis)
iqr_distance = np.multiply(d_iqr, bar)
stat_shape = list(x.shape)
if isinstance(axis, collections.Iterable):
for single_axis in axis:
stat_shape[single_axis] = 1
else:
stat_shape[axis] = 1
if side in ['gt', 'both']:
upper_range = d_q3 + iqr_distance
upper_outlier = np.greater(x - upper_range.reshape(stat_shape), 0)
if side in ['lt', 'both']:
lower_range = d_q1 - iqr_distance
lower_outlier = np.less(x - lower_range.reshape(stat_shape), 0)
if side == 'gt':
return upper_outlier
if side == 'lt':
return lower_outlier
if side == 'both':
return np.logical_or(upper_outlier, lower_outlier)
마지막으로 이상 값을 필터링하려면 numpy
선택기를 사용하십시오 .
좋은 하루 되세요.
답변
큰 이상 값으로 인해 표준 편차가 매우 커지면 위의 모든 방법이 실패한다는 것을 고려하십시오.
( 평균 계산이 실패하고 오히려 중앙값을 계산해야하는 것과 유사합니다. 그러나 평균은 “stdDv와 같은 오류가 더 발생하기 쉽습니다”. )
알고리즘을 반복적으로 적용하거나 사 분위수 범위를 사용하여 필터링 할 수 있습니다. (여기서 “인수”는 * 시그마 범위와 관련이 있지만 데이터가 가우시안 분포를 따르는 경우에만 해당)
import numpy as np
def sortoutOutliers(dataIn,factor):
quant3, quant1 = np.percentile(dataIn, [75 ,25])
iqr = quant3 - quant1
iqrSigma = iqr/1.34896
medData = np.median(dataIn)
dataOut = [ x for x in dataIn if ( (x > medData - factor* iqrSigma) and (x < medData + factor* iqrSigma) ) ]
return(dataOut)