이번에는 조금 더 복잡하지만 더 실제적인 상황을 다뤄보자. 아이리스 내 일부 데이터가 결측치일 때, 결측치를 해당 종Species의 중앙값으로 바꾸는 예다.
> data(iris) > iris[1, 1] = NA > iris Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 NA 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa ... > median_per_species <- sapply(split(iris$Sepal.Length, iris$Species), median, na.rm=TRUE) > iris <- within(iris, { + Sepal.Length <- ifelse(is.na(Sepal.Length), median_per_species[Species], Sepal.Length) + }) > iris Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.0 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa ...
종별 중앙값 median_per_species를 구하는 sapply( ) 부분이 조금 복잡하므로 풀어서 살펴보자. sapply( ) 안에서 사용한 split( )은 Sepal.Length를 Species별로 나누는 역할을 한다.
> split(iris$Sepal.Length, iris$Species)
$setosa
[1] NA 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1 5.4 5.1 4.6 5.1
...
$versicolor
[1] 7.0 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 5.0 5.9 6.0 6.1 5.6 6.7 5.6 5.8 6.2 5.6 5.9 6.1 6.3 6.1
...
$virginica
[1] 6.3 5.8 7.1 6.3 6.5 7.6 4.9 7.3 6.7 7.2 6.5 6.4 6.8 5.7 5.8 6.4 6.5 7.7 7.7 6.0 6.9 5.6 7.7 6.3
...
split( )의 결과에서 Species별 중앙값을 구하기 위해 sapply( )로 median( )을 호출하되, median( ) 호출 시 na.rm=TRUE를 추가적인 인자로 넘겨준다.
> sapply(split(iris$Sepal.Length, iris$Species), median, na.rm=TRUE)
setosa versicolor virginica
5.0 5.9 6.5
within( )은 이 결과를 사용해 NA를 중앙값으로 치환한 것이다.