앞서 Z 값과 수정된 Z값을 이용해서 이상치를 제거하는 방법을 설명해봤습니다. 그런데 앞서 포스트에서 사분범위 (IQR: Interquartile range)에서 크게 벗어난 값을 이상치로 설정하는 방법에 대해서도 언급한 바 있습니다. Q3+1.5xIQR과 Q1-1.5xIQR이 그것입니다.
사실 정규 분포를 따르더라도 표본 수가 많아지면 Q3+1.5xIQR과 Q1-1.5xIQR를 벗어나는 값도 같이 많아지기 때문에 그만큼 이상치로 보는 숫자가 점점 많아진다는 점도 고려해야 합니다. 사분범위를 이용한 방법과 앞서 Z값 3을 기준으로 삼는 방법 간의 차이점을 우선 비교하고 다음 예제로 넘어가겠습니다.
(Boxplot (with an interquartile range) and a probability density function of a Normal N(0,σ2) Population. 출처: wikipedia)
예제는 앞서와 같이 3000개 표본으로 하겠습니다.
set.seed(1234)
x<-rnorm span="">-rnorm>
plot(x)
x
IQR 이상값을 자동으로 찾는 함수를 만드는 코드를 구글링을 통해서 찾았습니다.
removeOutliers = function(x) {
# Get Q1 and Q3
qnt = quantile(x, probs=c(.25, .75))
# Get the interquartile range time 1.5
iqt = 1.5 * IQR(x)
# Apply on a copy of the original data
y = x
y[x < (qnt[1] - iqt)] = NA
y[x > (qnt[2] + iqt)] = NA
# Remove incomplete cases and return the resulted variable
return(y[complete.cases(y)])
}
이는 이상치를 자동으로 제거해주는 코드입니다. 만약 결측값을 그대로 두고 싶다면 마지막 줄을 수정하면 될 것 같습니다. 코드가 복잡하지 않으므로 잘 보면 어떤 식으로 작동하는지 이해하기 쉬울 것입니다.
removeOutliers = function(x) {
# Get Q1 and Q3
qnt = quantile(x, probs=c(.25, .75))
# Get the interquartile range time 1.5
iqt = 1.5 * IQR(x)
# Apply on a copy of the original data
y = x
y[x < (qnt[1] - iqt)] = NA
y[x > (qnt[2] + iqt)] = NA
# Remove incomplete cases and return the resulted variable
return(y)
}
y<-removeoutliers span="" x="">-removeoutliers>
sum(is.na(y))
> y<-removeoutliers span="" x="">-removeoutliers>
> sum(is.na(y))
[1] 27
27개의 결측값은 앞서 예제에서보다 훨씬 많습니다. 대략적으로 전체 값의 1%가 조금 안되는 값이 이상치로 분류되어 제거된 셈인데, 사실 모든 값들이 정규 분포를 따르고 제거할 필요가 없는 값이라는 점을 생각하면 좀 과도하게 제거된 것일 수도 있습니다. 하지만 표본의 100개 이하로 좀 작다면 무리 없이 적용할 수 있을 것입니다.
그러면 다음에는 각 방법의 차이점을 비교해 보겠습니다.
댓글
댓글 쓰기