¿Existe un numpy incorporado para hacer algo como lo siguiente? Es decir, tome una lista d
y devuelva una lista filtered_d
con los elementos periféricos eliminados en función de una distribución supuesta de los puntos en 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]
Digo 'algo así como' porque la función podría permitir distribuciones variables (poisson, gaussian, etc.) y umbrales de valores atípicos variables dentro de esas distribuciones (como la m
que he usado aquí).
Respuestas:
Este método es casi idéntico al suyo, solo que más numpyst (también funciona solo en matrices numpy):
fuente
m
es lo suficientemente grande (por ejemplom=6
), pero para valores pequeños dem
este sufre de la media la varianza no es estimadores robustos.Algo importante cuando se trata de valores atípicos es que se debe intentar utilizar estimadores lo más robustos posible. La media de una distribución estará sesgada por valores atípicos pero, por ejemplo, la mediana será mucho menor.
Basándose en la respuesta de Eumiro:
Aquí he reemplazado la media con la mediana más robusta y la desviación estándar con la mediana de la distancia absoluta a la mediana. Luego escalé las distancias por su (nuevamente) valor mediano para que
m
esté en una escala relativa razonable.Tenga en cuenta que para que la
data[s<m]
sintaxis funcione,data
debe ser una matriz numpy.fuente
3.5 / .6745 ~= 5.189
(multiplicans
por .6745 y especifican unam
de 3.5 ... también tomanabs(s)
). ¿Alguien puede explicar la elección de m? ¿O es algo que identificará a partir de su conjunto de datos en particular?m
lugar de declaraciones esponjosas como "interacción de pureza y eficiencia"?TypeError: only integer scalar arrays can be converted to a scalar index
La respuesta de Benjamin Bannier produce un traspaso cuando la mediana de las distancias desde la mediana es 0, por lo que encontré esta versión modificada un poco más útil para los casos que se muestran en el siguiente ejemplo.
Ejemplo:
Da:
fuente
Sobre la base de Benjamin, usando
pandas.Series
y reemplazando MAD con IQR :Por ejemplo, si establece
iq_range=0.6
, los percentiles del rango intercuartílico se convertirían en:,0.20 <--> 0.80
por lo que se incluirán más valores atípicos.fuente
Una alternativa es hacer una estimación robusta de la desviación estándar (asumiendo estadísticas gaussianas). Buscando calculadoras en línea, veo que el percentil del 90% corresponde a 1.2815σ y el 95% es 1.645σ ( http://vassarstats.net/tabs.html?#z )
Como un simple ejemplo:
La salida que obtengo es:
Que está cerca del valor esperado de 2.
Si queremos eliminar puntos por encima / por debajo de 5 desviaciones estándar (con 1000 puntos esperaríamos 1 valor> 3 desviaciones estándar):
Lo que da:
No tengo idea de qué enfoque es el más eficiente / robusto
fuente
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
numpy
matriz de atenuación única como en una matriz múltiplenumpy
.Primero importemos algunos módulos.
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.
Método basado en IQR
Este método probará si el valor es menor
q1 - 1.5 * iqr
o mayor queq3 + 1.5 * iqr
, que es similar al método de trazado de SPSS.Por último, si desea filtrar los valores atípicos, use un
numpy
selector.Que tengas un buen día.
fuente
Tenga en cuenta que todos los métodos anteriores fallan cuando su desviación estándar se vuelve muy grande debido a grandes valores atípicos.
( Simalar como el cálculo promedio falla y debería calcular la mediana. Sin embargo, el promedio es "más propenso a errores como el stdDv". )
Puede intentar aplicar iterativamente su algoritmo o filtrar usando el rango intercuartílico: (aquí, "factor" se relaciona con un rango * sigma, pero solo cuando sus datos siguen una distribución gaussiana)
fuente
Quería hacer algo similar, excepto establecer el número en NaN en lugar de eliminarlo de los datos, ya que si lo elimina, cambia la longitud, lo que puede estropear el trazado (es decir, si solo está eliminando valores atípicos de una columna en una tabla , pero necesita que permanezca igual que las otras columnas para poder trazarlas entre sí).
Para hacerlo, utilicé las funciones de enmascaramiento de numpy :
fuente
si desea obtener la posición del índice de los valores atípicos
idx_list
, la devolverá.fuente
Para un conjunto de imágenes (cada imagen tiene 3 dimensiones), donde quería rechazar valores atípicos para cada píxel que usé:
Entonces es posible calcular la media:
(Lo uso para la resta de fondo)
fuente