더북(TheBook)

데이터 프레임에서 조건에 따른 행의 검색과 데이터 테이블에서 색인을 사용한 검색 속도를 비교해보자. 다음은 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)가 사용된다.

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