리스트에서 특이치를 기각하기 위한 numpy가 내장되어 있습니까?
다음과 같은 일을 할 수 있는 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
여기서 사용했습니다.).
특이치를 다룰 때 중요한 것은 가능한 한 강력한 추정기를 사용해야 한다는 것입니다.분포의 평균은 특이치에 의해 편향되지만 중위수와 같은 경우에는 훨씬 더 작습니다.
eumiro의 답변을 작성합니다.
def reject_outliers(data, m = 2.):
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d/mdev if mdev else np.zeros(len(d))
return data[s<m]
여기에서는 평균을 보다 견고한 중위수로 바꾸고 표준 편차를 중위수에 대한 절대 거리를 중위수로 바꿉니다.그런 다음 (다시) 중앙값으로 거리를 조정하여 다음과 같이 했습니다.m
적절한 상대적 규모입니다.
로 참고: 경우의data[s<m]
, 작업구문,data
numpy 배열이어야 합니다.
이 방법은 귀하의 방법과 거의 동일하며 더 많은 numpyst(numpy 어레이에서만 작동):
def reject_outliers(data, m=2):
return data[abs(data - np.mean(data)) < m * np.std(data)]
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.2815ppm, 95%는 1.645ppm(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
어떤 접근 방식이 더 효율적인지/강력한지 모르겠습니다.
데이터에서 숫자를 제거하는 대신 NaN으로 설정하는 것을 제외하고는 유사한 작업을 수행하고 싶었습니다. 데이터를 제거하면 표시가 엉망이 될 수 있는 길이를 변경할 수 있습니다(예: 테이블의 한 열에서만 특이치를 제거하지만 서로에 대해 플롯할 수 있도록 다른 열과 동일하게 유지해야 함).).
이를 위해 Numpy의 마스킹 기능을 사용했습니다.
def reject_outliers(data, m=2):
stdev = np.std(data)
mean = np.mean(data)
maskMin = mean - stdev * m
maskMax = mean + stdev * m
mask = np.ma.masked_outside(data, maskMin, maskMax)
print('Masking values outside of {} and {}'.format(maskMin, maskMax))
return mask
저는 이 답변에서 "z score"에 기반한 솔루션과 "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 기반 방법
이 방법은 값이 다음보다 작은지 테스트합니다.q1 - 1.5 * iqr
또는 그 이상q3 + 1.5 * iqr
SPSS의 플롯 방법과 유사합니다.
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
선택자
좋은 하루 되세요.
큰 특이치로 인해 표준 편차가 매우 커지면 위의 모든 방법이 실패한다고 가정합니다.
평균 계산이 실패하는 것과 비슷하므로 오히려 중위수를 계산해야 합니다. 그러나 평균은 "표준 Dv와 같은 오류에 더 취약하다").
알고리즘을 반복적으로 적용하거나 사분위간 범위를 사용하여 필터링할 수 있습니다. (여기서 "인자"는 *시그마 범위와 관련이 있지만 데이터가 가우스 분포를 따르는 경우에만 해당)
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)
여기서 특이치를 찾습니다.x
포인트 창의 중위수로 대체합니다.win
) 주변에서 (벤자민 배니어로부터 중위수 편차에 답함)
def outlier_smoother(x, m=3, win=3, plots=False):
''' finds outliers in x, points > m*mdev(x) [mdev:median deviation]
and replaces them with the median of win points around them '''
x_corr = np.copy(x)
d = np.abs(x - np.median(x))
mdev = np.median(d)
idxs_outliers = np.nonzero(d > m*mdev)[0]
for i in idxs_outliers:
if i-win < 0:
x_corr[i] = np.median(np.append(x[0:i], x[i+1:i+win+1]))
elif i+win+1 > len(x):
x_corr[i] = np.median(np.append(x[i-win:i], x[i+1:len(x)]))
else:
x_corr[i] = np.median(np.append(x[i-win:i], x[i+1:i+win+1]))
if plots:
plt.figure('outlier_smoother', clear=True)
plt.plot(x, label='orig.', lw=5)
plt.plot(idxs_outliers, x[idxs_outliers], 'ro', label='outliers')
plt.plot(x_corr, '-o', label='corrected')
plt.legend()
return x_corr
너무 많은 답변들이 있지만, 저는 저자나 다른 사용자들에게도 유용할 수 있는 새로운 답변을 추가하고 있습니다.
Hampel 필터를 사용할 수 있습니다.하지만 당신은 당신과 함께 일해야 합니다.Series
.
Hampel 필터가 특이치 지수를 반환한 다음, 다음에서 삭제할 수 있습니다.Series
그런 다음 다시 변환합니다.List
.
Hampel 필터를 사용하기 위해 패키지를 쉽게 설치할 수 있습니다.pip
:
pip install hampel
용도:
# Imports
from hampel import hampel
import pandas as pd
list_d = [2, 4, 5, 1, 6, 5, 40]
# List to Series
time_series = pd.Series(list_d)
# Outlier detection with Hampel filter
# Returns the Outlier indices
outlier_indices = hampel(ts = time_series, window_size = 3)
# Drop Outliers indices from Series
filtered_d = time_series.drop(outlier_indices)
filtered_d.values.tolist()
print(f'filtered_d: {filtered_d.values.tolist()}')
출력은 다음과 같습니다.
filtered_d: [2, 4, 5, 1, 6, 5]
어디에,ts
판다입니다.Series
목적어와window_size
총 창 크기는 다음과 같이 계산됩니다.2 * window_size + 1
.
내가 설정한 이 시리즈에 대해window_size
가치가 있는3
.
Series를 사용하면 그래픽을 생성할 수 있다는 것이 멋진 점입니다.
# Imports
import matplotlib.pyplot as plt
plt.style.use('seaborn-darkgrid')
# Plot Original Series
time_series.plot(style = 'k-')
plt.title('Original Series')
plt.show()
# Plot Cleaned Series
filtered_d.plot(style = 'k-')
plt.title('Cleaned Series (Without detected Outliers)')
plt.show()
출력은 다음과 같습니다.
Hampel 필터에 대해 자세히 알아보려면 다음 판독값을 사용하는 것이 좋습니다.
idx_list
돌려줄 겁니다
def reject_outliers(data, m = 2.):
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d/mdev if mdev else 0.
data_range = np.arange(len(data))
idx_list = data_range[s>=m]
return data[s<m], idx_list
data_points = np.array([8, 10, 35, 17, 73, 77])
print(reject_outliers(data_points))
after rejection: [ 8 10 35 17], index positions of outliers: [4 5]
사용한 각 픽셀에 대한 특이치를 거부하려는 영상 세트(각 영상에 3차원이 있음)의 경우:
mean = np.mean(imgs, axis=0)
std = np.std(imgs, axis=0)
mask = np.greater(0.5 * std + 1, np.abs(imgs - mean))
masked = np.multiply(imgs, mask)
그런 다음 평균을 계산할 수 있습니다.
masked_mean = np.divide(np.sum(masked, axis=0), np.sum(mask, axis=0))
(백그라운드 감산에 사용)
Numpy 배열에서 축을 따라 특이치를 잘라내고 이 축을 따라 최소값 또는 최대값 중 가까운 값으로 바꿉니다.임계값은 z-점수입니다.
def np_z_trim(x, threshold=10, axis=0):
""" Replace outliers in numpy ndarray along axis with min or max values
within the threshold along this axis, whichever is closer."""
mean = np.mean(x, axis=axis, keepdims=True)
std = np.std(x, axis=axis, keepdims=True)
masked = np.where(np.abs(x - mean) < threshold * std, x, np.nan)
min = np.nanmin(masked, axis=axis, keepdims=True)
max = np.nanmax(masked, axis=axis, keepdims=True)
repl = np.where(np.abs(x - max) < np.abs(x - min), max, min)
return np.where(np.isnan(masked), repl, masked)
내 솔루션은 상한 및 하한 백분위수를 삭제하고 경계와 동일한 값을 유지합니다.
def remove_percentile_outliers(data, percent_to_drop=0.001):
low, high = data.quantile([percent_to_drop / 2, 1-percent_to_drop / 2])
return data[(data >= low )&(data <= high)]
내 솔루션은 특이치를 이전 값과 동일하게 합니다.
test_data = [2,4,5,1,6,5,40, 3]
def reject_outliers(data, m=2):
mean = np.mean(data)
std = np.std(data)
for i in range(len(data)) :
if np.abs(data[i] -mean) > m*std :
data[i] = data[i-1]
return data
reject_outliers(test_data)
출력:
[2, 4, 5, 1, 6, 5, 5, 3]
언급URL : https://stackoverflow.com/questions/11686720/is-there-a-numpy-builtin-to-reject-outliers-from-a-list
'programing' 카테고리의 다른 글
함수에 매개 변수로 전달하지 않고 Spring에서 현재 사용자 로케일을 가져오는 방법은 무엇입니까? (0) | 2023.07.29 |
---|---|
PHP의 UTF-8 문자열에서 4바이트 문자를 대체/제거하는 방법은 무엇입니까? (0) | 2023.07.29 |
Android에서 이미지 보기의 투명 배경 설정 (0) | 2023.07.29 |
수직 격자선을 matplotlib의 선 그림에 표시 (0) | 2023.07.29 |
jQuery 액세스 입력 숨김 값 (0) | 2023.07.29 |