data.table 1.14.9 업데이트

data.table 1.14.9 버전 업데이트 내용 살펴보기.
R
data.table
Published

February 21, 2023

data.table은 R에서 데이터를 빠르고 메모리 효율적으로 분석하도록 도와주는 패키지입니다. 현재 CRAN에 공개되어 있는 data.table 의 버전은 1.14.8 버전입니다 (2023-02-21 기준).

github에서 개발 중인 (거의 개발이 마무리되어가고 있습니다) data.table 1.14.9 버전은 꽤 많은 내용들이 업데이트되었는데요. 업데이트 사항들을 살펴보니 꽤 흥미로운 요소들이 많았습니다.

이번 글에서는 data.table 1.14.9 버전에서 유용하게 사용할 수 있는 추가 기능들을 소개해드리고자 합니다.

패키지 업데이트

현재 개발 중인 1.14.9 버전을 사용하기 위해선 CRAN이 아니라, github에서 개발 중인 패키지를 다운로드 받아야 합니다.

# remotes::install_github('Rdatatable/data.table')
data.table::update_dev_pkg()
R data.table package is up-to-date at 88039186915028ab3c93ccfd8e22c0d1c3534b1a (1.14.9)
library(data.table)

아래와 같은 메시지가 뜨면 정상적으로 설치된 것 입니다.

data.table 1.14.9 IN DEVELOPMENT built 2023-02-21 01:19:16 UTC; user using 12 threads (see ?getDTthreads).  Latest news: r-datatable.com

주요 업데이트 내용

새로운 버전에서 추가됐거나 변경된 점들 중, (주관적인) 유용한 부분에 대해 살펴보겠습니다!

데이터 유형 출력

이전까지 data.table 유형의 데이터를 출력했을 때, 각 열의 데이터 유형을 알 수 없었습니다. 그래서 str() 등을 통해 확인해야만 했었죠.

이제 data.tabletibble처럼 열별로 데이터 유형을 쉽게 확인할 수 있습니다.

iris |> as.data.table() |> head()

# 이전
#    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1:          5.1         3.5          1.4         0.2  setosa
# 2:          4.9         3.0          1.4         0.2  setosa
# 3:          4.7         3.2          1.3         0.2  setosa
# 4:          4.6         3.1          1.5         0.2  setosa
# 5:          5.0         3.6          1.4         0.2  setosa
# 6:          5.4         3.9          1.7         0.4  setosa

# 1.14.9
#    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#           <num>       <num>        <num>       <num>  <fctr>
# 1:          5.1         3.5          1.4         0.2  setosa
# 2:          4.9         3.0          1.4         0.2  setosa
# 3:          4.7         3.2          1.3         0.2  setosa
# 4:          4.6         3.1          1.5         0.2  setosa
# 5:          5.0         3.6          1.4         0.2  setosa
# 6:          5.4         3.9          1.7         0.4  setosa
Tip

이전 버전에서도 data.table 의 열 유형을 확인하는 것이 가능합니다. options()를 통해 아래와 같이 설정해주시면 됩니다.

options(datatable.print.class=TRUE)

DT()

DT(i, j, by, …) 라는 형태의 함수가 추가되었습니다. data.table의 함수적 형태라고 볼 수 있겠습니다.

기존에는 [i, j, by,...] 처럼 [] 을 이용했는데, 이를 위해서는 데이터가 항상 data.table 이어야 했습니다. 하지만 DT() 를 이용한다면 data.table이 아니어도 data.table 문법을 활용할 수 있게 되었습니다.

mtcars |> DT(hp>100, .(mean_mpg = mean(mpg)), by=.(cyl))

env

프로그래밍 인터페이스가 새롭게 추가되었습니다. 파라미터들을 통해 계산에 사용할 column, 새롭게 정의할 column의 이름은 물론 함수의 이름까지 활용할 수 있게 되었습니다. 이 기능은 env 인자를 통해 활용 가능합니다.

dt <- data.table(x = 1:5, y = 11:15, z = c('A','A','B','C','B'))

dt[,.(out_colname = fun(in_colname, fun_arg1 = fun_arg1_val)), by=group,
   env = list(
     out_colname = "mean_x",
     fun = "mean",
     in_colname = "x",
     fun_arg1 = "na.rm",
     fun_arg1_val = T,
     group = "z"
   )]

env 를 활용한 프로그래밍 인터페이스는 주로 사용자 정의 함수를 활용할 때 사용할 것 같습니다. 사용자 정의 함수에서 파라미터들을 문자열로 넣어주기 때문에, env는 굉장히 편리하게 사용할 수 있을 것으로 보입니다.

%notin%

data.table의 infix 연산자 (%%가 들어간 연산자) 중 새로운 녀석이 추가되었습니다. 바로 %notin%입니다. 기존에 있던 %in% 연산자는 A %in% B 형태로 쓰여, 해당 변수(열)에 특정 값이 있는지 확인할 수 있었습니다. %in% 의 부정형을 사용하기 위해서는 변수 앞에 !을 붙여줘야 했었죠. 이제는 %notin%을 통해 더 직관적으로 그 의미를 이해할 수 있게 되었습니다.

# 기존 방식
as.data.table(iris)[!Species %in% 'setosa',.N, by=.(Species)]
# 1.14.9 버전
as.data.table(iris)[Species %notin% 'setosa',.N, by=.(Species)]

let()

column을 reference에서 변경하기 위해 사용하던 := 의 별명함수(alias)가 생겼습니다. 바로 let() 입니다.

DT = data.table(A = 1:5)

# 기존 방식
DT[, B := 6:10]

# 새로운 방식
DT[, let(C = LETTERS[1:5],
         D = letters[1:5])]
DT

let()의 등장으로 =:= 을 헷갈려 하시는 분들의 어려움을 해소하는 데 도움이 될 것 같습니다.

fifelse()

fifelse()를 사용할 때 NA와 다른 유형의 데이터가 생성될 수 있게끔 변경되었습니다. 기존에는 fifelse()에서 true, false 인자에 들어가는 값에 NA가 들어가면 에러 메시지가 떴습니다. 하지만 1.14.9 버전부터는 해당 에러메시지가 뜨지 않고, 정상적으로 잘 출력됩니다.

as.data.table(airquality)[,fifelse(Solar.R < 300, NA, Solar.R)]

# 이전 버전
# Error in fifelse(Solar.R < 300, NA, Solar.R) : 
#   'yes' is of type logical but 'no' is of type integer. Please make sure that both arguments have the same type.

# 1.14.9 버전
# [1]  NA  NA  NA 313  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA 334 307  NA 322  NA
#  [21]  NA 320  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
#  [41] 323  NA  NA  NA 332 322  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
#  [61]  NA  NA  NA  NA  NA  NA 314  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
#  [81]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
# [101]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
# [121]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
# [141]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

.I의 사용

.Iby에 사용함으로써, 행 단위(rowwise) 계산이 가능해졌습니다.

예전에 여러 열들을 행별로 계산하기 위해서는 rowSums()rowMeans() 등을 활용했었는데 이제 더 간단하게 계산할 수 있게 되었습니다.

library(ggplot2)

# 이전 활용
a=as.data.table(diamonds)[,.(sum = rowSums(.SD)),.SDcols=depth:z]

# 1.14.9 버전
b=as.data.table(diamonds)[,.(sum = sum(.SD)),.SDcols=depth:z, by=.I]

microbenchmark()를 이용해 두 코드의 성능을 확인해보니, rowSums()를 활용하는 게 더 빠른 것으로 나타났습니다.

microbenchmark::microbenchmark(
  list =  list(
    previous = a,
    post = b
  ),
  times = 10
)

지금까지 data.table 1.14.9 버전의 주요한 내용들에 대해 살펴보았습니다. 더 많은 내용은 아래 레퍼런스를 통해 살펴보시기 바랍니다!

레퍼런스

Back to top

Footnotes

  1. https://rdatatable.gitlab.io/data.table/news/index.html↩︎

  2. https://rdatatable.gitlab.io/data.table/news/index.html↩︎