Hola chicos, esta pregunta podría ser más sobre lógica que sobre código, espero que alguien pueda aclararla.
Por lo tanto, tengo una lista de datos que contiene algunos valores atípicos, y quiero eliminarla usando la diferencia entre cada elemento de la lista e identificando dónde la diferencia es demasiado grande.
De este ejemplo, quiero eliminar de la lista de datos los índices [2,3,4]. ¿Cuál es la mejor manera de hacerlo?
Intenté usar el método np.argwhere () para encontrar los índices, sin embargo, estoy atascado en cómo usar el resultado para cortar un np.array ??

data=[4.0, 4.5, 22.5, 40.5, 22.5, 3.5, 3.0, 3.5, 4.5, 3.5, 2.5]
data=np.array(data)
d = data[:-1] - data[1:]
print(np.mean(d)) 

En este ejemplo, cuando imprimo la diferencia (d) me devuelve esto:

print(d) # returns:[ -0.5 -18.  -18.   18.   19.    0.5  -0.5  -1.    1.    1. ]

Eso es bueno. Ahora, la lógica que apliqué era indicar dónde en d tenemos un número más alto que el promedio de los datos originales.

x = np.argwhere(d>np.mean(data))
print(x)        # returns: array([3], dtype=int64), array([4], dtype=int64)
indices_to_extract = [x[0]-1,x[-1]]
print(indices_to_extract)      # returns: [array([2], dtype=int64), array([[4]], dtype=int64)]
a1 = np.delete(r,indices_to_extract,axis=0)
print(a1)       #returns: [ 4.   4.5 40.5  3.5  3.   3.5  4.5  3.5  2.5]


 #Desirable return:
[ 4.   4.5 3.5  3.  3.5  4.5  3.5  2.5]

La pregunta principal es, ¿cómo hacer el resultado del rango de números np.argwhere () que se puede usar para cortar?

1
Angel Lira 23 jun. 2020 a las 12:39

3 respuestas

La mejor respuesta

El problema con tomar la diferencia entre los elementos de la lista es que, por ejemplo, el valor con el índice 1 (4.5) se considerará atípico (obtiene un valor alto con la diferencia). También puede obtener valores positivos y negativos al tomar la diferencia, por lo que si desea hacerlo de esa manera, debe aplicar el módulo (abs) en el resultado de la diferencia.

Una forma de detectar valores atípicos es la siguiente:

Calcule la puntuación z:

d = (data - np.mean(data)) / np.std(data)

Seleccione todos los valores de los datos, excepto los valores atípicos (por encima del cuantil del 75%):

data[np.where( ~(d > np.quantile(d, 0.75)))]

Salida:

array([4. , 4.5, 3.5, 3. , 3.5, 4.5, 3.5, 2.5])
1
DavideBrex 23 jun. 2020 a las 09:59

Aconsejaría usar distancias normalizadas a la mediana, que es más robusta:

d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d / (mdev if mdev else 1.)
print(data[s < 4])

Puede cambiar el umbral (aquí 4 en la última línea) a la precisión deseada.

Salida:

[4.  4.5 3.5 3.  3.5 4.5 3.5 2.5]
1
Ehsan 23 jun. 2020 a las 11:08

Para usar np.argwhere() para un rango de números, diga [3,20] en su caso, use:

x = np.argwhere((data<20) & (data>3))

Para devolver una matriz menor / mayor que un número (digamos datos por debajo de 20) simplemente puede usar:

data[np.where(data<20)]

Y para un rango de números diga [3,20]:

data[np.where((data<20)&(data>3))]
0
ipinak 23 jun. 2020 a las 15:04