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

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