더북(TheBook)

이번에는 조금 더 복잡하지만 더 실제적인 상황을 다뤄보자. 아이리스 내 일부 데이터가 결측치일 때, 결측치를 해당 종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를 중앙값으로 치환한 것이다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.