이 질문은 현지화 된 특이 치를 식별하고 수정 하기 위해 가장 가까운 이웃 을 강력 하게 사용하는 방법을 묻습니다 . 왜 그렇게하지 않습니까?
절차는 강력한 로컬 스무스를 계산하고 잔차를 평가하고 너무 큰 값을 제거하는 것입니다. 이 기능은 모든 요구 사항을 직접 충족 시키며 로컬 이웃의 크기와 특이 치를 식별하기위한 임계 값을 변경할 수 있으므로 다른 응용 프로그램에 맞게 조정할 수있을만큼 유연합니다.
(유연성이 중요한 이유는 무엇입니까? 그러한 절차는 특정 지역화 된 행동을 "외부적인"것으로 식별 할 가능성이 높기 때문에 그러한 절차는 모두 매끄럽게 간주 될 수 있습니다 . 세부 사항을 유지하는 것과 로컬 특이 치를 탐지하지 못하는 사이의 트레이드 오프를 약간 제어해야합니다.)
이 절차의 또 다른 장점은 사각형의 행렬 행렬이 필요하지 않다는 것입니다. 실제로 이러한 데이터에 적합한 로컬 스무스를 사용하여 불규칙 데이터 에도 적용 할 수 있습니다 .
R
, 및 모든 기능을 갖춘 통계 패키지뿐만 아니라와 같은 강력한 로컬 스무더가 내장되어 있습니다 loess
. 다음 예제는이를 사용하여 처리되었습니다. 이 행렬에는 개의 행과 개의 열 이 있으며 약 항목이 있습니다. 이것은 여러 개의 극한 극단뿐만 아니라 구별 할 수없는 전체 지점 ( "주름")을 갖는 복잡한 기능을 나타냅니다. "outlying"으로 간주되는 비율의 이상을 약간 초과 하여 표준 편차가 원본 데이터의 표준 편차의 에 불과한 가우시안 오차가 추가되었습니다 . 이 합성 데이터 세트는 실제 데이터의 여러 가지 까다로운 기능을 제공합니다.794940005 %1 / 20
(당 것을 유의 R
매트릭스 행은 수직 스트립으로서 그려 규칙). 잔차를 제외한 모든 이미지는 약간의 차이가있는 값을 표시하는 데 도움이됩니다. 이것이 없으면 거의 모든 지역 특이 치가 보이지 않을 것입니다!
"Imputed"(고정)와 "Real"(원래의 오염되지 않은) 이미지를 비교하여 이상치 (outlier)를 제거하면 에서 발생하는 주름의 일부가 전부는 아니 을 알 수 있습니다. 로 , 라이트 시안)는 "잔차"플롯 스트라이프 각도로 명백하다.( 0 , 79 )( 49 , 30 )
"잔여 물"그림의 얼룩은 명백한 고립 된 지역 특이 치를 나타냅니다. 이 그림에는 기본 데이터에 기인 한 다른 구조 (예 : 대각선 줄무늬)도 표시됩니다. 지리 통계적 방법을 통해 데이터의 공간 모델을 사용하여이 절차를 개선 할 수 있지만,이를 설명하고 설명하면 여기에 너무 멀어 질 수 있습니다.
BTW,이 코드는 찾아보고 의 도입 이상치. 이것은 절차의 실패가 아닙니다. 특이 치가 정규 분포로 분포 되었기 때문에 그 중 절반은 크기가 이상인 기본 값과 비교하여 크기 가 0에서 가깝 거나 너무 작아서 표면에서 감지 할 수있는 변화가 없었습니다. 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")