Eu gostaria de fornecer dois métodos nesta resposta, solução baseada em "pontuação z" e solução baseada em "IQR".
O código fornecido nesta resposta funciona tanto em numpymatriz dim única quanto em matriz múltipla numpy.
Vamos importar alguns módulos primeiro.
import collections
import numpy as np
import scipy.stats as stat
from scipy.stats import iqr
método baseado em pontuação z
Este método testará se o número está fora dos três desvios padrão. Com base nesta regra, se o valor for outlier, o método retornará verdadeiro, caso contrário, retornará falso.
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
Método baseado em IQR
Este método testará se o valor é menor q1 - 1.5 * iqrou maior que q3 + 1.5 * iqr, que é semelhante ao método de plotagem do 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)
Finalmente, se você quiser filtrar os outliers, use um numpyseletor.
Tenha um bom dia.