Patrick's 데이터 세상
데이터 마트 - 데이터 테이블 본문
데이터 테이블(data.table)은 데이터 프레임과 유사하지만 보다 빠른 그룹화(grouping)와 순서화(ordering), 짧은 문장 지원 측면에서 데이터 프레임보다 매력적이다.
하지만 무조건 빠른 것이 아니므로 특성에 맞게 사용해야 한다.
특히 64비트 환경에서 RAM이 충분히 많을 때는 효율적이다.
install.packages("data.table")
library(data.table)
data.table() 함수를 이용하여 데이터 프레임을 생성.
DT = data.table(x=c("b","b","b","a","a"), v=rnorm(5)) # 정규분포에서 5개의 난수 생성
DT
#Result
data.table도 data.frame과 같은 방법으로 생성된다.
데이터 프레임과 다른 점은 데이터 테이블은 행 번호가 콜론(;)으로 프린트되어 있어 첫 번째 열과 눈으로 쉽게 분리해서 볼 수 있다.
또한 기존의 데이터 프레임 형식의 객체(데이터)를 데이터 테이블 형식으로 쉽게 변환할 수 있다.
data(cars)
head(cars)
#Result
데이터 프레임으로 된 데이터를 데이터 테이블 형식으로 불러온다.
데이터 프레임을 데이터 테이블로 전환해 별도 이름으로 저장한다.
CARS <- data.table(cars)
head(CARS)
#Result
생성된 데이터 테이블 형식의 데이터(CARS와 DT)를 살펴보기 위해 tables() 기능을 이용해 크기가 어떠한지, key는 있는지, 용량은 얼만지 확인한다.
tables()
#Result
sapply(CARS,class)
#Result
DT
#Result
DT[2,]
#Result
DT[DT$x=="b",] # x값이 b인 데이터 조회
#Result
데이터 테이블에 key를 지정해 해당 값으로 표시해 보자.
setkey(DT,x)
DT
#Result
데이터 프레임에서와는 달리 표시 순서가 x에 의해 ordering된 것을 알 수 있다.
더불어 tables()에서 key가 x로 설정됐으며, 전체 용량이 0MB라는 것을 알 수 있다.
tables()
#Result
"b"가 들어간 모든 데이터를 표시하고 싶은 경우와, 첫 번째 결과, 마지막 결과, 모든 결과를 표시하는 옵션을 보여준다.
DT["b",] # 검색 조건 다음의 ","는 선택사항이다. DT["b"]와 같은 결과이다.
#Result
DT["b",mult="first"]
#Result
DT["b",mult="last"]
#Result
4개의 컬럼으로 이루어진 1000만 건 자료의 데이터 프레임
grpsize <- ceiling(1e7/26^2) # 천만개의 행과 676개 그룹
tt <- system.time(DF <- data.frame(
x=rep(LETTERS, each=26*grpsize),
y=rep(letters, each=grpsize),
v=runif(grpsize*26^2),
stringAsFactors=FALSE)
)
tt
#Result
x는 R, y는 h를 갖는 데이터 프레임 DF에서 자료를 찾는데 시간이 다소 걸린다.
1000만 건에서 특정 조건을 만족하는 데이터를 메모리에서 검색해 빠르게 보여줬지만, 하나하나 모든 자료를 비교해 찾는 벡터 검색 방식이라서 매우 비효율적이다.
기본적으로 R은 이러한 방식으로 개발됐다.
head(DF, 3) # 앞 3줄 조회
tail(DF, 3) # 뒤 3줄 조회
dim(DF) # 행, 열 개수 조회
10000068 / 3.323 # 3,009,349 rows per seconds
tt<-system.time(ans1 <- DF[DF$x=="R" & DF$y=="h",])
tt
#Result
데이터 테이블로 변환하여 똑같은 그룹을 추출한다.
데이터 테이블에서 동일한 작업을 수행하면, 대략 100배 정도 빠르다.
index를 이용한 바이너리 검색(binary search)을 하기 때문이다. 1,440분(1일) 소요될 일이 15분 이내에 완료된다면 동일한 작업을 하루에도 수십 번 할 수 있다.
DT <- data.table(DF)
setkey(DT,x,y)
ss <- system.time(ans2<-DT[J("R","h")]) # binary search
head(ans2,3)
#Result
dim(ans2)
#Result
identical(ans1$v, ans2$v)
#Result
ss
#Result
그러나 데이터 테이블을 데이터 프레임처럼 사용하면 성능은 비슷해진다.
즉, 데이터 테이블을 사용한다고 무조건 빨라지는 것은 아니다.
# bad case for using data.table
system.time(ans2 <- DF[DF$x=="R" & DF$y=="h",])
#Result
mapply(identical, ans1, ans2)
#Result
이전까지 DT[...] 안의 첫 번째 인수(argument), 즉 i에 대해서 알아보았다.이제부터 두 번째와 세 번째 인수, 즉 j와 by에 대해 알아보자.
데이터 테이블 summary
DT[,sum(v)]
#Result
x를 기준으로 summary
DT[,sum(v), by=x]
#Result
ttt <- system.time(tt <- tapply(DT$v,DT$x,sum));ttt
#Result
sss <- system.time(ss <- DT[,sum(v),by=x]);sss # 18.5x faster
#Result
데이터 테이블에서의 by는 빠르다.
tapply와 비교해보자.
데이터 테이블에서의 0.187초는 tapply를 적용했을 때의 3.469초보다 빠르다.
head(tt)
head(ss)
identical(as.vector(tt),ss$V1)
summary 또는 grouping을 x와 y 변수를 이용하고자 하는 경우 by="x,y"와 같은 표현방식으로 처리하면 된다
sss <- system.time(ss <- DT[,sum(v), by="x,y"]);sss;ss
#Result
'Programming > R' 카테고리의 다른 글
통계학 개론 (0) | 2020.06.25 |
---|---|
결측값 처리, 이상값 검색 (0) | 2020.06.25 |
데이터 마트 - plyr (0) | 2020.06.25 |
데이터 마트 - sqldf를 이용한 데이터 분석 (0) | 2020.06.25 |
데이터 마트 - R reshape (0) | 2020.06.25 |