data.table 기초 문법

data.table 문법, 연산자, 함수
data.table
R
Published

January 18, 2023

1. data.table 소개

data.table은 R의 data.frame을 상속하여 만들어진 패키지입니다. 그렇기 때문에 대괄호([])를 쓰는 등의 문법은 대체로 data.frame과 비슷합니다. 그러나 data.table은 기존의 data.frame과 다른 장점을 갖고 있습니다.

data.table의 장점은 다음과 같습니다.

  • 매우 빠른 속도

    data.table은 기본 data.frame 구조보다 훨씬 빠르게 데이터를 연산합니다.

    require(data.table)
    require(dplyr)
    require(microbenchmark)
    data('storms')
    df_test <- function(){
      aggregate(x=storms[,c('wind','pressure')],
                by = list(storms$name,storms$year, storms$month,storms$day),
                FUN = mean)
    }
    
    dplyr_test <- function(){
      storms %>% 
        group_by(name, year, month, day) %>% 
        summarise(wind=mean(wind), pressure=mean(pressure),
                  )
    }
    storm_dt <- as.data.table(storms)
    dt_test <- function(){
      storm_dt[,.(wind=mean(wind), pressure=mean(pressure)), by=.(name, year,month,day)]
    }
    
    microbenchmark(df_test(), dplyr_test(), dt_test(), times=10)

    위는 각각 data.frame, dplyr, data.table로 동일한 결과를 불러오도록 실행했을 때 걸린 시간입니다. data.table의 결과가 최소 10배는 더욱 빠른 것을 알 수 있습니다.

  • 효율적인 메모리 처리

    data.table은 다른 데이터 패키지보다 효율적으로 데이터연산을 처리합니다. 그렇기 때문에 메모리 사용에 있어서도 더 적은 양으로 더 빠르게 계산을 진행합니다.

  • 낮은 패키지 의존성

    패키지 의존성이라는 것은 특정 패키지를 불러오기 위해 또다른 패키지를 불러오는 것입니다. 우리가 배울 data.table은 R 사용자들에게 자주 활용되는 tidyverse 계열의 dplyr패키지보다 의존성이 훨씬 낮습니다. 그렇기 때문에 번거롭게 하나의 패키지를 사용하기 위해 다른 패키지들을 설치해줄 필요가 없습니다.

    dplyr vs data.table 패키지 의존성 비교

2. data.table 함수

data.table 패키지에는 data.table에서 사용할 수 있는 고유의 함수들이 존재합니다. 여기서는 우선 앞으로 사용할 데이터를 불러오고 설정하기 위한 함수들을 우선 배워봅시다.

  • fread(): f(ast) + read의 의미입니다. 말그대로 빠르게 데이터를 불러오는 것(read)을 의미합니다. .csv, .txt 등의 확장자 이름을 가진 파일들을 불러올 수 있습니다.
require(NHANES)
dt <- as.data.table(NHANES)

fread()를 통해 불러온 파일의 classdata.table입니다.

class(dt)
[1] "data.table" "data.frame"

data.table을 출력했을 때, data.frame과 다른 점은 크게 두 가지가 있습니다.

data.table은 우선 모든 column에 대해 첫 5개, 마지막 5개의 행을 출력합니다.

또한 행의 번호에 :가 붙어 출력됩니다.

  • fwrite(): f(ast) + write 입니다. 말그대로 빠르게 데이터를 저장(write)합니다. .csv, .txt 등의 확장자 파일로 저장할 수 있습니다.
  • setnames(): column 이름을 사용자가 알아보기 쉽게끔 변경해야 할 때가 있습니다. setnames()는 column의 이름을 변경하는 함수입니다. column의 이름을 하나만 바꾸고 싶은 경우에는 문자열 하나만 넣어주면 되고, 여러 개의 column 이름을 동시에 변경할 때는 문자 벡터를 넣어주면 됩니다.
# 하나의 column 이름을 변경할 때
setnames(dt, old='Gender', new='gender')

# 여러 개의 column 이름을 동시에 변경할 때
setnames(dt,
         old = c('Age','Race1','Education'),# 바꿔줄 기존의 column 이름
         new = c('age','race','education') # 새로운 column 이름
         )
  • data.frame 등을 data.table로 변경하기

    새롭게 파일을 불러오는 것 뿐만 아니라 기존의 data.framedata.table 형태로 변경해줄 수 있습니다.

    setDT() : 영구적으로 data.table 형태로 저장합니다. 저장된 값을 따로 출력하지는 않습니다.

    setDT()

    as.data.table() : 일시적으로 data.table 형태로 출력합니다. 출력된 데이터가 저장되지는 않습니다.

    require(data.table)
    head(as.data.table(iris))

3. i: data.table 행

data.table에서 행(row)을 다루는 부분을 i 라고 부릅니다 (왜 i가 된건지는 모르겠습니다).

data.table에서 행을 다룬다는 것은 특정한 조건을 만족하는 행들을 추출 또는 선택(filtering)한다는 것과 같습니다.

자, 이제 data.table에서 행을 다루는 방법을 살펴보겠습니다.

1) 논리 연산자를 이용한 row filtering

data.frame 의 행을 다루는 부분에서도 배웠지만, 기본적으로 i에서는 논리 연산자를 이용해 행을 선택합니다. 논리 연산자의 조건을 만족하는 행들, 즉 논리 연산자의 실행 결과가 TRUE 인 행들만 추출하는 것입니다.

dt[age>=30] |> head()
dt[gender=='male' & age>=45] |> head() # 남성이고 45세 이상
dt[gender=='female' | age>=50] |> head() #여성 또는 50세 이상

이처럼 &|를 붙여주면, 여러 조건을 사용하여 원하는 행들을 추출할 수 있습니다.

행을 다룰 때 data.table과 data.frame의 차이점

data.frame과 달리 data.table 문법에서는, 대괄호 안에서 column을 df$var 양식으로 사용하지 않아도 됩니다. 그냥 column의 이름만 사용하면 됩니다.

또한 data.frame에서는 행 부분을 입력할 때, 꼭 , 를 붙여줘야 했습니다. 그러나 data.table의 경우 행만 filtering 할 때, 굳이 ,을 붙여줄 필요가 없습니다.

어떤가요? data.table이 훨씬 더 간단하죠? 😃

2) Infix 연산자를 이용한 row filtering

data.table에서는 논리 연산자 뿐만 아니라 infix 연산자를 이용하여, 조건을 충족시키는 행을 선택할 수 있습니다. 파이프 연산자 역시 조건을 만족하는 경우인 TRUE 에 해당하는 값들만 선택합니다.

Note

infix 연산자는 함수 피연산자의 양쪽에 있는 인수에 계산을 적용하는 기능을 제공합니다.

  • A %in% B: A가 B 안에 있는지 확인합니다. 이 때 B는 vector가 옵니다. 문자를 확인하는 경우에는 %chin% 을 이용해 더욱 빠르게 계산할 수 있습니다.

    dt[race %in% c('Black','White')] |> head()
  • A %like% B: A가 B와 비슷한지 확인합니다. 이 때 B에는 보통 문자열(character)이 옵니다.

    dt[MaritalStatus %like% 'Married'] |> head()
  • A %between% B: A가 B 사이에 있는지 확인합니다. 이 때 B는 c(0,10)과 같은 범위로 지정합니다.

    dt[BMI %between% c(20,25)] |> head()
    Tip

    위에서 소개해드린 %%을 이용한 infix 연산자 말고도 data.table 패키지 내의 함수를 이용할 수도 있습니다.

    %between%between()

    %like%like()

    # 예시
    dt[like(race,'ite')]