Me gustaría proporcionar dos métodos en esta respuesta, una solución basada en la "puntuación z" y una solución basada en "IQR".
El código proporcionado en esta respuesta funciona tanto en una numpymatriz de atenuación única como en una matriz múltiple numpy.
Primero importemos algunos módulos.
import collections
import numpy as np
import scipy.stats as stat
from scipy.stats import iqr
método basado en puntuación z
Este método probará si el número cae fuera de las tres desviaciones estándar. Según esta regla, si el valor es atípico, el método devolverá verdadero, si no, devolverá 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 basado en IQR
Este método probará si el valor es menor q1 - 1.5 * iqro mayor que q3 + 1.5 * iqr, que es similar al método de trazado de 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)
Por último, si desea filtrar los valores atípicos, use un numpyselector.
Que tengas un buen día.