데이터 프레임에서 조건에 따른 행의 검색과 데이터 테이블에서 색인을 사용한 검색 속도를 비교해보자. 다음은 x에 연속 균등 분포Uniform Distribution를 따르는 난수 값을, y에 각 알파벳을 10,000회씩 반복한 값을 저장한 데이터 프레임에서 y 값이 C인 행들을 선택하는 예다.

    > DF <- data.frame(x=runif(260000), y=rep(LETTERS, each=10000))
    > str(DF)
    'data.frame': 260000 obs. of 2 variables:
     $ x: num 0.1405 0.0378 0.8146 0.3096 0.9899 ...
     $ y: Factor w/ 26 levels "A","B","C","D",..: 1 1 1 1 1 1 1 1 1 1 ...
    > head(DF)
               x y
    1 0.14046554 A
    2 0.03776698 A
    3 0.81462321 A
    4 0.30959019 A
    5 0.98985253 A
    6 0.24352429 A
    > system.time(x <- DF[DF$y=="C", ])
      user system elapsed
      0.09   0.00    0.09
    

    system.time( )을 사용해 평가한 결과를 보면 총 소요 시간elapsed은 0.09초로 나타났다.7 이 값이 특별히 크다고 할 수는 없으나 데이터양이 많다면 얼마든지 더 많은 시간이 걸릴 수 있다.

    이를 해결하는 방법은 y 값에 대해 미리 색인8 을 만들어두었다가 y 값을 사용한 검색 시 색인을 사용하는 것이다. 색인을 만드는 일에도 시간이 소요되기는 하지만 데이터 검색 횟수가 많다면 결과적으로 많은 속도 향상을 이룰 수 있다. 색인은 setkey( ) 함수로 생성하며, 색인을 사용한 검색에는 J( )를 사용한다. 다음은 y 값이 C인 행들을 데이터 테이블과 색인을 사용해 선택하는 예다.

    > DT <- as.data.table(DF)
    > setkey(DT, y)
    > system.time(x <- DT[J("C"), ])
      user system elapsed
      0.01   0.00    0.02
    

    색인을 사용하면 총 소요 시간이 0.02초로 훨씬 빨라진 것을 볼 수 있다. 만약 여러 컬럼을 키로 만들어둬야 한다면 setkey(DT, 컬럼명 1, 컬럼명 2, …) 형태로 다수의 키를 지정할 수 있으며 J(컬럼명 1, 컬럼명 2, …) 형태로 키를 나열해 데이터를 검색하면 된다.

    특히 데이터 테이블의 두 번째 인자는 컬럼명을 사용한 표현식이 될 수 있으므로 검색과 동시에 계산을 수행할 수 있다. 다음 예는 y 값이 C인 행들을 찾은 뒤 x의 평균을 구한 결과다.

    > DT[J("C"), mean(x)]
       y        V1
    1: C 0.5033286
    

    여러 계산 결과를 원한다면 list( ) 안에 표현식을 나열한다. 이때 tag=value 형태로 표현식을 적으면 결과의 컬럼명을 지정할 수 있다. 다음은 y가 C인 행들을 찾고 이들의 평균(x_mean)과 표준 편차(x_std)를 계산한 예다.

    > DT[J("C"), list(x_mean=mean(x), x_std=sd(x))]
       y    x_mean     x_std
    1: C 0.5033286 0.2904743
    

    7 system.time( )에 대해서는 이 장의 뒤에서 자세히 다룬다. 여기서는 주어진 명령의 총 소요 시간을 elapsed 컬럼을 읽어 알 수 있다는 점만 알고 넘어가도록 하자.

    8 이진 탐색 트리(binary search tree)가 사용된다.

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