ponderada para graficas frecuencia estandar estadisticas entre desviacion cuadrado correlacion comando chi calcular acumulada python numpy

para - graficas estadisticas python



¿Existe un numpy incorporado para rechazar valores atípicos de una lista (6)

¿Hay 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 según 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í'' porque la función podría permitir distribuciones variables (poisson, gaussianas, etc.) y umbrales de valores atípicos variables dentro de esas distribuciones (como el m que he usado aquí).


Algo importante cuando se trata de valores atípicos es que uno debe tratar de usar estimadores tan robustos como sea 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:

def reject_outliers(data, m = 2.): d = np.abs(data - np.median(data)) mdev = np.median(d) s = d/mdev if mdev else 0. return data[s<m]

Aquí he reemplazado la media con la mediana más robusta y la desviación estándar con la distancia absoluta a la mediana. Luego escale las distancias por su valor mediano (de nuevo) para que m esté en una escala relativa razonable.


Basándose en Benjamin''s, utilizando pandas.Series , y reemplazando MAD con 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]

Por ejemplo, si establece iq_range=0.6 , los percentiles del rango intercuartílico se convertirán en: 0.20 <--> 0.80 , por lo que se incluirán más valores atípicos.


Este método es casi idéntico al tuyo, simplemente más numpyst (también funciona en matrices numpy solamente):

def reject_outliers(data, m=2): return data[abs(data - np.mean(data)) < m * np.std(data)]


La respuesta de Benjamin Bannier produce un traspaso cuando la mediana de las distancias desde la mediana es 0, por lo que esta versión modificada me resultó un poco más útil para los casos, como se muestra en el siguiente ejemplo.

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]

Ejemplo:

data_points = np.array([10, 10, 10, 17, 10, 10]) print(reject_outliers(data_points)) print(reject_outliers_2(data_points))

Da:

[[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)


Quería hacer algo similar, excepto establecer el número en NaN en lugar de eliminarlo de los datos, ya que si lo quita, cambia la longitud que puede arruinar 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 que pueda trazarlas una contra la otra).

Para hacerlo, utilicé las funciones de enmascaramiento de 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


Una alternativa es hacer una estimación robusta de la desviación estándar (suponiendo que las 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:

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)

El resultado que obtengo es:

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

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):

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))

Lo que da:

Mean= 4.99755359935 Median= 4.95213030447 Max/Min= 11.1226494654 -2.15388472011 StdDev= 1.97692712883

No tengo idea de qué enfoque es el más eficiente / robusto