2012-08-09 17 views
10

Sto tracciando alcuni dati da vari test. A volte in un test mi capita di avere un outlier (diciamo 0.1), mentre tutti gli altri valori sono di tre ordini di grandezza più piccoli.matplotlib: ignorare i valori anomali durante la stampa

Con matplotlib, ho tramare contro il campo [0, max_data_value]

Come posso solo zoom in miei dati e non mostrare i valori anomali, che sarebbe rovinare l'asse x nella mia trama?

Devo semplicemente prendere il 95 percentile e avere l'intervallo [0, 95_percentile] sull'asse x?

+0

Che tipo di trama? Scatter? Istogramma? –

+0

Sto complottando con gli istogrammi. –

risposta

36

Non esiste un singolo test "migliore" per un outlier. Idealmente, dovresti inserire informazioni a priori (ad es. "Questo parametro non dovrebbe essere superato x a causa di blah ...").

La maggior parte dei test per valori anomali utilizza la deviazione assoluta mediana, anziché il 95 ° percentile o qualche altra misurazione basata sulla varianza. Altrimenti, la varianza/stddev calcolata sarà fortemente distorta dai valori anomali.

Ecco una funzione che implementa uno dei test più comuni degli outlier.

def is_outlier(points, thresh=3.5): 
    """ 
    Returns a boolean array with True if points are outliers and False 
    otherwise. 

    Parameters: 
    ----------- 
     points : An numobservations by numdimensions array of observations 
     thresh : The modified z-score to use as a threshold. Observations with 
      a modified z-score (based on the median absolute deviation) greater 
      than this value will be classified as outliers. 

    Returns: 
    -------- 
     mask : A numobservations-length boolean array. 

    References: 
    ---------- 
     Boris Iglewicz and David Hoaglin (1993), "Volume 16: How to Detect and 
     Handle Outliers", The ASQC Basic References in Quality Control: 
     Statistical Techniques, Edward F. Mykytka, Ph.D., Editor. 
    """ 
    if len(points.shape) == 1: 
     points = points[:,None] 
    median = np.median(points, axis=0) 
    diff = np.sum((points - median)**2, axis=-1) 
    diff = np.sqrt(diff) 
    med_abs_deviation = np.median(diff) 

    modified_z_score = 0.6745 * diff/med_abs_deviation 

    return modified_z_score > thresh 

Come esempio di utilizzo, si farebbe qualcosa di simile al seguente:

import numpy as np 
import matplotlib.pyplot as plt 

# The function above... In my case it's in a local utilities module 
from sci_utilities import is_outlier 

# Generate some data 
x = np.random.random(100) 

# Append a few "bad" points 
x = np.r_[x, -3, -10, 100] 

# Keep only the "good" points 
# "~" operates as a logical not operator on boolean numpy arrays 
filtered = x[~is_outlier(x)] 

# Plot the results 
fig, (ax1, ax2) = plt.subplots(nrows=2) 

ax1.hist(x) 
ax1.set_title('Original') 

ax2.hist(filtered) 
ax2.set_title('Without Outliers') 

plt.show() 

enter image description here

+0

Questa è un'ottima risposta (+1 da me), ma penso che '~' sia un bit non, non un logico no - non sembra importante qui per ragioni di cui non sono al 100% chiaro, ma in altri posti sarebbe . '~ False! = True', ma' not False == True' –

+1

Buon punto! In numpy, è sovraccarico per funzionare come logico non su array booleani (ad esempio '~ np.array (False) == True'), ma questo non è il caso di qualsiasi altra cosa. Dovrei chiarirlo. (Su una nota a margine, per convenzione 'not some_array' solleverà un errore di valore se' some_array' ha più di un elemento.Quindi la necessità di '~' nell'esempio sopra.) –

+0

Grazie per la risposta - ho effettivamente provato ' non "e ho ottenuto l'errore che prevedi, quindi ero ancora più sconcertato ... –

7

Se non siete dedicati circa rifiutando valori anomali come detto da Joe e Per motivi puramente estetici, è possibile impostare i limiti dell'asse x della trama:

plt.xlim(min_x_data_value,max_x_data_value) 

Dove i valori rappresentano i limiti desiderati da visualizzare.

plt.ylim(min,max) funziona anche per impostare i limiti sull'asse y.

+1

Per un istogramma, tuttavia, l'OP dovrebbe anche ricalcolare i raccoglitori. Matplotlib usa bordi del cestino fissi. Non "rebin" quando si ingrandisce. –

Problemi correlati