La domanda chiede di modi per utilizzare vicini più prossimi in un robusto modo per identificare e valori anomali localizzati corretti. Perché non fare esattamente questo?
La procedura consiste nel calcolare un solido smooth locale, valutare i residui e azzerare quelli troppo grandi. Questo soddisfa tutti i requisiti direttamente ed è abbastanza flessibile da adattarsi alle diverse applicazioni, perché si possono variare le dimensioni del vicinato locale e la soglia per identificare i valori anomali.
(Perché la flessibilità è così importante? Perché una tale procedura ha buone probabilità di identificare alcuni comportamenti localizzati come "periferici". In quanto tali, tutte queste procedure possono essere considerate più fluide . Elimineranno alcuni dettagli insieme agli apparenti valori anomali. L'analista ha bisogno di un certo controllo sul compromesso tra la conservazione dei dettagli e il mancato rilevamento di valori anomali locali.)
Un altro vantaggio di questa procedura è che non richiede una matrice rettangolare di valori. In effetti, può anche essere applicato a dati irregolari utilizzando un dispositivo più fluido locale adatto a tali dati.
R
, così come la maggior parte dei pacchetti di statistiche con funzionalità complete, ha integrato diversi strumenti di smoothing locali come loess
. L'esempio seguente è stato elaborato utilizzandolo. La matrice ha righe e 49 colonne - quasi 4000 voci. Rappresenta una funzione complicata con diversi estremi locali e un'intera linea di punti in cui non è differenziabile (una "piega"). A poco più del 5 % dei punti - una percentuale molto elevata da considerare "periferico" - sono stati aggiunti errori gaussiani cui deviazione standard è di solo 1 / 20 della deviazione standard dei dati originali. Questo set di dati sintetici presenta quindi molte delle caratteristiche impegnative di dati realistici.794940005%1/20
Si noti che (come da R
convenzioni) le righe della matrice vengono disegnate come strisce verticali. Tutte le immagini, ad eccezione dei residui, hanno l'ombra delle colline per aiutare a visualizzare piccole variazioni nei loro valori. Senza questo, quasi tutti i valori anomali locali sarebbero invisibili!
(0,79)(49,30)
Le macchioline nel diagramma "Residui" mostrano gli evidenti valori anomali locali isolati. Questo grafico mostra anche altre strutture (come quella striscia diagonale) attribuibili ai dati sottostanti. Si potrebbe migliorare questa procedura usando un modello spaziale dei dati ( tramite metodi geostatistici), ma descriverlo e illustrarlo ci porterebbe troppo lontano qui.
1022003600
#
# Create data.
#
set.seed(17)
rows <- 2:80; cols <- 2:50
y <- outer(rows, cols,
function(x,y) 100 * exp((abs(x-y)/50)^(0.9)) * sin(x/10) * cos(y/20))
y.real <- y
#
# Contaminate with iid noise.
#
n.out <- 200
cat(round(100 * n.out / (length(rows)*length(cols)), 2), "% errors\n", sep="")
i.out <- sample.int(length(rows)*length(cols), n.out)
y[i.out] <- y[i.out] + rnorm(n.out, sd=0.05 * sd(y))
#
# Process the data into a data frame for loess.
#
d <- expand.grid(i=1:length(rows), j=1:length(cols))
d$y <- as.vector(y)
#
# Compute the robust local smooth.
# (Adjusting `span` changes the neighborhood size.)
#
fit <- with(d, loess(y ~ i + j, span=min(1/2, 125/(length(rows)*length(cols)))))
#
# Display what happened.
#
require(raster)
show <- function(y, nrows, ncols, hillshade=TRUE, ...) {
x <- raster(y, xmn=0, xmx=ncols, ymn=0, ymx=nrows)
crs(x) <- "+proj=lcc +ellps=WGS84"
if (hillshade) {
slope <- terrain(x, opt='slope')
aspect <- terrain(x, opt='aspect')
hill <- hillShade(slope, aspect, 10, 60)
plot(hill, col=grey(0:100/100), legend=FALSE, ...)
alpha <- 0.5; add <- TRUE
} else {
alpha <- 1; add <- FALSE
}
plot(x, col=rainbow(127, alpha=alpha), add=add, ...)
}
par(mfrow=c(1,4))
show(y, length(rows), length(cols), main="Data")
y.res <- matrix(residuals(fit), nrow=length(rows))
show(y.res, length(rows), length(cols), hillshade=FALSE, main="Residuals")
#hist(y.res, main="Histogram of Residuals", ylab="", xlab="Value")
# Increase the `8` to find fewer local outliers; decrease it to find more.
sigma <- 8 * diff(quantile(y.res, c(1/4, 3/4)))
mu <- median(y.res)
outlier <- abs(y.res - mu) > sigma
cat(sum(outlier), "outliers found.\n")
# Fix up the data (impute the values at the outlying locations).
y.imp <- matrix(predict(fit), nrow=length(rows))
y.imp[outlier] <- y[outlier] - y.res[outlier]
show(y.imp, length(rows), length(cols), main="Imputed")
show(y.real, length(rows), length(cols), main="Real")