この質問は、局所的な異常値を特定して修正するために、最近傍を堅牢な方法で使用する方法を求めています。どうしてそうしないのですか?
手順は、ロバストな局所平滑化を計算し、残差を評価し、大きすぎるものをゼロにすることです。これは、すべての要件を直接満たし、異なるアプリケーションに適応するのに十分な柔軟性があります。これは、局所的な近傍のサイズと外れ値を識別するためのしきい値を変更できるためです。
(なぜ柔軟性がそんなに重要なのでしょうか?そのような手順は、特定のローカライズされた動作を「外れた」ものとして識別する可能性が高いためです。そのため、そのような手順はすべてよりスムーズであると見なすことができます。詳細の保持とローカルの外れ値の検出の失敗とのトレードオフをある程度制御する必要があります。)
この手順のもう1つの利点は、値の長方形のマトリックスが必要ないことです。実際、このようなデータに適したローカルスムーザーを使用することで、不規則なデータにも適用できます。
R
、ほとんどのフル機能の統計パッケージと同様に、などの堅牢なローカルスムーザーがいくつか組み込まれていloess
ます。次の例は、それを使用して処理されました。マトリックスには、行と列(ほぼエントリ)があります。これは、いくつかの局所的な極値と、微分不可能な点の線(「折り目」)を持つ複雑な関数を表します。わずかに超えるにポイント-非常に高い割合が「範囲外」とみなされる-その標準偏差だけでガウス誤差を添加した1 / 20元のデータの標準偏差を。これにより、この合成データセットは、現実的なデータの困難な機能の多くを提示します。49 4000 5 %794940005 %1 / 20
(R
慣例により)行列の行は垂直のストリップとして描画されることに注意してください。残差を除くすべての画像は陰影付きで、値のわずかな変動を表示します。これがなければ、ほとんどすべてのローカルの外れ値が見えなくなります!
「実」(オリジナル汚染されていない)画像に「帰属」(アップ固定)を比較することで、外れ値を除去することから実行折り目(の一部、全部ではないが、滑らかたことは明らかであるダウン(49 、30 ) ;ライトシアンが「残差」プロット)でストライプを角度付けとしては明白です。(0 、79 )(49 、30 )
「残差」プロットの斑点は、明らかに孤立した局所的な外れ値を示しています。このプロットには、基礎となるデータに起因する他の構造(その斜めのストライプなど)も表示されます。データの空間モデルを使用することで(地球統計学的手法を介して)この手順を改善できますが、それを説明し、それを説明するには、ここから遠く離れた場所に行く必要があります。
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")